Skip to content

feat: configurable app name and icon for whitelabel deployments#594

Open
donnfelker wants to merge 4 commits intoColeMurray:mainfrom
donnfelker:feat/configurable-app-name-icon
Open

feat: configurable app name and icon for whitelabel deployments#594
donnfelker wants to merge 4 commits intoColeMurray:mainfrom
donnfelker:feat/configurable-app-name-icon

Conversation

@donnfelker
Copy link
Copy Markdown
Contributor

@donnfelker donnfelker commented May 4, 2026

Summary

  • Threads a single Terraform variable app_name (default Open-Inspect) through the web UI, both bot workers, the control-plane PR footer, and outbound HTTP User-Agent headers — forks and whitelabel deployments can now rebrand without patching source.
  • Adds optional app_icon_url (custom logo + browser favicon) and NEXT_PUBLIC_APP_SHORT_NAME (the historical "Inspect" sidebar label, kept as the default).
  • New resolveAppName(env) helper in @open-inspect/shared is the single source of truth — workers resolve at request time, the web bundle inlines NEXT_PUBLIC_APP_NAME / NEXT_PUBLIC_APP_ICON_URL / NEXT_PUBLIC_APP_SHORT_NAME at build time.

Surfaces wired up

Surface Source Variable
Web tab title, sign-in heading, landing hero metadata, sidebar-layout, (app)/page NEXT_PUBLIC_APP_NAME
Web sidebar logo label session-sidebar NEXT_PUBLIC_APP_SHORT_NAME (defaults to Inspect)
Web sidebar logo image + browser favicon new <AppIcon> helper, metadata.icons NEXT_PUBLIC_APP_ICON_URL
Slack App Home intro text slack-bot/src/index.ts APP_NAME (worker binding)
Linear OAuth success page linear-bot/src/index.ts APP_NAME
Linear completion comment headers linear-bot/src/callbacks.ts APP_NAME
Pull request body footer control-plane/src/session/pull-request-service.ts APP_NAME
GitHub + GitLab User-Agent headers provider config + github-app.ts + github-bot/github-auth.ts APP_NAME

Defaults preserve all existing behavior — no diff for deployments that don't set the new vars.

Backwards compatibility

  • All new Terraform vars default to current values (app_name = "Open-Inspect", app_icon_url = "").
  • Sidebar logo defaults to literal Inspect (the historical short label) and only follows APP_NAME when explicitly overridden.
  • Function-level User-Agent params on github-bot helpers default to Open-Inspect so any other callers keep working.

Screenshots with config values as example

Default
CleanShot 2026-05-04 at 17 26 36@2x

With Custom App Name (no Short Name)
CleanShot 2026-05-04 at 17 25 59@2x

With Custom App Name and Short Name
CleanShot 2026-05-04 at 17 26 14@2x

Docs updated

  • docs/GETTING_STARTED.md — new terraform.tfvars block, CI secrets table entries, and a "Customizing the App Name and Icon" section
  • docs/SETUP_GUIDE.md — adds NEXT_PUBLIC_APP_NAME / NEXT_PUBLIC_APP_ICON_URL to the local dev .env.local template

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Optional app branding (name, short name, icon) to customize site title, icon, command menu, sidebar label, PR footers, bot messages, and OAuth success pages.
  • Documentation
    • Setup and getting-started updated with branding vars, CI/CD secret guidance, and notes about build-time inlining and redeploy steps.
  • Tests
    • Added coverage ensuring branding appears and is safely escaped in UI, comments, and bot outputs.

donnfelker and others added 2 commits May 4, 2026 16:30
Brand strings ("Open-Inspect" / "Inspect") and the inline sidebar SVG
were hardcoded across the web UI, bot workers, PR footer, and outbound
HTTP User-Agent headers. Forks and whitelabel deployments had to patch
source to rebrand. Thread a single Terraform variable `app_name` (with
optional `app_icon_url`) through every surface so deployments can
override the brand without touching code.

The web build receives `NEXT_PUBLIC_APP_NAME` and
`NEXT_PUBLIC_APP_ICON_URL` (inlined into the client bundle, per
Cloudflare OpenNext build-time requirements). The control-plane and bot
workers receive an `APP_NAME` plain-text binding and resolve it per
request via a new `resolveAppName(env)` helper in
`@open-inspect/shared`. Defaults preserve existing behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous commit unified the sidebar logo text with the full app
name, which regressed the historical "Inspect" short label to
"Open-Inspect". The sidebar logo is intentionally a shorter brand than
the tab title and sign-in heading.

Add APP_SHORT_NAME (driven by optional NEXT_PUBLIC_APP_SHORT_NAME),
defaulting to "Inspect" for the built-in brand and falling through to
APP_NAME when only NEXT_PUBLIC_APP_NAME is set. Whitelabel deployments
can override the short label independently for cases where the long
name is too wide for the sidebar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2e2c1a0c-a73e-4b84-917e-9a524c95e19e

📥 Commits

Reviewing files that changed from the base of the PR and between 720ed0c and 53d3188.

📒 Files selected for processing (6)
  • docs/GETTING_STARTED.md
  • docs/SETUP_GUIDE.md
  • terraform/environments/production/terraform.tfvars.example
  • terraform/environments/production/variables.tf
  • terraform/environments/production/web-cloudflare.tf
  • terraform/environments/production/web-vercel.tf
✅ Files skipped from review due to trivial changes (2)
  • terraform/environments/production/web-vercel.tf
  • terraform/environments/production/terraform.tfvars.example
🚧 Files skipped from review as they are similar to previous changes (4)
  • terraform/environments/production/web-cloudflare.tf
  • terraform/environments/production/variables.tf
  • docs/SETUP_GUIDE.md
  • docs/GETTING_STARTED.md

📝 Walkthrough

Walkthrough

Threads a configurable app name/icon through shared helpers, env types, Terraform bindings, web site config/UI, bot/provider code, and tests; uses resolveAppName() to set APP_NAME and to populate User-Agent headers and PR/comment footers; updates docs and CI secrets for optional whitelabeling. (50 words)

Changes

App Whitelabeling

Layer / File(s) Summary
Shared Foundation
packages/shared/src/app-name.ts, packages/shared/src/app-name.test.ts, packages/shared/src/index.ts
Add DEFAULT_APP_NAME, AppNameEnv, and resolveAppName() with tests; re-export from shared.
Env Types
packages/control-plane/src/types.ts, packages/github-bot/src/types.ts, packages/linear-bot/src/types.ts, packages/slack-bot/src/types/index.ts
Add optional APP_NAME?: string to service Env interfaces.
Terraform / Deploy Wiring
terraform/environments/production/variables.tf, terraform/environments/production/terraform.tfvars.example, terraform/environments/production/web-cloudflare.tf, terraform/environments/production/web-vercel.tf, terraform/environments/production/workers-*.tf
Introduce app_name, app_short_name, app_icon_url variables; wire NEXT_PUBLIC_* into web build envs and add APP_NAME plain-text bindings to workers.
Web Site Config
packages/web/src/lib/site-config.ts, packages/web/src/lib/site-config.test.ts
New exported APP_NAME, APP_SHORT_NAME, APP_ICON_URL derived from NEXT_PUBLIC_* with trimming/fallbacks; tests for defaulting and precedence.
Web UI Components / Layout
packages/web/src/components/ui/app-icon.tsx, packages/web/src/app/layout.tsx, packages/web/src/app/(app)/page.tsx, packages/web/src/components/global-command-menu.tsx, packages/web/src/components/session-sidebar.tsx, packages/web/src/components/sidebar-layout.tsx
Add AppIcon component; replace hard-coded strings/icons with APP_NAME/APP_SHORT_NAME/APP_ICON_URL in metadata, headers, sidebar, and command menu.
Control Plane Providers & Auth
packages/control-plane/src/auth/github-app.ts, packages/control-plane/src/auth/github.ts, packages/control-plane/src/source-control/providers/constants.ts, packages/control-plane/src/source-control/providers/types.ts, packages/control-plane/src/source-control/providers/github-provider.ts, packages/control-plane/src/source-control/providers/github-provider.test.ts
Import DEFAULT_APP_NAME, add optional userAgent config, thread resolved userAgent into all outbound GitHub/GitLab requests and GitHub App token flows; tests added/updated for header threading and defaults.
Control Plane Wiring
packages/control-plane/src/routes/shared.ts, packages/control-plane/src/session/durable-object.ts, packages/control-plane/src/session/pull-request-service.ts, packages/control-plane/src/session/pull-request-service.test.ts
Compute userAgent = resolveAppName(env) when creating providers; inject appName into SessionPullRequestService and use it in PR footer; tests verify custom app name usage.
GitHub Bot
packages/github-bot/src/github-auth.ts, packages/github-bot/src/handlers.ts, packages/github-bot/test/*
Add optional userAgent to GitHub app config and functions; handlers call resolveAppName(env) and pass as userAgent into token generation, permission checks, and reaction posts; tests updated.
Linear Bot
packages/linear-bot/src/index.ts, packages/linear-bot/src/callbacks.ts, packages/linear-bot/src/types.ts, packages/linear-bot/src/__tests__/pure-functions.test.ts, packages/linear-bot/src/callbacks.helpers.test.ts
Add buildOAuthSuccessHtml() and formatCompletionComment() helpers using appName; use resolveAppName(env) for OAuth success page and completion comments; tests added for escaping and formatting.
Slack Bot
packages/slack-bot/src/index.ts, packages/slack-bot/src/types/index.ts, packages/slack-bot/src/index.test.ts
Add buildAppHomeIntroText(appName) and call with resolveAppName(env) when publishing App Home; tests added.
Documentation / Setup
docs/GETTING_STARTED.md, docs/SETUP_GUIDE.md
Document app_name, app_short_name, app_icon_url in Terraform examples and NEXT_PUBLIC_* in .env.local; add CI/CD secrets (APP_NAME, APP_SHORT_NAME, APP_ICON_URL) and a section describing build-time inlining and redeploy/apply steps.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer (deploy)
    participant WebBuild as Web Build (Vercel/Cloudflare)
    participant Worker as Worker / Control Plane
    participant GitHub as GitHub API
    rect rgba(200,200,255,0.5)
    Dev->>WebBuild: terraform apply / set NEXT_PUBLIC_APP_NAME
    WebBuild->>WebBuild: inlines NEXT_PUBLIC_APP_NAME into bundle
    end
    rect rgba(200,255,200,0.5)
    Worker->>Worker: resolveAppName(env) -> userAgent
    Worker->>GitHub: API request (User-Agent: userAgent)
    GitHub-->>Worker: response
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • ColeMurray

Poem

🐰 I found a name, I found an icon bright,
I stitched them through headers and into the site.
From env to token, the rabbit hopped along,
Replacing the default with your brand's little song.
Hooray — the app wears a carrot-colored light!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: adding configurable app name and icon support for whitelabel deployments, which aligns with the extensive changes across documentation, TypeScript/JavaScript code, and Terraform configuration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/github-bot/test/handlers.test.ts (1)

187-193: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

handlePullRequestOpened test has incomplete assertion coverage for generateInstallationToken.

The implementation correctly passes userAgent to generateInstallationToken via resolveCallerGating, but the test only verifies the function was called without checking the arguments. Compare this to handleReviewRequested (line 351), which asserts generateInstallationToken receives the full payload including userAgent: "Open-Inspect". Add the same argument verification to handlePullRequestOpened:

expect(generateInstallationToken).toHaveBeenCalledWith({
  appId: "12345",
  privateKey: "test-key",
  installationId: "67890",
  userAgent: "Open-Inspect",
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/github-bot/test/handlers.test.ts` around lines 187 - 193, Update the
test for handlePullRequestOpened to assert generateInstallationToken was called
with the expected payload including userAgent; specifically, in the test that
currently calls generateInstallationToken and postReaction, replace or augment
the existing toHaveBeenCalled() for generateInstallationToken with a
toHaveBeenCalledWith asserting an object containing appId: "12345", privateKey:
"test-key", installationId: "67890", and userAgent: "Open-Inspect" so the call
via resolveCallerGating is fully validated.
🧹 Nitpick comments (5)
packages/linear-bot/src/__tests__/pure-functions.test.ts (1)

8-8: 💤 Low value

Consider co-locating buildOAuthSuccessHtml in a utility module rather than importing from the worker entry point.

../index initializes the full Hono app and registers all routes at module load time. The rest of this test file imports pure utilities directly from ../model-resolution and ../callbacks, not from the entry point. Importing the worker entry just to access one helper couples unrelated test suites to the entire worker initialization graph and makes future entry-point side-effects (e.g., KV access at init) silently break these tests.

Moving buildOAuthSuccessHtml to e.g. ./utils/oauth-html.ts (or ./webhook-handler.ts alongside escapeHtml) and re-exporting it from index.ts keeps the public API intact while making the pure-function tests independent of the worker entry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/linear-bot/src/__tests__/pure-functions.test.ts` at line 8, The test
imports buildOAuthSuccessHtml from ../index which pulls in and initializes the
entire Hono worker; move the pure helper into a dedicated module (e.g., create a
new utils/oauth-html.ts or webhook-handler.ts) that exports
buildOAuthSuccessHtml (and related helpers like escapeHtml), update index.ts to
re-export buildOAuthSuccessHtml so public API is unchanged, and change the test
to import buildOAuthSuccessHtml from the new utils module to avoid triggering
worker initialization side effects.
packages/web/src/components/ui/app-icon.tsx (1)

8-13: 💤 Low value

Consider adding an onError fallback to InspectIcon to handle a missing/broken icon URL at runtime.

If APP_ICON_URL is set at build time but the asset isn't served (e.g., /vector.png not deployed to public/), users see a broken-image placeholder in the sidebar/command menu. An onError handler can recover gracefully.

Note: this requires adding "use client" since onError is an event handler.

♻️ Proposed refactor
+"use client";
+import { useState } from "react";
 import { APP_ICON_URL, APP_NAME } from "@/lib/site-config";
 import { InspectIcon } from "@/components/ui/icons";

 interface AppIconProps {
   className?: string;
 }

 export function AppIcon({ className }: AppIconProps) {
+  const [imgError, setImgError] = useState(false);
+  if (APP_ICON_URL && !imgError) {
-  if (APP_ICON_URL) {
-    return <img src={APP_ICON_URL} alt={`${APP_NAME} logo`} className={className} />;
+    return (
+      <img
+        src={APP_ICON_URL}
+        alt={`${APP_NAME} logo`}
+        className={className}
+        onError={() => setImgError(true)}
+      />
+    );
   }
   return <InspectIcon className={className} />;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/components/ui/app-icon.tsx` around lines 8 - 13, The AppIcon
component should handle runtime image load failures: mark the file as a client
component by adding "use client" at the top, add local state (e.g., failed
boolean via useState) and an onError handler on the <img> rendered when
APP_ICON_URL is truthy that sets failed=true, and change the render to show
InspectIcon when failed is true (or when APP_ICON_URL is falsy). Update the
AppIcon function to reference APP_ICON_URL, the onError handler, and InspectIcon
accordingly so a broken/missing asset falls back to InspectIcon at runtime.
packages/shared/src/app-name.ts (1)

9-9: 💤 Low value

Redundant value.length > 0 check after value &&.

After .trim(), an all-whitespace APP_NAME becomes "", which is already falsy. value && value.length > 0 is equivalent to just value.

♻️ Proposed simplification
-  return value && value.length > 0 ? value : DEFAULT_APP_NAME;
+  return value || DEFAULT_APP_NAME;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/app-name.ts` at line 9, The ternary check in the return
statement is redundant: replace the expression that currently uses "value &&
value.length > 0 ? value : DEFAULT_APP_NAME" with a simpler truthy check so the
function (in app-name.ts, e.g., the exported function that computes the app
name) returns value when truthy and DEFAULT_APP_NAME otherwise; update the
return in that function to use a single truthy check (or logical OR) instead of
testing both value and value.length.
packages/web/src/lib/site-config.test.ts (1)

30-40: ⚡ Quick win

Import DEFAULT_APP_NAME instead of hardcoding "Open-Inspect"

Both fallback assertions (lines 33 and 39) hardcode "Open-Inspect". If DEFAULT_APP_NAME is ever updated in @open-inspect/shared, these tests will fail without the failure being obviously tied to the constant — and a new value would need to be chased down here manually.

♻️ Proposed fix
-import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+import { DEFAULT_APP_NAME } from "@open-inspect/shared";

 ...

   it("falls back to Open-Inspect when NEXT_PUBLIC_APP_NAME is unset", async () => {
     delete process.env.NEXT_PUBLIC_APP_NAME;
     const { APP_NAME } = await import("./site-config");
-    expect(APP_NAME).toBe("Open-Inspect");
+    expect(APP_NAME).toBe(DEFAULT_APP_NAME);
   });

   it("falls back to Open-Inspect when NEXT_PUBLIC_APP_NAME is empty", async () => {
     process.env.NEXT_PUBLIC_APP_NAME = "   ";
     const { APP_NAME } = await import("./site-config");
-    expect(APP_NAME).toBe("Open-Inspect");
+    expect(APP_NAME).toBe(DEFAULT_APP_NAME);
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/lib/site-config.test.ts` around lines 30 - 40, Replace the
hardcoded "Open-Inspect" in the two tests with the shared constant by importing
DEFAULT_APP_NAME from "@open-inspect/shared" and asserting
expect(APP_NAME).toBe(DEFAULT_APP_NAME);; update the top of the test module to
import DEFAULT_APP_NAME alongside the dynamic import of "./site-config" (or
require it statically) and keep the existing APP_NAME checks identical
otherwise.
terraform/environments/production/web-cloudflare.tf (1)

17-23: ⚡ Quick win

NEXT_PUBLIC_APP_SHORT_NAME not wired through Terraform

APP_SHORT_NAME is described as a new configurable feature in this PR (evidenced by NEXT_PUBLIC_APP_SHORT_NAME support in site-config.ts and the PR description), but neither the build environment nor the generated wrangler.production.toml [vars] exposes a Terraform variable for it. Terraform-managed deployments that need a short name distinct from APP_NAME (e.g., "Vector" alongside NEXT_PUBLIC_APP_NAME=Vector Bot) cannot set it via the standard Terraform path.

The default behaviour ("Inspect" fallback or inherit from APP_NAME) means this isn't a blocker, but it leaves the feature only half-surfaced at the infrastructure layer.

♻️ Proposed addition

In variables.tf (alongside app_name / app_icon_url):

variable "app_short_name" {
  description = "Short sidebar label (defaults to app_name when not set)"
  type        = string
  default     = ""
}

Then in the build environment block:

     environment = {
       NEXT_PUBLIC_WS_URL           = local.ws_url
       NEXT_PUBLIC_SANDBOX_PROVIDER = var.sandbox_provider
       NEXT_PUBLIC_APP_NAME         = var.app_name
       NEXT_PUBLIC_APP_ICON_URL     = var.app_icon_url
+      NEXT_PUBLIC_APP_SHORT_NAME   = var.app_short_name
     }

And in wrangler.production.toml [vars]:

     NEXT_PUBLIC_APP_NAME = "${var.app_name}"
     NEXT_PUBLIC_APP_ICON_URL = "${var.app_icon_url}"
+    NEXT_PUBLIC_APP_SHORT_NAME = "${var.app_short_name}"

Also applies to: 62-75

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@terraform/environments/production/web-cloudflare.tf` around lines 17 - 23,
Add a Terraform variable and wire it through the Cloudflare build vars and
wrangler production vars: declare a new variable "app_short_name" (string,
default ""), add NEXT_PUBLIC_APP_SHORT_NAME = var.app_short_name to the
environment map used for builds (alongside
NEXT_PUBLIC_APP_NAME/NEXT_PUBLIC_APP_ICON_URL), and add a corresponding
NEXT_PUBLIC_APP_SHORT_NAME entry under the [vars] block in
wrangler.production.toml generation so the short name can be set via Terraform
rather than only falling back to APP_NAME.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@terraform/environments/production/variables.tf`:
- Around line 334-344: Add a new Terraform variable named app_short_name
(string, default empty) to expose the sidebar short label, then propagate it
into the web deployment stacks by wiring it to the APP_SHORT_NAME /
NEXT_PUBLIC_APP_SHORT_NAME build env var where web-cloudflare.tf and
web-vercel.tf set other web app envs; update any places that generate or pass
environment variables for the web build (the blocks that currently reference
app_name/app_icon_url) to also include app_short_name so deployers can set the
short label via Terraform.

In `@terraform/environments/production/web-vercel.tf`:
- Around line 64-75: Add the missing NEXT_PUBLIC_APP_SHORT_NAME env var to the
Vercel env block by creating an entry with key "NEXT_PUBLIC_APP_SHORT_NAME",
value var.app_short_name, targets ["production","preview"], sensitive = false
(placed alongside NEXT_PUBLIC_APP_NAME and NEXT_PUBLIC_APP_ICON_URL in
web-vercel.tf) and declare var.app_short_name in the Terraform variables for the
production environment (variables.tf) with a default of "" to match other
optional branding vars; this ensures packages/web/src/lib/site-config.ts can
read NEXT_PUBLIC_APP_SHORT_NAME as intended.

---

Outside diff comments:
In `@packages/github-bot/test/handlers.test.ts`:
- Around line 187-193: Update the test for handlePullRequestOpened to assert
generateInstallationToken was called with the expected payload including
userAgent; specifically, in the test that currently calls
generateInstallationToken and postReaction, replace or augment the existing
toHaveBeenCalled() for generateInstallationToken with a toHaveBeenCalledWith
asserting an object containing appId: "12345", privateKey: "test-key",
installationId: "67890", and userAgent: "Open-Inspect" so the call via
resolveCallerGating is fully validated.

---

Nitpick comments:
In `@packages/linear-bot/src/__tests__/pure-functions.test.ts`:
- Line 8: The test imports buildOAuthSuccessHtml from ../index which pulls in
and initializes the entire Hono worker; move the pure helper into a dedicated
module (e.g., create a new utils/oauth-html.ts or webhook-handler.ts) that
exports buildOAuthSuccessHtml (and related helpers like escapeHtml), update
index.ts to re-export buildOAuthSuccessHtml so public API is unchanged, and
change the test to import buildOAuthSuccessHtml from the new utils module to
avoid triggering worker initialization side effects.

In `@packages/shared/src/app-name.ts`:
- Line 9: The ternary check in the return statement is redundant: replace the
expression that currently uses "value && value.length > 0 ? value :
DEFAULT_APP_NAME" with a simpler truthy check so the function (in app-name.ts,
e.g., the exported function that computes the app name) returns value when
truthy and DEFAULT_APP_NAME otherwise; update the return in that function to use
a single truthy check (or logical OR) instead of testing both value and
value.length.

In `@packages/web/src/components/ui/app-icon.tsx`:
- Around line 8-13: The AppIcon component should handle runtime image load
failures: mark the file as a client component by adding "use client" at the top,
add local state (e.g., failed boolean via useState) and an onError handler on
the <img> rendered when APP_ICON_URL is truthy that sets failed=true, and change
the render to show InspectIcon when failed is true (or when APP_ICON_URL is
falsy). Update the AppIcon function to reference APP_ICON_URL, the onError
handler, and InspectIcon accordingly so a broken/missing asset falls back to
InspectIcon at runtime.

In `@packages/web/src/lib/site-config.test.ts`:
- Around line 30-40: Replace the hardcoded "Open-Inspect" in the two tests with
the shared constant by importing DEFAULT_APP_NAME from "@open-inspect/shared"
and asserting expect(APP_NAME).toBe(DEFAULT_APP_NAME);; update the top of the
test module to import DEFAULT_APP_NAME alongside the dynamic import of
"./site-config" (or require it statically) and keep the existing APP_NAME checks
identical otherwise.

In `@terraform/environments/production/web-cloudflare.tf`:
- Around line 17-23: Add a Terraform variable and wire it through the Cloudflare
build vars and wrangler production vars: declare a new variable "app_short_name"
(string, default ""), add NEXT_PUBLIC_APP_SHORT_NAME = var.app_short_name to the
environment map used for builds (alongside
NEXT_PUBLIC_APP_NAME/NEXT_PUBLIC_APP_ICON_URL), and add a corresponding
NEXT_PUBLIC_APP_SHORT_NAME entry under the [vars] block in
wrangler.production.toml generation so the short name can be set via Terraform
rather than only falling back to APP_NAME.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 85802609-558b-4cda-b26c-75cced3b132a

📥 Commits

Reviewing files that changed from the base of the PR and between cd68977 and b76316f.

📒 Files selected for processing (46)
  • docs/GETTING_STARTED.md
  • docs/SETUP_GUIDE.md
  • packages/control-plane/src/auth/github-app.ts
  • packages/control-plane/src/auth/github.ts
  • packages/control-plane/src/routes/shared.ts
  • packages/control-plane/src/session/durable-object.ts
  • packages/control-plane/src/session/pull-request-service.test.ts
  • packages/control-plane/src/session/pull-request-service.ts
  • packages/control-plane/src/source-control/providers/constants.ts
  • packages/control-plane/src/source-control/providers/github-provider.test.ts
  • packages/control-plane/src/source-control/providers/github-provider.ts
  • packages/control-plane/src/source-control/providers/gitlab-provider.ts
  • packages/control-plane/src/source-control/providers/types.ts
  • packages/control-plane/src/types.ts
  • packages/github-bot/src/github-auth.ts
  • packages/github-bot/src/handlers.ts
  • packages/github-bot/src/types.ts
  • packages/github-bot/test/github-auth.test.ts
  • packages/github-bot/test/handlers.test.ts
  • packages/linear-bot/src/__tests__/pure-functions.test.ts
  • packages/linear-bot/src/callbacks.helpers.test.ts
  • packages/linear-bot/src/callbacks.ts
  • packages/linear-bot/src/index.ts
  • packages/linear-bot/src/types.ts
  • packages/shared/src/app-name.test.ts
  • packages/shared/src/app-name.ts
  • packages/shared/src/index.ts
  • packages/slack-bot/src/index.test.ts
  • packages/slack-bot/src/index.ts
  • packages/slack-bot/src/types/index.ts
  • packages/web/src/app/(app)/page.tsx
  • packages/web/src/app/layout.tsx
  • packages/web/src/components/global-command-menu.tsx
  • packages/web/src/components/session-sidebar.tsx
  • packages/web/src/components/sidebar-layout.tsx
  • packages/web/src/components/ui/app-icon.tsx
  • packages/web/src/lib/site-config.test.ts
  • packages/web/src/lib/site-config.ts
  • terraform/environments/production/terraform.tfvars.example
  • terraform/environments/production/variables.tf
  • terraform/environments/production/web-cloudflare.tf
  • terraform/environments/production/web-vercel.tf
  • terraform/environments/production/workers-control-plane.tf
  • terraform/environments/production/workers-github.tf
  • terraform/environments/production/workers-linear.tf
  • terraform/environments/production/workers-slack.tf

Comment thread terraform/environments/production/variables.tf
Comment thread terraform/environments/production/web-vercel.tf
donnfelker and others added 2 commits May 4, 2026 17:55
The installationBindings() helper added a layer of indirection that
made the four github-app helper calls harder to follow — readers had
to jump to the method definition to see what was actually being
forwarded. Inline { cacheStore, userAgent } at each call site so the
arguments are visible where they're used.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The sidebar header has limited horizontal width (288px) so a long
app_name like "Acme Coding Agent" overflows. Promote the existing
NEXT_PUBLIC_APP_SHORT_NAME web env var to a first-class Terraform
variable so production deployments can override the sidebar label
the same way as app_name and app_icon_url, without requiring direct
edits to the web build env.

Threaded through web-cloudflare.tf (build env + wrangler vars) and
web-vercel.tf (env array). Documented in tfvars.example, the local
dev .env.local template, the GETTING_STARTED tfvars block, the
whitelabel section, and the CI secrets table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.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