d3869e6694
POST /api/v1/companies/{companyId}/inbox-items/{id}/stamp registered itself
with scope documents:write but had no V1_ENDPOINT_SCOPES entry, and the
wrapper resolves the required scope from that map before it validates the
bearer token, so the route answered NOT_FOUND to every caller. Add the entry,
drop the three phantom entries that had no route (GET openapi.yaml, GET
companies/:companyId, GET companies/:companyId/events), and add a parity test
that pins the scope map to the endpoint registry in both directions, checks
every pattern against an existing route file, and checks every v1 route file
is imported by load-routes.ts.
The webhook event catalogue was hand-copied in three places and had drifted:
the fan-out handler delivered 28 events while the v1 create enum, the OpenAPI
spec, the generated agent skill and the docs page listed 24, so the four
reconciliation.* events could not be subscribed to. lib/webhooks/public-events.ts
is now the single source; the handler set, the Zod enum and the docs section
derive from it, with tests that pin each surface to the catalogue. The PATCH
webhook docs no longer tell agents to delete and recreate a webhook to rotate
its secret: POST .../rotate-secret exists.
Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
30 lines
1020 B
TypeScript
30 lines
1020 B
TypeScript
/**
|
|
* registerWebhookHandler() must subscribe to exactly the catalogue in
|
|
* lib/webhooks/public-events.ts: an event an agent can subscribe to via the
|
|
* API but that the handler never fans out would be silently undeliverable.
|
|
*/
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
vi.mock('@/lib/auth/api-keys', () => ({
|
|
createServiceClientNoCookies: vi.fn(() => ({ __client: true })),
|
|
}))
|
|
vi.mock('next/server', () => ({ after: vi.fn() }))
|
|
|
|
import { eventBus } from '@/lib/events/bus'
|
|
import { registerWebhookHandler } from '../handler'
|
|
import { PUBLIC_WEBHOOK_EVENTS } from '../public-events'
|
|
|
|
describe('registerWebhookHandler', () => {
|
|
beforeEach(() => {
|
|
eventBus.clear()
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
it('subscribes to every catalogued event type and nothing else', () => {
|
|
const on = vi.spyOn(eventBus, 'on')
|
|
registerWebhookHandler()
|
|
const subscribed = on.mock.calls.map(([eventType]) => eventType).sort()
|
|
expect(subscribed).toEqual([...PUBLIC_WEBHOOK_EVENTS].sort())
|
|
})
|
|
})
|