Skip to content

feat: add Figma design previews and plugin issue linking#718

Open
jaeyunha wants to merge 3 commits into
stagingfrom
issue-583-p2-figma-design-previews-and-creat
Open

feat: add Figma design previews and plugin issue linking#718
jaeyunha wants to merge 3 commits into
stagingfrom
issue-583-p2-figma-design-previews-and-creat

Conversation

@jaeyunha

@jaeyunha jaeyunha commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds Figma plugin API endpoints for metadata, create issue, link issue, and unlink issue workflows.
  • Persists plugin-linked Figma sources as safe snapshot metadata and queues Figma metadata refresh jobs for pasted links, plugin links, and manual refreshes.
  • Documents the new endpoints/schemas in OpenAPI and regenerates the TypeScript SDK.
  • Keeps issue detail preview refresh behavior and safe source-link rendering intact.

Verification

  • node scripts/check-openapi-coverage.mjs passed.
  • node scripts/check-web-sdk-usage.mjs passed.
  • pnpm --filter @namuh-eng/expn-sdk typecheck passed.
  • pnpm --filter @namuh-eng/expn-sdk test passed.
  • pnpm --filter @exponential/web exec vitest run tests/issue-detail-view.test.tsx passed.
  • cd apps/api && PATH="/home/jaeyunha/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.10.linux-amd64/bin:$PATH" go test ./internal/figma ./internal/integrations passed.
  • make check is blocked by baseline syntax errors outside this PR's diff in apps/web/src/app/(app)/settings/integrations/page.tsx and apps/web/tests/integrations-view.test.tsx.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08b0ec54ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
_, err = tx.Exec(ctx, `
insert into provider_job (workspace_id, workspace_integration_id, provider, kind, status, payload, scheduled_at, updated_at)
values ($1::uuid, (select id from workspace_integration where workspace_id=$1::uuid and provider='figma' and status in ('connected','degraded') limit 1), 'figma', 'metadata_refresh', 'queued', $2::jsonb, now(), now())`, workspaceID, raw)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add the metadata_refresh job kind before enqueueing

When an issue description or comment contains a Figma URL, this enqueue path inserts provider_job.kind='metadata_refresh', but packages/proto/migrations/0007_integration_provider_lifecycle.sql still constrains kind to webhook_ingestion, outbound_delivery, backfill, or sync, and this commit does not alter that check. In those inputs the insert returns a constraint violation, SyncSources returns an error, and the surrounding issue/comment create or update rolls back instead of saving.

Useful? React with 👍 / 👎.

Comment on lines +61 to 63
if got := setupRequirement("figma"); got != nil {
t.Fatalf("configured figma requirement = %#v", got)
t.Setenv("AUTH_INTERCOM_ID", "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Close the Figma setupRequirement assertion

This if got := setupRequirement("figma"); got != nil { block is missing its closing brace before the Intercom setup checks, so the rest of TestSetupRequirement remains nested in the if and the following func TestCanManage is parsed inside the function body. As a result, the integrations test package will not compile once the Go toolchain parses this file.

Useful? React with 👍 / 👎.

@jaeyunha jaeyunha force-pushed the issue-583-p2-figma-design-previews-and-creat branch from 08b0ec5 to 0f66c68 Compare June 17, 2026 05:13

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f66c683b4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +443 to +445
_, err = tx.Exec(ctx, `
insert into provider_job (workspace_id, workspace_integration_id, provider, kind, status, payload, scheduled_at, updated_at)
values ($1::uuid, (select id from workspace_integration where workspace_id=$1::uuid and provider='figma' and status in ('connected','degraded') limit 1), 'figma', 'metadata_refresh', 'queued', $2::jsonb, now(), now())`, workspaceID, raw)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add a worker to process Figma metadata jobs

When a source is linked/created or the user clicks Refresh, this enqueue succeeds but nothing ever claims provider='figma'/kind='metadata_refresh': apps/api/cmd/api/main.go only starts Slack, MicrosoftTeams, Sentry, Salesforce, Front, Intercom, and Zendesk workers, and a repo-wide search for metadata_refresh only finds these enqueue sites. As a result, linked Figma cards never get refreshed name/thumbnail/error metadata even though the UI reports a refresh; add a Figma worker/claim loop or fetch the metadata synchronously before returning success.

Useful? React with 👍 / 👎.

Comment on lines +275 to +278
result, err := h.DB.Exec(r.Context(), `
delete from figma_source
where workspace_id=$1::uuid and issue_id=$2::uuid and container_type='plugin'
and (($3 <> '' and id=$3::uuid) or ($4 <> '' and normalized_url=$4))`, p.WorkspaceID, issue.ID, strings.TrimSpace(input.SourceID), normalizedURL)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Broadcast Figma unlink mutations to sync clients

When the plugin unlinks a Figma source while another client has the issue open, this delete is returned as successful without adding an operation entry, unlike the link path above which calls syncapi.InsertOperation after mutating figma_source. WebSocket/offline-sync clients therefore keep the stale preview card until a full issue refetch; wrap the delete in a transaction and insert an issue updated operation when rows are removed.

Useful? React with 👍 / 👎.

@jaeyunha

Copy link
Copy Markdown
Member Author

Controller disposition for current head 0f66c68: validation-blocked / rebase required; do not merge as-is.

Evidence:

Required before merge: rebase onto current origin/staging, resolve the OpenAPI/SDK and issue-detail conflicts without dropping #583 acceptance coverage, then rerun the focused verification from the PR body plus any conflict-adjacent tests.

jaeyunha added 2 commits June 17, 2026 00:33
…pair

# Conflicts:
#	apps/web/src/components/issue-detail-view.tsx
#	packages/proto/openapi.yaml
#	packages/sdk/src/generated.ts
@jaeyunha

Copy link
Copy Markdown
Member Author

Controller update: conflict repaired on current head a878ddb. PR is now MERGEABLE/CLEAN and origin/staging is an ancestor of the PR head. Focused checks passed: OpenAPI coverage, web SDK guard, SDK typecheck/test/build, issue-detail Vitest, and Go tests for internal/figma + internal/integrations. Remaining blocker is broad make check baseline syntax errors outside this PR diff in apps/web/src/app/(app)/settings/integrations/page.tsx and apps/web/tests/integrations-view.test.tsx.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a878ddb4f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

problem.Write(w, http.StatusInternalServerError, "Create Figma issue failed", err.Error())
return
}
if _, err := syncapi.InsertOperation(r.Context(), tx, p.WorkspaceID, "issue", issue.ID, "created", issue, p.UserID); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Publish Figma plugin issue operations

When the Figma plugin creates an issue, this inserts an operation but discards it and returns without calling syncapi.PublishOperations after the commit; the link handler below does the same. I checked apps/api/internal/sync/handler.go: connected WebSocket clients only receive live updates from the Redis publish path, and DB rows are only replayed when they reconnect. Thus a user with the team list or issue open won't see plugin-created issues/links until a reconnect or manual refresh, unlike the normal issue create path which publishes the inserted op.

Useful? React with 👍 / 👎.

Comment on lines +8301 to +8305
properties:
issueId: { type: string, format: uuid }
identifier: { type: string }
sourceId: { type: string, format: uuid }
source: { $ref: '#/components/schemas/FigmaPluginSourceInput' }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require the source for Figma link requests

For POST /integrations/figma/plugin/links, the handler immediately calls normalizeFigmaPluginSource(input.Source), so a request that follows this schema with only issueId/identifier or sourceId compiles in the generated SDK but reaches the server with an empty source.url and is rejected as 400. Since DELETE can use sourceId but POST cannot, split the schemas or mark source required for the link operation so plugin clients don't generate invalid link calls.

Useful? React with 👍 / 👎.

@jaeyunha

Copy link
Copy Markdown
Member Author

Controller disposition for current head a878ddb: validation-blocked / rebase required; do not merge as-is.

Current blocker:

Required before merge: rebase or rebuild on fresh origin/staging, keep only the intended #583 API/web/OpenAPI/SDK deltas, rerun the focused Figma/API/web/SDK gates, and update this PR head.

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