Skip to content

refactor(api): migrate brand identities to Effect programs - #1042

Merged
janburzinski merged 6 commits into
mainfrom
cursor/effect-brand-identities
Sep 12, 2026
Merged

janburzinski merged 6 commits into
mainfrom
cursor/effect-brand-identities

Conversation

@janburzinski

@janburzinski janburzinski commented Sep 12, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Give a short summary of what this PR does and why it's needed.

Screenshot/Recording (if applicable)

Attach a screenshot or recording of the change. This is optional, but can help reviewers understand the change. You can use Cap to record a video.

Checklist
  • I ran a self-review before opening this PR
  • I ran formatting/linting/type checks locally
  • I updated docs when behavior or setup changed
  • I only added comments where the logic is not obvious
  • I have used conventional commits for the PR title and commit messages
  • I did not use AI to write the code in this PR or have disclosed that I did
Open in Web Open in Cursor 

Summary by cubic

Refactors brand identity API handlers into Effect programs with typed errors. Delete now returns 409 when the identity is referenced by projects or content briefs, instead of surfacing a raw foreign-key error.

Refactors

  • Routes delegate to Effect programs in apps/api/src/programs/brand-identities.ts; database errors die and hit the central error handler.
  • Adds typed domain errors and a shared respondToBrandIdentityFailure mapping for consistent error responses.
  • The brand identity is only rolled back when the dashboard explicitly rejects workflow start (4xx or pre-flight configuration/auth failures). Transport timeouts and any post-acceptance Redis failure mark the job failed and return 503 without deleting.
  • Selects GitHub app account type/login in the dashboard publish query so main typechecks.

Written for commit 14c3863. Summary will update on new commits.

Review in cubic

Extract all six brand-identities handlers into Effect programs with
typed domain errors, runBrandIdentityProgram bridge, and thin Hono
routes. Preserves HTTP semantics including pre-rate-limit validation,
workflow rollback, default-identity switching, and QStash cleanup.

Co-authored-by: Cursor Agent
@vercel

vercel Bot commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

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

5 Skipped Deployments
Project Deployment Actions Updated
notra Skipped Skipped Sep 12, 2026 9:59am UTC
notra-agent Skipped Skipped Sep 12, 2026 9:59am UTC
notra-onboarding-agent Skipped Skipped Sep 12, 2026 9:59am UTC
notra-ui Skipped Skipped Sep 12, 2026 9:59am UTC
notra-web Skipped Skipped Sep 12, 2026 9:59am UTC

Request Review

@vercel
vercel Bot temporarily deployed to Preview – notra-onboarding-agent September 12, 2026 07:23 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-agent September 12, 2026 07:23 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra September 12, 2026 07:23 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-ui September 12, 2026 07:23 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-web September 12, 2026 07:23 Inactive
@github-actions github-actions Bot added apps/api Changes files in apps/api priority/normal Issue priority or pull request review urgency; maintainers decide type/chore PR change classification labels Sep 12, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 5 files

Confidence score: 3/5

  • In apps/api/src/routes/brand-identities.ts, Redis job creation or update failures can now surface as an unhandled 500 while leaving the newly inserted brand identity behind, creating an inconsistent persisted state. Restore the documented 503 response and clean up the inserted identity on failure.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/api/src/routes/brand-identities.ts">

<violation number="1" location="apps/api/src/routes/brand-identities.ts:344">
P2: When Redis job creation or job update fails, this delegated path now produces an unhandled 500 and leaves the newly inserted brand identity behind instead of returning the documented 503 and cleaning it up. Keep job lifecycle failures in the queue-failure recovery path so the identity is removed and the caller receives `Failed to queue brand identity analysis`.</violation>
</file>

Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.

Re-trigger cubic

Comment thread apps/api/src/programs/brand-identities.ts Outdated
throw new Error("Failed to create brand identity");
}
const result = await runBrandIdentityProgram(
createBrandIdentity({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: When Redis job creation or job update fails, this delegated path now produces an unhandled 500 and leaves the newly inserted brand identity behind instead of returning the documented 503 and cleaning it up. Keep job lifecycle failures in the queue-failure recovery path so the identity is removed and the caller receives Failed to queue brand identity analysis.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/routes/brand-identities.ts, line 344:

<comment>When Redis job creation or job update fails, this delegated path now produces an unhandled 500 and leaves the newly inserted brand identity behind instead of returning the documented 503 and cleaning it up. Keep job lifecycle failures in the queue-failure recovery path so the identity is removed and the caller receives `Failed to queue brand identity analysis`.</comment>

<file context>
@@ -352,115 +340,25 @@ brandIdentitiesRoutes.openapi(createBrandIdentityRoute, async (c) => {
-      throw new Error("Failed to create brand identity");
-    }
+  const result = await runBrandIdentityProgram(
+    createBrandIdentity({
+      db: c.get("db"),
+      organizationId: orgId,
</file context>

Route Redis job create/update failures through BrandAnalysisQueueFailedError
with the same rollback path as workflow failures (delete brand row, mark
job failed when applicable, return 503).

Add BrandIdentityInUseError when projects or geo content briefs reference
the identity; pre-migration delete surfaced raw FK errors for the same case.

Co-authored-by: Cursor Agent
@vercel
vercel Bot temporarily deployed to Preview – notra-web September 12, 2026 07:27 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-ui September 12, 2026 07:27 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-agent September 12, 2026 07:27 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra September 12, 2026 07:27 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-onboarding-agent September 12, 2026 07:27 Inactive
@github-actions

github-actions Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 14c3863.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 5 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread apps/api/src/programs/brand-identities.ts
Comment thread apps/api/src/programs/brand-identities.ts
Comment thread apps/api/src/utils/brand-identities.ts
Do not delete brand identity after workflow acceptance; post-workflow
Redis update failures return 503 only. Clean up partial Redis job keys
before workflow, and route delete failures through respondToBrandIdentityFailure.

Co-authored-by: Cursor Agent
@vercel
vercel Bot temporarily deployed to Preview – notra-web September 12, 2026 07:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra September 12, 2026 07:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-onboarding-agent September 12, 2026 07:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-ui September 12, 2026 07:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-agent September 12, 2026 07:32 Inactive

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 2 files (changes from recent commits).

Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread apps/api/src/programs/brand-identities.ts
Include installation account type/login in the GitHub integration query
used by publishChangelogToGitHub so merged main typechecks in CI.

Co-authored-by: Cursor Agent
Only roll back the brand identity when the dashboard explicitly rejects
workflow start (4xx or pre-flight configuration/auth failures). Transport,
timeout, and other ambiguous trigger errors mark the job failed and return
503 without deleting the row.

Co-authored-by: Cursor Agent
@vercel
vercel Bot temporarily deployed to Preview – notra-ui September 12, 2026 07:37 Inactive
@CLAassistant

CLAassistant commented Sep 12, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Use _tag-based type guards for workflow trigger rejection classification
instead of instanceof, matching schedules.ts patterns.

Refactor failBrandAnalysisQueue to Effect.fnUntraced for consistency
with integrations delete cleanup helper.
@cursor
cursor Bot force-pushed the cursor/effect-brand-identities branch from b807ef4 to 14c3863 Compare September 12, 2026 09:59
@vercel
vercel Bot temporarily deployed to Preview – notra September 12, 2026 09:59 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-onboarding-agent September 12, 2026 09:59 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-web September 12, 2026 09:59 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-ui September 12, 2026 09:59 Inactive
@vercel
vercel Bot temporarily deployed to Preview – notra-agent September 12, 2026 09:59 Inactive
@janburzinski
janburzinski merged commit 88911ab into main Sep 12, 2026
17 checks passed
@janburzinski
janburzinski deleted the cursor/effect-brand-identities branch September 12, 2026 10:02

This branch was previously deployed

5 inactive deployments
Preview – notra-agent — 14c38635 Deployed Sep 12, 2026 by vercel[bot]
Preview – notra-ui — 14c38635 Deployed Sep 12, 2026 by vercel[bot]
Preview – notra-web — 14c38635 Deployed Sep 12, 2026 by vercel[bot]
Preview – notra-onboarding-agent — 14c38635 Deployed Sep 12, 2026 by vercel[bot]
Preview – notra — 14c38635 Deployed Sep 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apps/api Changes files in apps/api priority/normal Issue priority or pull request review urgency; maintainers decide type/chore PR change classification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants