diff --git a/doc/connections/GITHUB-REVIEW-BOT.md b/doc/connections/GITHUB-REVIEW-BOT.md index 8bbb653fc40..b9472359516 100644 --- a/doc/connections/GITHUB-REVIEW-BOT.md +++ b/doc/connections/GITHUB-REVIEW-BOT.md @@ -15,12 +15,6 @@ Enable **GitHub review bots** in instance **Experimental** settings, then open the GitHub Code Review Bot connector. This default-off setting is independent of **Chat connectors**. Hiding either feature does not pause existing provider delivery. -On an HTTP instance, setup explains the public HTTPS delivery requirement before -you choose an agent. An enrolled Paperclip Cloud connector supplies that webhook -address, including for localhost; otherwise connect Cloud during setup or provide -a public HTTPS address before creating the App. HTTP localhost alone is not a -delivery failure when Cloud is connected. - 1. Choose the bot agent. Prefer a [low-trust review agent](https://docs.paperclip.ing/administration/trust-and-low-trust-review/) with an isolated sandbox and a scoped task boundary. Standard-trust agents @@ -70,6 +64,8 @@ to the App settings list instead of assuming an owner. Local instances receive public callbacks and signed events through an enrolled Paperclip Cloud connector, using outbound requests instead of a public tunnel. +Your localhost instance does not need HTTPS or a tunnel for this flow. Setup +asks you to connect Cloud only if the instance is not already enrolled. The Cloud gateway capability must be deployed before localhost onboarding. Direct public-HTTPS webhook connections and manual existing-App credential recovery remain supported. An expired, unconsumed Cloud handoff can be renewed in the same draft after the configuring manager confirms that no App was created on GitHub. Claimed, consumed, and uncertain exchanges still require existing-App recovery. Setup tasks and copied prompts are not part of this diff --git a/doc/plans/2026-10-07-github-app-live-test-drive.md b/doc/plans/2026-10-07-github-app-live-test-drive.md index 4e7bf80830e..019355a60cc 100644 --- a/doc/plans/2026-10-07-github-app-live-test-drive.md +++ b/doc/plans/2026-10-07-github-app-live-test-drive.md @@ -392,3 +392,18 @@ retain App identity/configuration, and create no agent wakeup. UI/server typecheck/build, production Storybook build, token gates and diff whitespace checks pass. This remains connection qualification; the earlier full-suite failure and outstanding current-head CI/review limits still apply. + +### Correction: Cloud-backed localhost needs no HTTPS prerequisite (October 8) + +The preceding HTTP prerequisite banner was misleading. Cloud already provides +the public HTTPS receiver, and localhost retrieves signed events through +outbound requests. The user's Paperclip origin does not need HTTPS or a tunnel +for this wizard. Removed the banner, its extra enrollment-status query, and +the two obsolete component stories. Keep the existing conditional Connect +Paperclip Cloud handoff as the actual setup action when enrollment is absent. + +The running localhost wizard now shows Choose agent without an HTTPS warning. +No new connection or App was created during this correction. The delayed-ping +waiting and same-draft recovery fixes remain in place. All 30 focused setup and +management UI tests, UI typecheck/build, Storybook build and token gates pass. +The earlier full-suite and current-head CI/review limits still apply. diff --git a/ui/src/pages/apps/chat/GitHubChatSetup.test.tsx b/ui/src/pages/apps/chat/GitHubChatSetup.test.tsx index 0ff5ec15679..9198e0a3674 100644 --- a/ui/src/pages/apps/chat/GitHubChatSetup.test.tsx +++ b/ui/src/pages/apps/chat/GitHubChatSetup.test.tsx @@ -83,7 +83,7 @@ vi.mock("@/api/githubChat", () => ({ }, })); vi.mock("@/api/tools", () => ({ - toolsApi: { startCloudConnectorEnrollment: vi.fn(), getCloudConnectorEnrollment: vi.fn() }, + toolsApi: { startCloudConnectorEnrollment: vi.fn() }, })); vi.mock("@/lib/clipboard", () => ({ copyTextToClipboard: vi.fn() })); @@ -162,14 +162,6 @@ describe("GitHub App wizard", () => { }); vi.mocked(githubChatApi.saveDraft).mockResolvedValue({ saved: true }); vi.mocked(githubChatApi.personalConnections).mockResolvedValue([]); - vi.mocked(toolsApi.getCloudConnectorEnrollment).mockResolvedValue({ - configured: false, - status: "not_configured", - brokerBaseUrl: "https://gateway.example", - instanceId: null, - environment: "staging", - origins: [], - }); vi.mocked(copyTextToClipboard).mockResolvedValue(); client = new QueryClient({ defaultOptions: { queries: { retry: false, gcTime: 0 } }, @@ -188,34 +180,6 @@ describe("GitHub App wizard", () => { await new Promise((resolve) => setTimeout(resolve, 20)); }); } - it("explains HTTP delivery before choosing an agent without creating an App", async () => { - await render("agentId=reviewer"); - expect(container.querySelector('[role="alert"]')?.textContent).toContain( - "publicly reachable HTTPS URL before creating an App", - ); - expect(container.textContent).toContain( - "GitHub cannot send webhooks directly to this HTTP address", - ); - expect(chatEndpointsApi.create).not.toHaveBeenCalled(); - expect(githubChatApi.registration).not.toHaveBeenCalled(); - }); - it("explains that an enrolled Cloud gateway supports the HTTP instance", async () => { - vi.mocked(toolsApi.getCloudConnectorEnrollment).mockResolvedValue({ - configured: true, - status: "active", - brokerBaseUrl: "https://gateway.example", - instanceId: "instance", - environment: "staging", - origins: [window.location.origin], - }); - await render("agentId=reviewer"); - expect(container.querySelector('[role="note"]')?.textContent).toContain( - "Cloud is connected and provides the HTTPS webhook", - ); - expect(container.textContent).not.toContain( - "configure a publicly reachable HTTPS URL before creating", - ); - }); it("shows pending signed delivery as waiting, not failed setup", async () => { fixture.endpoint.botExternalId = "1234"; vi.mocked(githubChatApi.advance).mockResolvedValue({ @@ -315,7 +279,7 @@ describe("GitHub App wizard", () => { }), "company-1", ); - expect(container.textContent).not.toContain("Change Reviewer to a low trust agent"); + expect(container.querySelector('[role="alert"]')).toBeNull(); await click("Continue"); expect(chatEndpointsApi.create).toHaveBeenCalledWith("company-1", { provider: "github", diff --git a/ui/src/pages/apps/chat/GitHubChatSetup.tsx b/ui/src/pages/apps/chat/GitHubChatSetup.tsx index 4ff6b5e44cb..a3e7db84733 100644 --- a/ui/src/pages/apps/chat/GitHubChatSetup.tsx +++ b/ui/src/pages/apps/chat/GitHubChatSetup.tsx @@ -25,7 +25,6 @@ import { copyTextToClipboard } from "@/lib/clipboard"; import { resolveAgentAppearance } from "@paperclipai/shared"; import { agentAvatarUrl } from "@/lib/agent-avatar-url"; import { GitHubAppBranding, gitHubBotMention } from "./GitHubAppIdentity"; -import { GitHubWebhookPrerequisite } from "./GitHubWebhookPrerequisite"; /** Restrict native manifest submission to GitHub registration endpoints. */ export function gitHubAppManifestAction( @@ -117,12 +116,6 @@ export function GitHubChatSetup() { refetchInterval: 3000, }); const bot = current.data; - const cloudEnrollment = useQuery({ - queryKey: ["cloud-connector", "enrollment"], - queryFn: () => toolsApi.getCloudConnectorEnrollment(), - enabled: !!selectedCompanyId && !identityOnly && window.location.protocol !== "https:", - retry: false, - }); const progress = useQuery({ queryKey: ["github-wizard", resume], queryFn: () => githubChatApi.advance(resume!), @@ -265,14 +258,6 @@ export function GitHubChatSetup() { ? "Connect your account" : "Connect GitHub"} - {!identityOnly && !connected && !bot?.botExternalId && ( - - )} {(error || (!identityOnly && progress.error) || accounts.error) && (

{error || diff --git a/ui/src/pages/apps/chat/GitHubWebhookPrerequisite.tsx b/ui/src/pages/apps/chat/GitHubWebhookPrerequisite.tsx deleted file mode 100644 index c131d0aa0e2..00000000000 --- a/ui/src/pages/apps/chat/GitHubWebhookPrerequisite.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { AlertTriangle, Info } from "lucide-react"; - -export function GitHubWebhookPrerequisite({ - origin, - cloudState, -}: { - origin: string; - cloudState: "loading" | "active" | "required" | "unavailable"; -}) { - if (new URL(origin).protocol === "https:") return null; - const warning = cloudState === "required" || cloudState === "unavailable"; - const Icon = warning ? AlertTriangle : Info; - return ( -

- -
-

- GitHub needs public HTTPS webhook delivery -

-

- GitHub cannot send webhooks directly to this HTTP address. - {cloudState === "active" - ? " Paperclip Cloud is connected and provides the HTTPS webhook. Keep this instance running to receive events." - : cloudState === "loading" - ? " Paperclip Cloud can provide HTTPS delivery. Checking its connection…" - : `${cloudState === "unavailable" ? " Couldn’t confirm Cloud delivery." : ""} Connect Paperclip Cloud during setup, or configure a publicly reachable HTTPS URL before creating an App.`} -

- {warning && ( - - Set up public HTTPS - - )} -
-
- ); -} diff --git a/ui/storybook/stories/github-bot-management/management.stories.tsx b/ui/storybook/stories/github-bot-management/management.stories.tsx index 6bbc8190324..d9e5bfae1f0 100644 --- a/ui/storybook/stories/github-bot-management/management.stories.tsx +++ b/ui/storybook/stories/github-bot-management/management.stories.tsx @@ -20,7 +20,6 @@ import { } from "@/pages/apps/chat/GitHubAppIdentity"; import { resolveAgentAppearance } from "@paperclipai/shared"; import { agentAvatarUrl } from "@/lib/agent-avatar-url"; -import { GitHubWebhookPrerequisite } from "@/pages/apps/chat/GitHubWebhookPrerequisite"; import { endpoint, agent, @@ -183,26 +182,6 @@ export const AppIdentityAndLogo: Story = { , ), }; -export const HttpSetupPrerequisite: Story = { - name: "03 Components / HTTP setup requires delivery", - render: () => - component( - , - ), -}; -export const HttpSetupWithCloud: Story = { - name: "03 Components / HTTP setup with Cloud connected", - render: () => - component( - , - ), -}; export const ReviewHistory: Story = { name: "03 Components / Review rows", render: () =>