Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/events/ans-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ const EventPayloadSchemas: Readonly<Record<string, z.ZodType<NotificationPayload
workers_observability_real_time_issue: IssueNotificationPayload
}

export function payloadSchemaFor(alertType: string): z.ZodType<NotificationPayload> {
return EventPayloadSchemas[alertType] ?? AlertPayload
}

/**
* JSON Schema for an event descriptor, in the subset ChatGPT accepts for tool
* parameters: a plain object schema with no `$schema` and no top-level
Expand All @@ -194,7 +198,7 @@ export function alertEventDefinitions(catalog: unknown) {
description: `${alert.display_name}: ${alert.description}`,
delivery: ['webhook'],
inputSchema: descriptorSchema(AlertArguments),
payloadSchema: descriptorSchema(EventPayloadSchemas[alert.type])
payloadSchema: descriptorSchema(payloadSchemaFor(alert.type))
}))
}

Expand Down Expand Up @@ -495,7 +499,7 @@ export async function forwardAnsWebhook(
} catch {
return new Response(null, { status: 400 })
}
const parsed = (EventPayloadSchemas[subscription.alertType] ?? AlertPayload).safeParse(raw)
const parsed = payloadSchemaFor(subscription.alertType).safeParse(raw)
if (!parsed.success) {
// Shape and failing paths only: alert values can hold customer data.
console.log(
Expand Down
8 changes: 8 additions & 0 deletions tests/ans-bridge.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { z } from 'zod'
import { describe, expect, it, vi } from 'vitest'
import {
MAX_EVENT_BYTES,
alertEventDefinitions,
AlertPayload,
payloadSchemaFor,
SubscribeParams,
UnsubscribeParams,
forwardAnsWebhook,
Expand Down Expand Up @@ -233,6 +236,11 @@ describe('ANS synchronous delivery bridge', () => {
).toEqual([])
})

it('falls back to the generic alert payload for types without their own schema', () => {
expect(payloadSchemaFor('universal_ssl_event_type')).toBe(AlertPayload)
expect(() => z.toJSONSchema(payloadSchemaFor('universal_ssl_event_type'))).not.toThrow()
})

it('does not accept subscriptions to events without an implemented contract', async () => {
const deps = dependencies()
deps.loadSubscription = vi.fn(async () => ({
Expand Down