Skip to content

feat(web): webhook subscriptions CRUD UI + global nav expansion - #69

Merged
Roddygithub merged 14 commits into
mainfrom
feat/webhook-subscriptions-ui
Jul 24, 2026
Merged

Roddygithub merged 14 commits into
mainfrom
feat/webhook-subscriptions-ui

Conversation

@Roddygithub

Copy link
Copy Markdown
Owner

Summary

  • New CreateWebhookPanel Client Component: 3-phase state machine (closed -> form -> reveal) where the form opens on click, URL/description/filter JSON submit via POST /api/v1/webhooks, and the reveal phase shows the ONE-SHOT plaintext secret with copy-to-clipboard + a mandatory I have securely stored this secret acknowledgement checkbox before Done (which calls router.refresh() so the new row appears in the grid).
  • New WebhookSubscriptionsGrid Client Component (AG Grid): id / url / description / filter (key-sorted summary) / created_at columns + a per-row Revoke button. Calls DELETE /api/v1/webhooks/{id} then router.refresh().
  • Extended GET /api/v1/webhooks client (fetchWebhookSubscriptions) + createWebhook + revokeWebhook export (api/webhooks.ts).
  • Rewrote web/src/app/webhooks/page.tsx as a force-dynamic Server Component that Promise.allSettled-fetches subscriptions + DLQ in parallel with per-section error isolation (one section failing does NOT block the other).
  • Added /players + /players/compare + /webhooks + /account + /upload to the global header nav (layout.tsx). The pre-PR2 nav surfaced only Players + Compare.
  • Extracted shared formatDateTime util in web/src/lib/format.ts (DRY across WebhookDlqGrid + WebhookSubscriptionsGrid).

Commits

  1. feat(web): extract shared formatDateTime in lib/format + refactor DLQ grid
  2. feat(web): add WebhookSubscriptionRow/Out types + fetch/create/revoke API
  3. feat(web): CreateWebhookPanel -- 3-phase state machine + one-shot secret reveal
  4. feat(web): WebhookSubscriptionsGrid -- AG Grid table + revoke action
  5. feat(web): extend /webhooks to render subs + DLQ; expose 5 pages in header nav
  6. test(web): 13 webhook-UI tests (page + CreateWebhookPanel + SubscriptionsGrid)

Why the inline create modal (not a separate route)

The backend returns the plaintext secret ONCE on the 201 response (Fernet envelope encryption-at-rest for every later fetch). A multi-page wizard would require server-side storage of the in-flight secret to survive a refresh, which we explicitly avoid. The single Client Component keeps the plaintext secret in React state for the lifetime of the wizard and only crosses the network once.

Test plan

  • cd web && pnpm typecheck — passes (TypeScript valid).
  • cd web && pnpm exec vitest run tests/app/webhooks-page.test.tsx tests/components/CreateWebhookPanel.test.tsx tests/components/WebhookSubscriptionsGrid.test.tsx — 13/13 pass.
  • The 13 tests cover: happy-path subscriptions render, parallel-fetch error isolation (each section surfaces its own error), CreateWebhookPanel state-machine transitions (closed -> form -> reveal + ack-enables-Done), WebhookSubscriptionsGrid empty state + revoke happy + revoke failure.
  • Manual: /webhooks renders the 2 section cards; clicking + New subscription opens the form, mock-typing + submitting transitions to the reveal callout with the one-shot secret visible.

Out of scope (deferred)

  • subscribed_event_types filter UX is JSON-as-text only; a structured key=value UI is a v0.12 follow-up.
  • Bulk subscribe / multi-secret reveal (single one-shot secret at a time only).
  • Per-event-type PNG / favicon via the secret hex (the whsec_ prefix is the canonical GW2 community compatibility marker).

@Roddygithub
Roddygithub force-pushed the feat/webhook-subscriptions-ui branch from 6e65f2c to 4668ce1 Compare July 24, 2026 15:08
@Roddygithub Roddygithub reopened this Jul 24, 2026
@Roddygithub
Roddygithub force-pushed the feat/webhook-subscriptions-ui branch from 15a452b to b2c59f1 Compare July 24, 2026 16:46
roddy added 14 commits July 24, 2026 18:48
… grid

Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
… API

Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
…ret reveal

Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
…eader nav

Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
…ionsGrid)

Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
… Pydantic closed set)

Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
…pendabot notice

Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
Signed-off-by: Roddy GitHub <roddy@users.noreply.github.com>
… drop CODEOWNERS touch)

Signed-off-by: RoddyGitHub <roddy@users.noreply.github.com>
@Roddygithub
Roddygithub force-pushed the feat/webhook-subscriptions-ui branch from b2c59f1 to cfdd615 Compare July 24, 2026 16:48
@Roddygithub
Roddygithub merged commit a0fab75 into main Jul 24, 2026
11 checks passed
@Roddygithub
Roddygithub deleted the feat/webhook-subscriptions-ui branch July 24, 2026 16:58
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.

2 participants