Skip to content

Fix webhook list empty URL column and truncate long event lists#134

Merged
nicknisi merged 4 commits into
mainfrom
devin/1777384556-fix-webhook-list-url
Apr 28, 2026
Merged

Fix webhook list empty URL column and truncate long event lists#134
nicknisi merged 4 commits into
mainfrom
devin/1777384556-fix-webhook-list-url

Conversation

@nicknisi
Copy link
Copy Markdown
Member

@nicknisi nicknisi commented Apr 28, 2026

Summary

Fixes #133.

workos webhook list shows an empty URL column because the WorkOS API returns endpoint_url in webhook endpoint responses, but the CLI reads ep.url (which is undefined). Additionally, when a webhook is subscribed to many events, the Events column joins all event names into a single cell that can exceed the terminal width.

Changes:

  • WebhookEndpoint interface (src/lib/workos-client.ts): Renamed urlendpoint_url to match the real API response shape.
  • webhook.ts list command: Read ep.endpoint_url instead of ep.url; truncate events at whole-token boundaries with a hidden count suffix (e.g. event.a, event.b, … (+3 more)).
  • Emulator entity/helpers/routes: Renamed urlendpoint_url throughout; emulator POST/PUT accept both endpoint_url (matching real API) and url (backwards-compat fallback).
  • Seed config: WorkOSSeedWebhookEndpoint accepts both endpoint_url and deprecated url; seedFromConfig resolves with fallback, validates presence and type.
  • Tests: Updated all mocks and assertions to use endpoint_url; added regression tests for legacy url input on create and update, and for event truncation.

Review & Testing Checklist for Human

  • Verify against the real WorkOS API that GET /webhook_endpoints returns endpoint_url (not url) — the fix is based on API docs + the issue report
  • Run workos webhook list against a real environment with multiple webhooks subscribed to many events and confirm the URL column is populated and events are truncated cleanly
  • Confirm the emulator still works end-to-end (workos emulate → create/list/delete webhook endpoints)

Notes

All 1618 tests pass, typecheck passes, build passes.

Link to Devin session: https://app.devin.ai/sessions/c4287ca8c287477290199d58c4329b6d
Requested by: @nicknisi

…ists

The WorkOS API returns endpoint_url (not url) in webhook endpoint
responses. The CLI was reading ep.url which resolved to undefined,
causing an empty URL column in workos webhook list output.

- Rename url to endpoint_url in WebhookEndpoint interface and emulator
  entity to match the real API response shape
- Update webhook list command to read ep.endpoint_url
- Truncate long event lists at 60 chars in table output
- Update emulator routes to accept endpoint_url (with url fallback)
- Update all related tests and mocks

Closes #133

Co-Authored-By: nick.nisi@workos.com <nick@nisi.org>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

📝 Walkthrough

Walkthrough

Webhook endpoint URL property renamed from url to endpoint_url across CLI, client types, emulator, and tests; CLI list now displays endpoint_url and truncates the joined Events cell to a 60-character budget, appending a +N more indicator when events are omitted.

Changes

Cohort / File(s) Summary
Type Definitions & Client
src/lib/workos-client.ts
Renamed WebhookEndpoint.urlendpoint_url; updated client typings for webhook create/list.
CLI Command & Tests
src/commands/webhook.ts, src/commands/webhook.spec.ts
List rows now use endpoint_url for URL column; Events column enforces a 60-character display budget and appends a +N more indicator when truncated; tests updated/added to assert these behaviors.
Emulator Routes & Tests
src/emulate/workos/routes/webhook-endpoints.ts, src/emulate/workos/routes/webhook-endpoints.spec.ts
Create/update handlers accept endpoint_url with url as legacy fallback; validation adjusted; DB writes and tests updated to store endpoint_url; added tests verifying legacy url is accepted and normalized.
Emulator Entities & Seed
src/emulate/workos/entities.ts, src/emulate/workos/index.ts
WorkOSWebhookEndpoint and seed types updated to use endpoint_url; seeding resolves URL from endpoint_url or deprecated url, erroring if neither present.
Event Bus & Delivery Tests
src/emulate/workos/event-bus.ts, src/emulate/workos/event-bus.spec.ts
Event delivery posts to endpoint.endpoint_url instead of endpoint.url; test fixtures updated accordingly.
Store & Helpers
src/emulate/workos/store.ts, src/emulate/workos/helpers.ts
Collection indexing and formatWebhookEndpoint now use/emit endpoint_url instead of url.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed Title accurately describes the two main fixes: correcting the URL column display and truncating long event lists for the webhook list command.
Linked Issues check ✅ Passed PR comprehensively addresses issue #133 requirements: fixes empty URL column by using endpoint_url, truncates long event lists at whole boundaries with +N suffix, and aligns emulator with API response shape while maintaining backward compatibility.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #133: webhook URL field rename (url→endpoint_url) and event list truncation implementation across entities, routes, helpers, and tests with appropriate backward compatibility support.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1777384556-fix-webhook-list-url

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

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

This PR fixes a bug where workos webhook list displayed an empty URL column because the CLI was reading ep.url while the WorkOS API returns endpoint_url. The rename is applied consistently across the client interface, emulator entity, store, event-bus, helpers, and all tests. A secondary improvement truncates long event lists to a 60-character display budget with an accurate (+N more) hidden-count suffix. Backward compatibility for callers still passing url is preserved in HTTP routes and seedFromConfig.

Confidence Score: 5/5

Safe to merge — the rename is applied uniformly across all layers, backward-compat fallbacks are in place, and the previously flagged issues in prior review threads have been resolved.

No P0 or P1 issues found. The urlendpoint_url rename is consistent across entity, store, helpers, event-bus, routes, client interface, and all tests. The truncation logic correctly computes hidden = total - visible (not total), the seedFromConfig fallback was added, and legacy-url backward-compat tests are included. All previously flagged thread concerns are addressed.

No files require special attention.

Important Files Changed

Filename Overview
src/lib/workos-client.ts Renamed urlendpoint_url in WebhookEndpoint interface to match real API shape — the root fix for the bug.
src/commands/webhook.ts Reads ep.endpoint_url correctly; adds 60-char event truncation with accurate hidden count suffix.
src/emulate/workos/routes/webhook-endpoints.ts POST and PUT routes accept both endpoint_url and legacy url with proper fallback and validation.
src/emulate/workos/index.ts WorkOSSeedWebhookEndpoint interface supports both endpoint_url (new) and deprecated url; seedFromConfig resolves with fallback and validates presence.
src/emulate/workos/entities.ts Entity interface WorkOSWebhookEndpoint renamed urlendpoint_url consistently.
src/emulate/workos/event-bus.ts Delivery fetch updated to endpoint.endpoint_url — correct and necessary companion to the entity change.
src/emulate/workos/store.ts Collection index key updated from url to endpoint_url, consistent with entity rename.
src/emulate/workos/helpers.ts formatWebhookEndpoint now maps ep.endpoint_url correctly in the formatted response object.
src/commands/webhook.spec.ts Mock updated to endpoint_url; regression tests for truncation (multi-event and long-single-event) added.
src/emulate/workos/routes/webhook-endpoints.spec.ts All route tests updated; new backwards-compat tests for legacy url on create and update added.
src/emulate/workos/event-bus.spec.ts All event-bus test fixtures updated to endpoint_url, no logic changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["CLI: runWebhookList(apiKey)"] --> B["WorkOS SDK\nclient.webhooks.list()"]
    B --> C["WebhookEndpoint\n{ endpoint_url, events, ... }"]
    C --> D{joined events\n≤ 60 chars?}
    D -- Yes --> E["Row: id, endpoint_url,\nfull events, created_at"]
    D -- No --> F["Greedy pack visible[]\nwhile len ≤ 60"]
    F --> G["suffix = ', … (+hidden more)'"]
    G --> H["Row: id, endpoint_url,\ntruncated events, created_at"]
    E --> I["formatTable() → console.log"]
    H --> I

    subgraph Emulator["Emulator (backwards-compat)"]
        J["POST/PUT body\n{url} or {endpoint_url}"] --> K["endpoint_url ?? url"]
        K --> L["WorkOSWebhookEndpoint\n{ endpoint_url }"]
        M["seedFromConfig\n{url} or {endpoint_url}"] --> N["endpoint_url ?? url\n+ required check"]
        N --> L
    end
Loading

Reviews (4): Last reviewed commit: "fix: tighten seed validation for webhook..." | Re-trigger Greptile

greptile-apps[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

- Truncate events at whole-token boundaries and show hidden count
  instead of total (e.g. '… (+3 more)' not '… (+5)')
- Add url fallback in seedFromConfig for legacy seed configs
- Add regression tests for legacy url input on POST/PUT

Co-Authored-By: nick.nisi@workos.com <nick@nisi.org>
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.

♻️ Duplicate comments (1)
src/emulate/workos/index.ts (1)

320-331: ⚠️ Potential issue | 🟠 Major

Tighten seed validation before insert.

if (!endpointUrl) still lets truthy non-string values through, so malformed seed configs can persist invalid webhook endpoints. Match the route handler’s typeof guard here before inserting.

🔧 Proposed fix
-      const endpointUrl = whConfig.endpoint_url ?? whConfig.url;
-      if (!endpointUrl) {
+      const endpointUrl = whConfig.endpoint_url ?? whConfig.url;
+      if (!endpointUrl || typeof endpointUrl !== 'string') {
         throw new Error('workos seed config: webhookEndpoints[].endpoint_url is required');
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/emulate/workos/index.ts` around lines 320 - 331, The current seed logic
accepts truthy non-string endpoint values; before calling
ws.webhookEndpoints.insert when building endpointUrl from whConfig.endpoint_url
?? whConfig.url, validate that the resolved endpointUrl is a string (e.g.,
typeof endpointUrl === 'string') and throw the same error if not; update the
check around endpointUrl (and/or inspect whConfig.endpoint_url and whConfig.url
individually) so only string endpoint URLs are inserted by
ws.webhookEndpoints.insert.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/emulate/workos/index.ts`:
- Around line 320-331: The current seed logic accepts truthy non-string endpoint
values; before calling ws.webhookEndpoints.insert when building endpointUrl from
whConfig.endpoint_url ?? whConfig.url, validate that the resolved endpointUrl is
a string (e.g., typeof endpointUrl === 'string') and throw the same error if
not; update the check around endpointUrl (and/or inspect whConfig.endpoint_url
and whConfig.url individually) so only string endpoint URLs are inserted by
ws.webhookEndpoints.insert.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c51edaf8-2f98-495f-b5ee-2ea1782d1753

📥 Commits

Reviewing files that changed from the base of the PR and between 6be28f1 and 50ed023.

📒 Files selected for processing (3)
  • src/commands/webhook.ts
  • src/emulate/workos/index.ts
  • src/emulate/workos/routes/webhook-endpoints.spec.ts

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

@devin-ai-integration
Copy link
Copy Markdown
Contributor

Original prompt from nick.nisi@workos.com

Can you take this issue? #133 - validate that it's legit and then work on a fix.

@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

nicknisi and others added 2 commits April 28, 2026 16:49
@nicknisi nicknisi merged commit 73804ed into main Apr 28, 2026
7 checks passed
@nicknisi nicknisi deleted the devin/1777384556-fix-webhook-list-url branch April 28, 2026 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

workos webhook list shows an empty URL column and breaks table layout for long Events values

1 participant