Skip to content

fix(manage-ui): fix URL validation bypass and permission guard in credential provider setup#2776

Merged
omar-inkeep merged 4 commits intomainfrom
fix/url-validation-bypass
Mar 20, 2026
Merged

fix(manage-ui): fix URL validation bypass and permission guard in credential provider setup#2776
omar-inkeep merged 4 commits intomainfrom
fix/url-validation-bypass

Conversation

@omar-inkeep
Copy link
Copy Markdown
Contributor

@omar-inkeep omar-inkeep commented Mar 19, 2026

Summary

  • URL validation bypass: Reorder Zod schema construction in generic-auth-form.tsx so custom validators (e.g. URL protocol allowlist blocking javascript: URLs) are chained after the required/optional base schema instead of being silently overwritten by it.
  • Permission guard: Move all React hooks above the canEdit early-return guard in the provider setup page to satisfy the Rules of Hooks. Each hook body now checks canEdit internally, and the return null guard prevents rendering write controls for unauthorized users.

🤖 Generated with Claude Code

…dential provider setup

Reorder Zod schema construction so custom validators (e.g. URL protocol
allowlist) are chained after required/optional base schema instead of
being overwritten. Move all React hooks above the canEdit early-return
guard to satisfy Rules of Hooks, with canEdit checks inside hook bodies.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 19, 2026

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

Project Deployment Actions Updated (UTC)
agents-api Ready Ready Preview, Comment Mar 20, 2026 2:29pm
agents-manage-ui Ready Ready Preview, Comment Mar 20, 2026 2:29pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
agents-docs Skipped Skipped Mar 20, 2026 2:29pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 19, 2026

🦋 Changeset detected

Latest commit: 882d78e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@inkeep/agents-manage-ui Patch
@inkeep/agents-api Patch
@inkeep/agents-cli Patch
@inkeep/agents-core Patch
@inkeep/agents-email Patch
@inkeep/agents-mcp Patch
@inkeep/agents-sdk Patch
@inkeep/agents-work-apps Patch
@inkeep/ai-sdk-provider Patch
@inkeep/create-agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pullfrog
Copy link
Copy Markdown
Contributor

pullfrog Bot commented Mar 19, 2026

TL;DR — Fixes two bugs in the credential provider setup flow: a Zod schema ordering issue that silently discarded custom URL validators, and missing canEdit permission guards that allowed read-only users to trigger credential mutations. Also adds server-side URL protocol validation as defense-in-depth.

Key changes

  • page.tsx permission guards — Adds canEdit checks to every useCallback and useEffect in ProviderSetupPage, and renders null instead of the form when the user lacks edit permission.
  • generic-auth-form.tsx schema fix — Moves the required/optional z.string() assignment before field.validate so the .refine() step is no longer overwritten by a plain z.string().
  • nango.ts server-side URL validation — Validates that app_link credentials use only http: or https: protocols via new URL() parsing, preventing protocol-smuggling attacks.

Summary | 4 files | 4 commits | base: mainfix/url-validation-bypass


Permission guard in ProviderSetupPage

Before: The canEdit redirect lived in a single useEffect, but all mutation callbacks (handleNangoConnect, startConnectFlow, handleCreateNewIntegration, handleUpdateCredentials, handleDeleteIntegration) and the auto-connect effect ran without checking permissions — a viewer could trigger credential writes if the redirect hadn't completed yet.
After: Every callback and effect bails early when !canEdit, and the component returns null before rendering any interactive UI for unauthorized users.

The provider lookup is also moved above the canEdit redirect effect so it's available for the guard checks that follow.

page.tsx


createFormSchema validation ordering in generic-auth-form.tsx

Before: The schema was built as z.string().refine(field.validate) → then unconditionally reassigned to z.string().min(1) or z.string().optional(), discarding the .refine() entirely. Custom validators (like URL format checks) never executed.
After: The base schema (z.string().min(1) or z.string().optional()) is constructed first, then .refine() is chained onto it — preserving both the required/optional semantics and the custom validation logic.

The .validate call inside the .refine() callback uses optional chaining (field.validate?.(stringValue)) for safety, even though the outer if (field.validate) guard already ensures presence.

generic-auth-form.tsx


Server-side URL protocol validation in buildCredentialsPayload

Before: app_link values in credential payloads were passed through without protocol validation — any URL scheme (e.g. javascript:, file:) could be submitted.
After: When app_link is a non-empty string, it is parsed with new URL() and only http: / https: protocols are allowed. Invalid protocols throw an error.

This serves as defense-in-depth alongside the client-side .refine() fix, ensuring malicious protocols are rejected even if the form validation is bypassed.

nango.ts

Pullfrog  | View workflow run | Triggered by Pullfrogpullfrog.com𝕏

Copy link
Copy Markdown
Contributor

@pullfrog pullfrog Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both fixes are correct and well-scoped.

URL validation bypass (generic-auth-form.tsx): The old code built a refined schema with .refine() for custom validators like validateUrl, then immediately reassigned fieldSchema to a fresh z.string().min(1, ...) or z.string().optional() — silently discarding the refine. The fix correctly sets up the base schema first, then chains .refine() on top. The refine callback handles undefined (from the optional schema) correctly via String(value || '').

Permission guard (page.tsx): All hooks remain unconditionally called at the top of the component. The if (!canEdit) return null guard is placed after every hook — no Rules of Hooks violation. Each useCallback/useEffect also short-circuits internally on !canEdit, preventing side effects for unauthorized users. The import migration from useProjectPermissionsQuery to useProjectPermissions (context-based) is a clean improvement.

Pullfrog  | View workflow runpullfrog.com𝕏

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(1) Total Issues | Risk: Low

This PR correctly fixes two issues:

  1. URL validation bypass — The Zod schema construction order is fixed so custom validators (like validateUrl blocking javascript: URLs) are chained via .refine() after the base schema instead of being silently overwritten.
  2. React Rules of Hooks — All hooks are now called unconditionally before any early returns, with canEdit guards moved inside each hook body.

Both fixes are implemented correctly and the security issue is properly addressed at the client-side validation layer.

💭 Consider (1) 💭

Inline Comments:

  • 💭 Consider: generic-auth-form.tsx:49 Redundant null check for field.validate inside its own guard block

🧹 While You're Here (1) 🧹

🧹 1) nango.ts:90-102 Missing server-side URL validation

Issue: The buildCredentialsPayload server action spreads untrusted credentials directly without validating the app_link field, allowing client-side validation to be bypassed entirely.

Why: While this PR fixes client-side validation, a determined attacker could call the server action directly with a javascript: URL. The stored payload could cause XSS if app_link is ever rendered in an anchor tag or similar context. This is a pre-existing issue that predates this PR.

Fix: Consider adding server-side validation in buildCredentialsPayload:

if (credentials.app_link && typeof credentials.app_link === 'string') {
  const url = new URL(credentials.app_link);
  if (!['http:', 'https:'].includes(url.protocol)) {
    throw new Error('Only HTTP and HTTPS URLs are allowed for app_link');
  }
}

Refs:


✅ APPROVE

Summary: The security fix is correctly implemented and the React hooks violation is properly resolved. The client-side validation bypass is closed. I'm flagging the pre-existing server-side validation gap as a "While You're Here" item — it's not blocking but worth considering for defense-in-depth. Ship it! 🚀

Discarded (2)
Location Issue Reason Discarded
page.tsx:70-74 Flash of content before redirect for unauthorized users Not a real issue — the return null guard at line 281 prevents any sensitive UI from rendering while redirect is pending. The security is correctly handled.
generic-auth-form.tsx:53 Generic error message discards specific validation messages from validateUrl Pre-existing UX issue not introduced by this PR; the PR scope is security, not error message improvements.
Reviewers (3)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
pr-review-standards 0 0 0 0 0 0 0
pr-review-frontend 2 0 0 0 1 0 1
pr-review-security-iam 2 0 0 1 0 0 1
Total 4 0 0 1 1 0 2

Comment thread agents-manage-ui/src/components/credentials/views/generic-auth-form.tsx Outdated
@github-actions github-actions Bot deleted a comment from claude Bot Mar 19, 2026
…ntialsPayload

Validate app_link against HTTP/HTTPS allowlist in the server action to
prevent bypassing client-side form validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(0) Total Issues | Risk: Low

This re-review covers the delta since the last automated review (69792a6251d1f717de959).

Delta Analysis

The new commit f717de959 adds server-side URL protocol validation in buildCredentialsPayload(), directly addressing the "While You're Here" item from the prior review about missing server-side validation.

Changes reviewed:

  • nango.ts:101-106 — New validation block that mirrors the client-side validateUrl implementation

Implementation quality:

  • ✅ Type checking before string operations (typeof credentials.app_link === 'string')
  • ✅ Whitespace handling (.trim() before parsing)
  • ✅ Protocol allowlist (http:, https: only)
  • ✅ Throws on invalid protocol to prevent bypass
  • ✅ Mirrors client-side validation logic for consistency

The server-side validation correctly prevents javascript: URLs and other dangerous protocols from being stored, closing the XSS vector identified in the prior review.

🕐 Pending Recommendations (1)

  • 💭 generic-auth-form.tsx:49 Redundant null check for field.validate inside its own guard block (prior review item, still unresolved but minor)

✅ APPROVE

Summary: The delta correctly implements server-side URL validation, addressing the security feedback from the prior review. The implementation is clean and consistent with the client-side validation. The one remaining "Consider" item is a minor code quality suggestion that doesn't affect functionality. Ship it! 🚀

Discarded (0)

No discarded findings.

Reviewers (1)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
orchestrator-manual 1 0 0 0 0 1 0
Total 1 0 0 0 0 1 0

Note: Delta review — only changes since 69792a6251d1 were analyzed. Sub-reviewers not dispatched for this small, well-scoped security fix.

…-form.tsx

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(0) Total Issues | Risk: Low

This re-review covers the delta since the last automated review (f717de959f3235b55e).

Delta Analysis

The new commit f3235b55e addresses the "Consider" suggestion from the prior review by removing the redundant null check.

Change reviewed:

  • generic-auth-form.tsx:49 — Removed field.validate ? ... : undefined ternary since we're already inside an if (field.validate) guard block

Before:

const error = field.validate ? field.validate(stringValue) : undefined;

After:

const error = field.validate(stringValue);

✅ This is the correct fix — the outer if (field.validate) guard at line 44 guarantees field.validate exists within the block, making the inner ternary redundant. The code is now cleaner and more readable.


✅ APPROVE

Summary: The delta addresses the prior review's "Consider" suggestion by removing the redundant null check. All prior feedback has been addressed — the URL validation bypass is fixed (client-side schema ordering + server-side protocol validation), the React Rules of Hooks violation is resolved, and the code quality suggestion is now applied. This PR is ready to ship! 🚀

Discarded (0)

No discarded findings.

Reviewers (1)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
orchestrator-manual 0 0 0 0 0 0 0
Total 0 0 0 0 0 0 0

Note: Delta review — only the 1-line change since f717de959 was analyzed. Sub-reviewers not dispatched for this trivial code quality fix.

@github-actions github-actions Bot deleted a comment from claude Bot Mar 19, 2026
@itoqa
Copy link
Copy Markdown

itoqa Bot commented Mar 19, 2026

Ito Test Report ✅

12 test cases ran. 12 passed.

🔍 Verified credential-provider routing, authorization guard behavior, URL-validation defenses, and responsive/edit-flow stability for the included cases. The included outcomes indicate expected behavior for authorized/unauthorized navigation, unsafe URL blocking, and key form interactions.

✅ Passed (12)
Test Case Summary Timestamp Screenshot
ROUTE-1 Authorized admin session loaded providers grid and successfully navigated to Custom Provider setup route with encoded providerId rendering an interactive form. 5:36 ROUTE-1_5-36.png
ROUTE-2 Deep-link to provider setup redirected to credentials index in simulated non-editor context. 9:43 ROUTE-2_9-43.png
ROUTE-4 Search term filtering narrowed results to GitHub, clearing restored all providers, and provider card navigation resolved correctly to an encoded providerId route. 5:37 ROUTE-4_5-37.png
LOGIC-1 Client validation rejects javascript: payload and prevents successful submission. 36:00 LOGIC-1_36-00.png
LOGIC-2 Valid HTTPS app_link passes client URL validation; no Invalid app link error is shown. 36:17 LOGIC-2_36-17.png
LOGIC-3 Malformed app_link input is rejected by client validation with explicit error state. 36:29 LOGIC-3_36-29.png
LOGIC-5 Validation behavior is trim-consistent: padded HTTPS is accepted while padded javascript: is rejected. 37:39 LOGIC-5_37-39.png
EDGE-2 After local bypass fallback for unavailable Nango integrations, rapid open/cancel/reopen dialog interactions with one confirm produced single-delete behavior and returned to a stable setup form without duplicate destructive action. 59:41 EDGE-2_59-41.png
EDGE-3 At 390x844, key form inputs and submit/cancel/navigation controls were visible and operable without action-blocking layout issues; provider list and setup navigation remained usable on mobile. 1:01:33 EDGE-3_1-01-33.png
ADV-1 All tested unsafe schemes (data, file, vbscript) are blocked by client validation. 37:53 ADV-1_37-53.png
ADV-3 Rapid interaction spam during redirect did not create credentials or trigger unauthorized actions. 9:44 ADV-3_9-44.png
ADV-4 Protocol-relative, encoded, mixed-case, and malformed-scheme payloads are all rejected by validation. 38:10 ADV-4_38-10.png
📋 View Recording

Screen Recording

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

(0) Total Issues | Risk: Low

This re-review covers the delta since the last automated review (f3235b55e882d78e1d).

Delta Analysis

The new commit 882d78e1d ("fix err") adds optional chaining to field.validate inside the .refine() callback.

Change reviewed:

  • generic-auth-form.tsx:49 — Changed field.validate(stringValue) to field.validate?.(stringValue)

Before:

const error = field.validate(stringValue);

After:

const error = field.validate?.(stringValue);

Assessment

This change is correct. While there's an outer if (field.validate) guard at line 44, the callback passed to .refine() is a closure that captures field. TypeScript's control flow analysis doesn't narrow types inside closures because the closure could theoretically be invoked at a different time when the narrowing is no longer valid.

The optional chaining:

  • Satisfies TypeScript's type checker (likely fixing a TS2722: Cannot invoke an object which is possibly 'undefined' error)
  • Has zero runtime cost (the guard already ensures field.validate exists when the callback is created)
  • Is a standard defensive pattern for closures in TypeScript

✅ APPROVE

Summary: The delta fixes a TypeScript type error by adding optional chaining for closure safety. All prior feedback has been addressed — the URL validation bypass is fixed (client-side schema ordering + server-side protocol validation), the React Rules of Hooks violation is resolved, and the code is type-safe. This PR is ready to ship! 🚀

Discarded (0)

No discarded findings.

Reviewers (1)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
orchestrator-manual 0 0 0 0 0 0 0
Total 0 0 0 0 0 0 0

Note: Delta review — only the 1-line change since f3235b55e was analyzed. Sub-reviewers not dispatched for this trivial TypeScript type fix.

@github-actions github-actions Bot deleted a comment from claude Bot Mar 20, 2026
@omar-inkeep omar-inkeep added this pull request to the merge queue Mar 20, 2026
Merged via the queue into main with commit eb3a4bb Mar 20, 2026
17 of 18 checks passed
@omar-inkeep omar-inkeep deleted the fix/url-validation-bypass branch March 20, 2026 14:45
@itoqa
Copy link
Copy Markdown

itoqa Bot commented Mar 20, 2026

Ito Test Report ❌

12 test cases ran. 2 failed, 10 passed.

Across 7 report shards, 12 test cases were executed with 10 passing and 2 failing, showing generally stable credential-provider flows including provider navigation/fallback for standard invalid IDs, whitespace-trimmed HTTPS App Link validation, interstitial edit/cancel stability, refresh/mobile/back-forward resilience, permission-based redirect behavior, and graceful stale multi-tab delete handling. The two most important findings are pre-existing defects: a high-severity race condition that allows rapid double-click on Create Credential to launch duplicate integration attempts, and a minor routing inconsistency where encoded slash providerId payloads bypass the in-flow “Provider not found” recovery UI and fall through to app-level 404 behavior.

❌ Failed (2)
Category Summary Screenshot
Adversarial 🟡 Encoded slash payloads bypass provider-level fallback and resolve via global 404 path. ADV-2
Edge ⚠️ Rapid double submit can trigger duplicate create attempts for the same provider flow. EDGE-2
🟡 Adversarial providerId path payloads
  • What failed: Expected in-flow "Provider not found." fallback UI for invalid provider IDs, but encoded slash payloads are handled before this component renders and show app-level not-found behavior instead.
  • Impact: Users deep-linking with malformed or slash-containing encoded IDs get an inconsistent error path and lose the contextual recovery UI ("Back to providers"). This degrades resilience and troubleshooting for invalid provider routes.
  • Introduced by this PR: No – pre-existing bug (code not changed in this PR)
  • Steps to reproduce:
    1. Open /default/projects/activities-planner/credentials/new/providers/%2E%2E%2F%2E%2E%2Fetc%2Fpasswd.
    2. Open /default/projects/activities-planner/credentials/new/providers/%3Cscript%3Ealert(1)%3C%2Fscript%3E.
    3. Observe that the in-flow "Provider not found." page does not render for these encoded slash payloads.
  • Code analysis: I reviewed provider route construction and provider setup resolution. The providers grid always writes providerId into a single dynamic segment, and the fallback UI exists only inside the matched page component after provider lookup, creating a gap for encoded slash payloads that do not reach this component.
  • Why this is likely a bug: The intended invalid-provider recovery UI is implemented in component logic that only runs after route match, so encoded slash payloads bypass that logic and produce inconsistent error handling for the same invalid-ID class.

Relevant code:

agents-manage-ui/src/components/credentials/views/nango-providers-grid.tsx (lines 116-122)

<CardGrid
  cardClassName="py-4 shadow-none rounded-lg"
  items={filteredProviders}
  getKey={(provider) => provider.name}
  getHref={(provider) =>
    `/${tenantId}/projects/${projectId}/credentials/new/providers/${encodeURIComponent(provider.name)}`
  }

agents-manage-ui/src/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page.tsx (lines 68-74)

const provider = providers?.find((p: ApiProvider) => encodeURIComponent(p.name) === providerId);

useEffect(() => {
  if (!canEdit) {
    router.replace(`/${tenantId}/projects/${projectId}/credentials`);
  }
}, [canEdit, router, tenantId, projectId]);

agents-manage-ui/src/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page.tsx (lines 289-299)

if (!provider) {
  return (
    <div className="flex flex-col items-center justify-center h-64 space-y-4">
      <h2 className="text-xl font-semibold">Provider not found.</h2>
      <p className="text-muted-foreground">
        The provider &quot;{decodeURIComponent(providerId)}&quot; was not found.
      </p>
      <Button asChild>
        <NextLink href={backLink}>Back to providers</NextLink>
      </Button>
⚠️ Rapid double submit creates duplicate integration attempts
  • What failed: Two create attempts can run concurrently and generate distinct integration keys instead of enforcing a single in-flight submission.
  • Impact: Users can unintentionally create duplicate integration attempts and inconsistent credential records from a single intended action. This increases operational cleanup risk and can trigger duplicate external auth/connect flows.
  • Introduced by this PR: No – pre-existing bug (code not changed in this PR)
  • Steps to reproduce:
    1. Navigate to a provider setup route that requires credential form input.
    2. Fill the required fields with valid values.
    3. Click Create Credential twice within roughly 100ms.
    4. Observe that two create attempts can proceed with distinct generated integration keys instead of deduping the submission.
  • Code analysis: The page submit path lacks a local dedupe lock before generating a new integration key, and loading is set only after awaiting organization fetch in startConnectFlow, which leaves a race window where a second submit is accepted.
  • Why this is likely a bug: Production submit logic allows multiple create invocations before the loading gate is activated, so duplicate operations are a direct consequence of code flow rather than test setup.

Relevant code:

agents-manage-ui/src/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page.tsx (lines 128-136)

const startConnectFlow = useCallback(
  async (integrationKey: string, credentials?: Record<string, any>) => {
    if (!canEdit || !provider) return;

    const { data: organizationData } = await authClient.organization.getFullOrganization();

    setLoading(true);
    setHasAttempted(true);

agents-manage-ui/src/app/[tenantId]/projects/[projectId]/credentials/new/providers/[providerId]/page.tsx (lines 183-190)

const handleCreateNewIntegration = useCallback(
  async (credentials?: Record<string, any>) => {
    if (!canEdit || !provider) return;

    const integrationKey = `${provider.name}-${tenantId}-${generateId().slice(0, 6)}`;

    await startConnectFlow(integrationKey, credentials);

agents-manage-ui/src/components/credentials/views/generic-auth-form.tsx (lines 205-214)

<div className="flex gap-3">
  <Button type="submit" disabled={loading}>
    {loading
      ? mode === 'update'
        ? 'Updating...'
        : 'Creating Credential...'
      : mode === 'update'
        ? 'Update Credentials'
        : 'Create Credential'}
✅ Passed (10)
Category Summary Screenshot
Adversarial Non-edit users are redirected from deep-linked provider setup to the credentials page, matching the implemented permission guard. ADV-1
Adversarial Multi-tab stale delete flow degrades gracefully without crashes or broken UI state. ADV-5
Edge Refresh during provider create flow returned to a usable setup form; inputs remained interactive after reload. EDGE-1
Edge Rapid Edit credentials -> Cancel toggling remained stable across repeated cycles. EDGE-3
Edge Mobile viewport setup flow stayed usable with visible controls and no horizontal clipping. EDGE-4
Edge Back/forward and in-page return paths resolved to correct routes with no persistent loading overlay. EDGE-5
Logic Trimmed HTTPS App Link is accepted by client validation and proceeds to submission. LOGIC-3
Happy-path Provider grid navigation to Slack setup route works and renders Create Credential form. ROUTE-1
Happy-path Invalid provider ID shows controlled fallback and Back to providers returns to grid. ROUTE-2
Happy-path Verified interstitial action menu wiring in provider setup (OAuth app actions -> Edit credentials). ROUTE-4

Commit: 882d78e

View Full Run


Tell us how we did: Give Ito Feedback

dimaMachina pushed a commit that referenced this pull request Mar 20, 2026
…dential provider setup (#2776)

* fix(manage-ui): fix URL validation bypass and permission guard in credential provider setup

Reorder Zod schema construction so custom validators (e.g. URL protocol
allowlist) are chained after required/optional base schema instead of
being overwritten. Move all React hooks above the canEdit early-return
guard to satisfy Rules of Hooks, with canEdit checks inside hook bodies.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* fix(manage-ui): add server-side URL protocol validation in buildCredentialsPayload

Validate app_link against HTTP/HTTPS allowlist in the server action to
prevent bypassing client-side form validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Update agents-manage-ui/src/components/credentials/views/generic-auth-form.tsx

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* fix err

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
github-merge-queue Bot pushed a commit that referenced this pull request Mar 30, 2026
* skill generator

* polish skill generator

* skills tests

* upd

* upd

* generation.test wip

* add generation.test

* tree node

* skill page

* skill loader

* skill loader refactor

* skill loader

* move skills sidebar to layout

* use pure monaco-editor component since we can have different file extension

* add shadcn context menu component

* format context menu

* skills files and edit pages

* dry

* update layout

* add docs

* add a changeset

* redirect to first skill

* skill files utils

* skill selector

* upd treenode

* skill files

* skill file editor

* delete skill confirmation

* add skill files actions

* skills data

* rm

* up skills route

* upd

* upd

* better project error message on dev

* types

* skill files

* skill loader

* format

* project test

* entities

* project full tests

* upd introspect

* upd cliiii

* nested skills tests

* remove edit page

* remove edit page

* update files page

* upd

* upd file editor

* add SkillFileInsertSchema

* superRefine

* add transform

* rm some cases in superRefine

* use pipe

* use pipe

* upd skill loader

* validation skills

* upd

* rm

* upd

* data access tests

* skills db changes

* add

* skill files

* upd

* upd

* upd skill update

* SkillUpdateSchema has required files

* upd skills manage

* upd

* upd layout and page

* style: auto-format with biome

* move empty state comp to page

* upd schemas

* update schemas

* move to with-sidebar

* polish

* upd

* upd skill generator

* Make webhooks docs user friendly (#2752)

* shaping a2a webhooks page

* moved triggers to visual builder

* vb webhooks wip

* numbered TOC steps

* added step circles

* indented toc steps more

* added newsletter signup to docs

* added share feedback button

* moved newsletter subscribe route to agent docs

* subscribe confirm polish

* improved spacing

* improved spacing

* added high quality images

* added verification step

* Sync lockfile after rebase

* Use tag reference for pullfrog action instead of pinned SHA (#2757)

The action is actively under development, so referencing the v0 tag
allows picking up updates automatically.

https://claude.ai/code/session_01QZyvEs97scVf1ahTG8C1rV

Co-authored-by: Claude <[email protected]>

* ci: provision PR preview environments in Railway (#2681)

* ci: add preview env diagnostics

* ci: probe preview env schema before deploy

* ci: probe preview env schema before deploy

* ci: harden preview api env defaults

* ci: attach git metadata to preview deploys

* ci: harden preview workflow operations

* ci: broaden preview log redaction

* ci: extract preview workflow scripts

* ci: harden preview script extraction

* fix(ci): correct Playwright cache restore-key prefix mismatch (#2760)

The restore-keys used `${{ runner.os }}-playwright-` but primary keys
used `playwright-${{ runner.os }}-`, so the prefix never matched on
cache miss, forcing a full browser download (~8.5 min) instead of a
cache restore (~13 sec).

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>

* fix(ci): replace full git clone with shallow checkout in CI job (#2761)

Remove fetch-depth: 0 from the ci job's checkout step, which cloned the
entire git history (1.5-5 min overhead). Only the OpenAPI change detection
step needs the base branch ref, so fetch it on-demand with --depth=1.

Also switches the diff from three-dot merge-base syntax to a two-dot
pathspec-filtered diff against the fetched base ref, which works correctly
with shallow clones.

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>

* format

* rm migration

* add new migrations

* validation for skill is ok

* move empty state to page

* delete skill

* delete skill revalidate path

* move skills schemas to own file

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* more typecheck fixes

* more typecheck fixes

* fix

* fix isRequired

* f1x

* move skill sidebar

* refactor skill sidebar

* add collapse file tree button

* upd

* upd

* upd

* deleteSkillFile

* upd

* deleteSkillFile

* fileId

* fileId

* upd schemas

* DeleteSkillFileConfirmation

* updateSkillFile

* rm simplematter from sdk

* Get Skill File

* getSkillFileById

* add new skill file page

* update skill file editor

* format

* Create Skill File

* upd

* createSkillFileAction

* createSkillFileById

* fix: Make OpenTelemetry startup idempotent (#2684)

* fix: Make OpenTelemetry startup idempotent

* fix: Re-export defaultSDK and cache NodeSDK instance on globalThis

Restores the export on defaultSDK to avoid breaking the
create-agents-template subpath import. Moves the new NodeSDK()
construction behind a globalThis guard (getOrCreateSDK) so
repeated Vite HMR module evaluations reuse the same instance instead
of leaking fresh SDK objects.

Co-authored-by: mike-inkeep <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix(template): use idempotent startOpenTelemetrySDK() in instrumentation

* fix: guard all OTel singletons behind globalThis for HMR idempotency

- Cache otlpExporter, batchProcessor, resource, instrumentations,
  spanProcessors, contextManager, and propagator on globalThis via
  Symbol keys and getOrCreate* helpers so HMR re-evaluation reuses
  existing instances instead of leaking new ones
- Make OtelGlobal type strict with per-key types, eliminating the
  loose `boolean | NodeSDK` union and the `as NodeSDK` cast
- Add logger.debug in the MetricReader catch block to distinguish
  clean idempotency from error-recovery idempotency
- Remove defaultSDK export (now module-private) since all consumers
  use startOpenTelemetrySDK() instead

* Fix type errors

* Simplify to just suppress the error since it's not an issue in prod, only local

* Limit to dev mode

* Add changeset for OTel HMR idempotency fix

Co-authored-by: Dimitri POSTOLOV <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: mike-inkeep <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: inkeep[bot] <257615677+inkeep[bot]@users.noreply.github.com>
Co-authored-by: Dimitri POSTOLOV <[email protected]>

* Fix scheduled trigger invocations being skipped (#2777)

* Fix scheduled trigger invocations being skipped when trigger is edited without changing the next execution time

* claude comments

* adding app id (#2779)

* Update pullfrog to latest SHA and add daily dependabot group for high-frequency deps (#2780)

* Update pullfrog to latest SHA and add daily dependabot group for high-frequency deps

- Update pullfrog from v0.0.178 SHA to v0.0.181 SHA (30d68e5) to stay on
  commit-pinned references for security (action has write permissions + 9 API keys)
- Split dependabot github-actions config into a "high-frequency" group for
  pullfrog with daily schedule, so SHA pins get updated automatically
- This supersedes PR #2757's approach of moving to mutable tag references

https://claude.ai/code/session_01D3ZGYHG8VhsZwqjjXqy2Ap

* Split dependabot github-actions into daily (pullfrog) and monthly (rest)

Separate into two ecosystem entries so pullfrog gets daily SHA updates
while other GitHub Actions stay on a monthly cadence.

https://claude.ai/code/session_01D3ZGYHG8VhsZwqjjXqy2Ap

* Fix invalid dependabot config: merge duplicate github-actions entries

Dependabot disallows duplicate ecosystem+directory pairs. Use a single
entry with two groups instead: high-frequency (pullfrog) and github-actions
(everything else via exclude-patterns).

https://claude.ai/code/session_01D3ZGYHG8VhsZwqjjXqy2Ap

---------

Co-authored-by: Claude <[email protected]>

* ci: seed preview auth in PR previews (#2775)

* ci: bootstrap preview auth

* ci: require secure preview auth config

* ci: recover preview auth runtime vars

* ci: install railway in preview bootstrap

* ci: provision preview db tcp proxies

* ci: proxy preview spicedb bootstrap

* ci: harden preview retry and error logging

---------

Co-authored-by: Andrew Mikofalvy <[email protected]>

* Fix scopes placeholder to show correct Nango format (#2784)

* Fix misleading scopes placeholder in credential form

The Nango API validates scopes against a strict comma-separated pattern
with no spaces. Updated placeholder and help text to show the correct
format and prevent 400 errors when users enter multiple scopes.

Made-with: Cursor

* Add changeset for scopes placeholder fix

Made-with: Cursor

* fix(manage-ui): fix URL validation bypass and permission guard in credential provider setup (#2776)

* fix(manage-ui): fix URL validation bypass and permission guard in credential provider setup

Reorder Zod schema construction so custom validators (e.g. URL protocol
allowlist) are chained after required/optional base schema instead of
being overwritten. Move all React hooks above the canEdit early-return
guard to satisfy Rules of Hooks, with canEdit checks inside hook bodies.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* fix(manage-ui): add server-side URL protocol validation in buildCredentialsPayload

Validate app_link against HTTP/HTTPS allowlist in the server action to
prevent bypassing client-side form validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Update agents-manage-ui/src/components/credentials/views/generic-auth-form.tsx

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* fix err

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* feat(pdf): Support PDF attachments (#2709)

* feat(pdf): Support PDF attachments

* Add tests and other review feedback

* Fix doc

* More renaming and cleanup

* refactor: extract Vercel content part schemas to types/chat.ts for reuse

Move inline Zod schemas from chatDataStream.ts and message-parts.ts into
types/chat.ts as shared, exported schemas. This eliminates duplicate
definitions and makes schema management easier.

Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>

* feat: Composio connected account ID pinning (#2783)

* feat: Composio connected account ID pinning

Pin connected_account_id to Composio MCP URLs to prevent cross-project
credential leakage. Implements "both or none" policy — user_id and
connected_account_id are injected together or not at all.

- Add ComposioCredentialStore for credential lifecycle management
- Update AgentMcpManager and discoverToolsFromServer with pinning logic
- Mark Composio tools without connectedAccountId as needs_auth
- Add generic disconnect credential UI (works for all credential types)
- Store authScheme in credential retrievalParams for display
- Update OAuth login flow to create credential references post-connect
- Add unit tests for new credential store, composio client, and pinning

Made-with: Cursor

* feedback

* fix test

* Version Packages (#2778)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Add back link to projects sidebar, add org settings link to user drop… (#2787)

* Add back link to projects sidebar, add org settings link to user dropdown, adjust sidebar highlight color in dark mode

* Apply suggestion from @claude[bot]

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* Fix bad claude formatting

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* fix: return FileUIPart-compliant file parts from /run conversations endpoint (#2782)

* fix: return Vercel AI SDK FileUIPart-compliant file parts from /run conversations endpoint

- Resolve blob:// URIs to proxy HTTP URLs via resolveMessagesListBlobUris()
- Reshape file parts from { data, metadata.mimeType } to { url, mediaType, filename? }
- Matches Vercel AI SDK FileUIPart spec for useChat() compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Skip malformed file parts

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Mike Rashkovsky <[email protected]>

* fix: treat load_skill as internal tool to suppress false-positive Sentry errors (#2756)

* fix: provide relationshipId for load_skill tool calls in graph events

* fix: treat load_skill as internal tool, suppress chat/graph streaming events

* fix for fetch trace (#2791)

* fix for fetch trace

* fix for fetch trace

* Fix empty breadcrumb on `/[tenantId]/profile` page and replace prop-drilled permission flags (`readOnly`, `canEdit`, `canUse`) with direct hook call `useProjectPermissionsQuery()` (#2792)

* upd

* upd

* format

* format

* format

* format

* format

* format

* format

* format

* format

* fix review

* fix breadcrumb on profile page

* Apply suggestions from code review

Co-authored-by: Dimitri POSTOLOV <[email protected]>

* Update agents-manage-ui/src/lib/api/projects.ts

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* Update agents-manage-ui/src/app/[tenantId]/profile/layout.tsx

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* style: auto-format with biome

* fix review

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix(manage-ui): fix user-scoped MCP credential card not refreshing after connect/disconnect (#2794)

Fetch user-scoped credential server-side in page.tsx (matching the
project-scoped pattern) instead of via a client-side React Query hook.
This ensures router.refresh() after OAuth connect or credential delete
re-fetches the credential data, so the "Your Connection" card updates
without a manual page refresh.

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>

* reuse `useProjectsQuery` instead of `fetchProjectsAction` in `useEffect` (#2793)

* reuse `useProjectsQuery` instead of `fetchProjectsAction` in `useEffect`

* format

* upd

* fix lint

* Create little-hounds-battle.md

* upd

* upd skill file editor

* polish skill editor like in github

* remove canEdit

* upd

* move skill metadata under collapsible advanced section

* reuse DeleteConfirmation

* upd skill file editor

* upd skill file editor2

* add useInitialCollapsedSidebar

* add useInitialCollapsedSidebar

* upd skill file editor

* rm

* // Avoid including metadata in the frontmatter when it's null

* fetchSkillFile and createSkillFile

* refactor skill breadcrumb

* format

* polish

* upd

* skills integration tests

* fix validation tests

* update skill form

* upd api skills in manage ui

* upd entities

* partial

* fix skill loader test

* chore: update OpenAPI snapshot

* polish skill file editor

* upd core skills tests

* upd core skills tests

* add SkillCreateDataSchema

* update skills data manage

* remove redundant

* lint

* lint

* typecheck

* typecheck

* typecheck

* knip

* lint

* rollback skill modals

* make modal opens in skill selector

* fix typecheck

* this should fix cypress

* fix sdk tests

* split permissions call

* add folder feature

* findNodeByPath

* SkillDirectoryBrowser

* upd

* polish

* fix

* fix edge case metadata validation

* fix

* fix cli test

* format

* upd

* upd

* upd

* chore: update OpenAPI snapshot

* fix skill generator

* add button group

* connect submit logic with extension select

* polish

* update skill generator tests

* update generation test

* polish skill generator

* format

* format

* fixes for tests

* typecheck

* fix review

* format

* new migration

* upd

* rm migration

* add migrations

* fix migration and add

* rm outdated

* Apply suggestions from code review

Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* polish

* Add detailed changeset for nested skill files feature

Co-authored-by: Dimitri POSTOLOV <[email protected]>

* fix typecheck

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gaurav Varma <[email protected]>
Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Varun Varahabhotla <[email protected]>
Co-authored-by: mike-inkeep <[email protected]>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: mike-inkeep <[email protected]>
Co-authored-by: inkeep[bot] <257615677+inkeep[bot]@users.noreply.github.com>
Co-authored-by: Dimitri POSTOLOV <[email protected]>
Co-authored-by: shagun-singh-inkeep <[email protected]>
Co-authored-by: omar-inkeep <[email protected]>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-authored-by: inkeep-internal-ci[bot] <259778081+inkeep-internal-ci[bot]@users.noreply.github.com>
Co-authored-by: sarah <[email protected]>
Co-authored-by: Abraham <[email protected]>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
tim-inkeep pushed a commit that referenced this pull request Mar 31, 2026
* skill generator

* polish skill generator

* skills tests

* upd

* upd

* generation.test wip

* add generation.test

* tree node

* skill page

* skill loader

* skill loader refactor

* skill loader

* move skills sidebar to layout

* use pure monaco-editor component since we can have different file extension

* add shadcn context menu component

* format context menu

* skills files and edit pages

* dry

* update layout

* add docs

* add a changeset

* redirect to first skill

* skill files utils

* skill selector

* upd treenode

* skill files

* skill file editor

* delete skill confirmation

* add skill files actions

* skills data

* rm

* up skills route

* upd

* upd

* better project error message on dev

* types

* skill files

* skill loader

* format

* project test

* entities

* project full tests

* upd introspect

* upd cliiii

* nested skills tests

* remove edit page

* remove edit page

* update files page

* upd

* upd file editor

* add SkillFileInsertSchema

* superRefine

* add transform

* rm some cases in superRefine

* use pipe

* use pipe

* upd skill loader

* validation skills

* upd

* rm

* upd

* data access tests

* skills db changes

* add

* skill files

* upd

* upd

* upd skill update

* SkillUpdateSchema has required files

* upd skills manage

* upd

* upd layout and page

* style: auto-format with biome

* move empty state comp to page

* upd schemas

* update schemas

* move to with-sidebar

* polish

* upd

* upd skill generator

* Make webhooks docs user friendly (#2752)

* shaping a2a webhooks page

* moved triggers to visual builder

* vb webhooks wip

* numbered TOC steps

* added step circles

* indented toc steps more

* added newsletter signup to docs

* added share feedback button

* moved newsletter subscribe route to agent docs

* subscribe confirm polish

* improved spacing

* improved spacing

* added high quality images

* added verification step

* Sync lockfile after rebase

* Use tag reference for pullfrog action instead of pinned SHA (#2757)

The action is actively under development, so referencing the v0 tag
allows picking up updates automatically.

https://claude.ai/code/session_01QZyvEs97scVf1ahTG8C1rV

Co-authored-by: Claude <[email protected]>

* ci: provision PR preview environments in Railway (#2681)

* ci: add preview env diagnostics

* ci: probe preview env schema before deploy

* ci: probe preview env schema before deploy

* ci: harden preview api env defaults

* ci: attach git metadata to preview deploys

* ci: harden preview workflow operations

* ci: broaden preview log redaction

* ci: extract preview workflow scripts

* ci: harden preview script extraction

* fix(ci): correct Playwright cache restore-key prefix mismatch (#2760)

The restore-keys used `${{ runner.os }}-playwright-` but primary keys
used `playwright-${{ runner.os }}-`, so the prefix never matched on
cache miss, forcing a full browser download (~8.5 min) instead of a
cache restore (~13 sec).

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>

* fix(ci): replace full git clone with shallow checkout in CI job (#2761)

Remove fetch-depth: 0 from the ci job's checkout step, which cloned the
entire git history (1.5-5 min overhead). Only the OpenAPI change detection
step needs the base branch ref, so fetch it on-demand with --depth=1.

Also switches the diff from three-dot merge-base syntax to a two-dot
pathspec-filtered diff against the fetched base ref, which works correctly
with shallow clones.

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>

* format

* rm migration

* add new migrations

* validation for skill is ok

* move empty state to page

* delete skill

* delete skill revalidate path

* move skills schemas to own file

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* upd

* more typecheck fixes

* more typecheck fixes

* fix

* fix isRequired

* f1x

* move skill sidebar

* refactor skill sidebar

* add collapse file tree button

* upd

* upd

* upd

* deleteSkillFile

* upd

* deleteSkillFile

* fileId

* fileId

* upd schemas

* DeleteSkillFileConfirmation

* updateSkillFile

* rm simplematter from sdk

* Get Skill File

* getSkillFileById

* add new skill file page

* update skill file editor

* format

* Create Skill File

* upd

* createSkillFileAction

* createSkillFileById

* fix: Make OpenTelemetry startup idempotent (#2684)

* fix: Make OpenTelemetry startup idempotent

* fix: Re-export defaultSDK and cache NodeSDK instance on globalThis

Restores the export on defaultSDK to avoid breaking the
create-agents-template subpath import. Moves the new NodeSDK()
construction behind a globalThis guard (getOrCreateSDK) so
repeated Vite HMR module evaluations reuse the same instance instead
of leaking fresh SDK objects.

Co-authored-by: mike-inkeep <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix(template): use idempotent startOpenTelemetrySDK() in instrumentation

* fix: guard all OTel singletons behind globalThis for HMR idempotency

- Cache otlpExporter, batchProcessor, resource, instrumentations,
  spanProcessors, contextManager, and propagator on globalThis via
  Symbol keys and getOrCreate* helpers so HMR re-evaluation reuses
  existing instances instead of leaking new ones
- Make OtelGlobal type strict with per-key types, eliminating the
  loose `boolean | NodeSDK` union and the `as NodeSDK` cast
- Add logger.debug in the MetricReader catch block to distinguish
  clean idempotency from error-recovery idempotency
- Remove defaultSDK export (now module-private) since all consumers
  use startOpenTelemetrySDK() instead

* Fix type errors

* Simplify to just suppress the error since it's not an issue in prod, only local

* Limit to dev mode

* Add changeset for OTel HMR idempotency fix

Co-authored-by: Dimitri POSTOLOV <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: mike-inkeep <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: inkeep[bot] <257615677+inkeep[bot]@users.noreply.github.com>
Co-authored-by: Dimitri POSTOLOV <[email protected]>

* Fix scheduled trigger invocations being skipped (#2777)

* Fix scheduled trigger invocations being skipped when trigger is edited without changing the next execution time

* claude comments

* adding app id (#2779)

* Update pullfrog to latest SHA and add daily dependabot group for high-frequency deps (#2780)

* Update pullfrog to latest SHA and add daily dependabot group for high-frequency deps

- Update pullfrog from v0.0.178 SHA to v0.0.181 SHA (30d68e5) to stay on
  commit-pinned references for security (action has write permissions + 9 API keys)
- Split dependabot github-actions config into a "high-frequency" group for
  pullfrog with daily schedule, so SHA pins get updated automatically
- This supersedes PR #2757's approach of moving to mutable tag references

https://claude.ai/code/session_01D3ZGYHG8VhsZwqjjXqy2Ap

* Split dependabot github-actions into daily (pullfrog) and monthly (rest)

Separate into two ecosystem entries so pullfrog gets daily SHA updates
while other GitHub Actions stay on a monthly cadence.

https://claude.ai/code/session_01D3ZGYHG8VhsZwqjjXqy2Ap

* Fix invalid dependabot config: merge duplicate github-actions entries

Dependabot disallows duplicate ecosystem+directory pairs. Use a single
entry with two groups instead: high-frequency (pullfrog) and github-actions
(everything else via exclude-patterns).

https://claude.ai/code/session_01D3ZGYHG8VhsZwqjjXqy2Ap

---------

Co-authored-by: Claude <[email protected]>

* ci: seed preview auth in PR previews (#2775)

* ci: bootstrap preview auth

* ci: require secure preview auth config

* ci: recover preview auth runtime vars

* ci: install railway in preview bootstrap

* ci: provision preview db tcp proxies

* ci: proxy preview spicedb bootstrap

* ci: harden preview retry and error logging

---------

Co-authored-by: Andrew Mikofalvy <[email protected]>

* Fix scopes placeholder to show correct Nango format (#2784)

* Fix misleading scopes placeholder in credential form

The Nango API validates scopes against a strict comma-separated pattern
with no spaces. Updated placeholder and help text to show the correct
format and prevent 400 errors when users enter multiple scopes.

Made-with: Cursor

* Add changeset for scopes placeholder fix

Made-with: Cursor

* fix(manage-ui): fix URL validation bypass and permission guard in credential provider setup (#2776)

* fix(manage-ui): fix URL validation bypass and permission guard in credential provider setup

Reorder Zod schema construction so custom validators (e.g. URL protocol
allowlist) are chained after required/optional base schema instead of
being overwritten. Move all React hooks above the canEdit early-return
guard to satisfy Rules of Hooks, with canEdit checks inside hook bodies.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* fix(manage-ui): add server-side URL protocol validation in buildCredentialsPayload

Validate app_link against HTTP/HTTPS allowlist in the server action to
prevent bypassing client-side form validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Update agents-manage-ui/src/components/credentials/views/generic-auth-form.tsx

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* fix err

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* feat(pdf): Support PDF attachments (#2709)

* feat(pdf): Support PDF attachments

* Add tests and other review feedback

* Fix doc

* More renaming and cleanup

* refactor: extract Vercel content part schemas to types/chat.ts for reuse

Move inline Zod schemas from chatDataStream.ts and message-parts.ts into
types/chat.ts as shared, exported schemas. This eliminates duplicate
definitions and makes schema management easier.

Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>

* feat: Composio connected account ID pinning (#2783)

* feat: Composio connected account ID pinning

Pin connected_account_id to Composio MCP URLs to prevent cross-project
credential leakage. Implements "both or none" policy — user_id and
connected_account_id are injected together or not at all.

- Add ComposioCredentialStore for credential lifecycle management
- Update AgentMcpManager and discoverToolsFromServer with pinning logic
- Mark Composio tools without connectedAccountId as needs_auth
- Add generic disconnect credential UI (works for all credential types)
- Store authScheme in credential retrievalParams for display
- Update OAuth login flow to create credential references post-connect
- Add unit tests for new credential store, composio client, and pinning

Made-with: Cursor

* feedback

* fix test

* Version Packages (#2778)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Add back link to projects sidebar, add org settings link to user drop… (#2787)

* Add back link to projects sidebar, add org settings link to user dropdown, adjust sidebar highlight color in dark mode

* Apply suggestion from @claude[bot]

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* Fix bad claude formatting

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* fix: return FileUIPart-compliant file parts from /run conversations endpoint (#2782)

* fix: return Vercel AI SDK FileUIPart-compliant file parts from /run conversations endpoint

- Resolve blob:// URIs to proxy HTTP URLs via resolveMessagesListBlobUris()
- Reshape file parts from { data, metadata.mimeType } to { url, mediaType, filename? }
- Matches Vercel AI SDK FileUIPart spec for useChat() compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Skip malformed file parts

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Mike Rashkovsky <[email protected]>

* fix: treat load_skill as internal tool to suppress false-positive Sentry errors (#2756)

* fix: provide relationshipId for load_skill tool calls in graph events

* fix: treat load_skill as internal tool, suppress chat/graph streaming events

* fix for fetch trace (#2791)

* fix for fetch trace

* fix for fetch trace

* Fix empty breadcrumb on `/[tenantId]/profile` page and replace prop-drilled permission flags (`readOnly`, `canEdit`, `canUse`) with direct hook call `useProjectPermissionsQuery()` (#2792)

* upd

* upd

* format

* format

* format

* format

* format

* format

* format

* format

* format

* fix review

* fix breadcrumb on profile page

* Apply suggestions from code review

Co-authored-by: Dimitri POSTOLOV <[email protected]>

* Update agents-manage-ui/src/lib/api/projects.ts

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* Update agents-manage-ui/src/app/[tenantId]/profile/layout.tsx

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* style: auto-format with biome

* fix review

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix(manage-ui): fix user-scoped MCP credential card not refreshing after connect/disconnect (#2794)

Fetch user-scoped credential server-side in page.tsx (matching the
project-scoped pattern) instead of via a client-side React Query hook.
This ensures router.refresh() after OAuth connect or credential delete
re-fetches the credential data, so the "Your Connection" card updates
without a manual page refresh.

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>

* reuse `useProjectsQuery` instead of `fetchProjectsAction` in `useEffect` (#2793)

* reuse `useProjectsQuery` instead of `fetchProjectsAction` in `useEffect`

* format

* upd

* fix lint

* Create little-hounds-battle.md

* upd

* upd skill file editor

* polish skill editor like in github

* remove canEdit

* upd

* move skill metadata under collapsible advanced section

* reuse DeleteConfirmation

* upd skill file editor

* upd skill file editor2

* add useInitialCollapsedSidebar

* add useInitialCollapsedSidebar

* upd skill file editor

* rm

* // Avoid including metadata in the frontmatter when it's null

* fetchSkillFile and createSkillFile

* refactor skill breadcrumb

* format

* polish

* upd

* skills integration tests

* fix validation tests

* update skill form

* upd api skills in manage ui

* upd entities

* partial

* fix skill loader test

* chore: update OpenAPI snapshot

* polish skill file editor

* upd core skills tests

* upd core skills tests

* add SkillCreateDataSchema

* update skills data manage

* remove redundant

* lint

* lint

* typecheck

* typecheck

* typecheck

* knip

* lint

* rollback skill modals

* make modal opens in skill selector

* fix typecheck

* this should fix cypress

* fix sdk tests

* split permissions call

* add folder feature

* findNodeByPath

* SkillDirectoryBrowser

* upd

* polish

* fix

* fix edge case metadata validation

* fix

* fix cli test

* format

* upd

* upd

* upd

* chore: update OpenAPI snapshot

* fix skill generator

* add button group

* connect submit logic with extension select

* polish

* update skill generator tests

* update generation test

* polish skill generator

* format

* format

* fixes for tests

* typecheck

* fix review

* format

* new migration

* upd

* rm migration

* add migrations

* fix migration and add

* rm outdated

* Apply suggestions from code review

Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* polish

* Add detailed changeset for nested skill files feature

Co-authored-by: Dimitri POSTOLOV <[email protected]>

* fix typecheck

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gaurav Varma <[email protected]>
Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Varun Varahabhotla <[email protected]>
Co-authored-by: mike-inkeep <[email protected]>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: mike-inkeep <[email protected]>
Co-authored-by: inkeep[bot] <257615677+inkeep[bot]@users.noreply.github.com>
Co-authored-by: Dimitri POSTOLOV <[email protected]>
Co-authored-by: shagun-singh-inkeep <[email protected]>
Co-authored-by: omar-inkeep <[email protected]>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Andrew Mikofalvy <[email protected]>
Co-authored-by: inkeep-internal-ci[bot] <259778081+inkeep-internal-ci[bot]@users.noreply.github.com>
Co-authored-by: sarah <[email protected]>
Co-authored-by: Abraham <[email protected]>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant