[ { "id": "F001", "description": "Create migration adding `inbound_webhooks` table (Citus-distributed by tenant, composite PK including tenant)", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F002", "description": "Create migration adding `inbound_webhook_deliveries` table (Citus-distributed by tenant)", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F003", "description": "Reserved-integration-type registry/check so user webhook slugs cannot collide with bundled integrations' `tenant_external_entity_mappings.integration_type` values (ninjaone, tactical_rmm, tanium, xero, qbo, entra, etc.)", "implemented": true, "prdRefs": ["Open Questions", "Acceptance Criteria (Definition of Done)"] }, { "id": "F004", "description": "Helper `lookupAlgaEntityByExternalId(tenant, webhookSlug, entityType, externalId)` queries `tenant_external_entity_mappings` (no new entity columns)", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F005", "description": "Helper `writeEntityMapping(tenant, webhookSlug, entityType, algaId, externalId, realm?)` for create-actions to register mappings", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F006", "description": "Add `inbound_webhook` permission resource and seed for admin role", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F007", "description": "Add PostHog feature flag `inbound_webhooks_enabled`", "implemented": true, "prdRefs": ["Rollout / Migration"] }, { "id": "F010", "description": "TypeScript types: `InboundWebhookConfig`, `InboundWebhookDelivery`, `AuthConfig` union, `HandlerConfig` union", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F011", "description": "Zod schemas for inbound webhook upsert input (per auth_type and handler_type)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F012", "description": "Server action `listInboundWebhooks` (withAuth, tenant-scoped)", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F013", "description": "Server action `getInboundWebhook(id)`", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F014", "description": "Server action `upsertInboundWebhook(input)` — slug uniqueness check per tenant", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F015", "description": "Server action `deleteInboundWebhook(id)`", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F016", "description": "Server action `rotateInboundWebhookSecret(id)` (writes new secret to vault, returns once)", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F017", "description": "Server action `setInboundWebhookActiveState(id, active)`", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F018", "description": "Server action `listInboundDeliveries(filter, page)`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F019", "description": "Server action `getInboundDelivery(id)`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F020", "description": "Server action `replayInboundDelivery(id)` — re-dispatches against current config, links new row", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F021", "description": "Server action `captureSamplePayload(id)` (toggles capture mode for 5 min)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F022", "description": "Server action `clearSamplePayload(id)`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F023", "description": "Server action `sendInboundWebhookTest(id, body, headers)` (synthetic in-process dispatch)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F030", "description": "Inbound HTTP route handler at `/api/inbound/[tenantSlug]/[webhookSlug]` (POST/PUT/PATCH)", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F031", "description": "Tenant slug → tenant resolver with caching", "implemented": true, "prdRefs": ["Open Questions"] }, { "id": "F032", "description": "Webhook slug → config lookup (per-tenant, indexed)", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F033", "description": "Auth verifier: HMAC-SHA256 (configurable header), timing-safe compare", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F034", "description": "Auth verifier: Bearer token, timing-safe compare", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F035", "description": "Auth verifier: IP allowlist (CIDR matching)", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F036", "description": "Auth verifier: Shared-secret-in-path token", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F037", "description": "Unified 401 response for unknown slug + bad auth (no enumeration)", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F038", "description": "Idempotency key extractor: header source", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F039", "description": "Idempotency key extractor: JSONata expression on body", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F040", "description": "Dedup lookup within configurable window; return 200 no-op for duplicates", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F041", "description": "Delivery row persisted before dispatch (so failures are visible)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F042", "description": "Per-webhook rate limiter (Redis token bucket, default 600/min)", "implemented": true, "prdRefs": ["Non-functional Requirements"] }, { "id": "F043", "description": "Header filtering on persistence (strip Cookie/Authorization)", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F044", "description": "Sample payload capture: first verified body within active capture window saved to config", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F050", "description": "Action registry core: `registerAction(def)`, `listActions()`, `getAction(name)` at `server/src/lib/inboundWebhooks/actions/registry.ts`", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F051", "description": "Action definition type: `{ name, entityType, displayName, description, targetFields[], handle() }`", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F052", "description": "Target field schema type: `{ name, type, required, description, enumValues? }`", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F053", "description": "Bootstrap import of all package-contributed inbound action registrations on server start", "implemented": true, "prdRefs": ["Data / API / Integrations"] }, { "id": "F054", "description": "Field mapping evaluator: runs JSONata against request body per target field", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F055", "description": "Mapping validation errors recorded as failed delivery with clear error", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F056", "description": "Lookup-miss in `*ByExternalId` actions returns failed delivery (not silent no-op)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1010", "description": "Ticket action: `createTicket` (registered in `packages/tickets/src/actions/inboundActions.ts`)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1011", "description": "Ticket action: `updateTicketByExternalId` (status, priority, assignment, board)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1012", "description": "Ticket action: `addTicketCommentByExternalId`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1013", "description": "Ticket action: `changeTicketStatusByExternalId`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1020", "description": "Client action: `upsertClientByExternalId`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1021", "description": "Client action: `setClientActiveByExternalId`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1030", "description": "Contact action: `upsertContactByExternalId` (uses `client_users` table)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1040", "description": "Asset action: `upsertAssetByExternalId` — delegates to `ingestNormalizedRmmDeviceSnapshot` when payload is RMM-shaped", "implemented": true, "prdRefs": ["Functional Requirements", "Goals"] }, { "id": "F1041", "description": "Asset action: plain (non-RMM) asset upsert path for generic asset payloads", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1050", "description": "Invoice action: `markInvoicePaidByExternalId`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1051", "description": "Invoice action: `updateInvoiceStatusByExternalId`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1052", "description": "Invoice action: idempotent mark-paid (no double-mark on already-paid invoice)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1060", "description": "Time entry action: `createTimeEntry`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1070", "description": "Project task action: `createProjectTask`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1071", "description": "Project task action: `updateProjectTaskStatusByExternalId`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F1080", "description": "Cross-cutting action: `addTagToEntityByExternalId` (accepts target entity_type + external_id + tag value)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F060", "description": "Workflow handler dispatcher: starts a workflow run with the normalized envelope", "implemented": true, "prdRefs": ["Functional Requirements", "Open Questions"] }, { "id": "F061", "description": "Envelope builder: `{source, body, headers, verified, delivery_id, idempotency_key, received_at}`", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F062", "description": "Delivery row links to workflow_run_id once started", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F063", "description": "Workflow trigger failure (engine error) recorded on delivery; subsequent workflow run failures do NOT mark delivery failed", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F070", "description": "Webhook payload context adapter for expression editor (`webhookPayloadContextAdapter.ts`)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F071", "description": "Adapter introspects captured sample payload to build path tree", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F072", "description": "Reuse `ExpressionTextArea` from workflow designer for field mapping inputs", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F080", "description": "Settings page refactor: tabbed `AdminWebhooksSetup` (Inbound | Outbound)", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F081", "description": "Inbound webhooks list view (table mirrors outbound shape)", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F082", "description": "Inbound webhook create/edit dialog with Identity section", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F083", "description": "Auth section: dropdown (HMAC/Bearer/IP/Path) + conditional sub-form", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F084", "description": "Auth secret one-time-display modal after creation", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F085", "description": "Idempotency section (key source dropdown + value input)", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F086", "description": "Handler section conditional rendering: direct_action vs workflow", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F087", "description": "Direct-action UI: action dropdown populated from registry", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F088", "description": "Direct-action UI: target field rows with `ExpressionTextArea` per field", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F089", "description": "Sample payload capture button + status indicator", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F090", "description": "Sample payload tree side panel (click-to-insert path)", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F091", "description": "Workflow handler UI: workflow dropdown + envelope info card", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F092", "description": "Active state toggle + auto-disable indicator", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F093", "description": "Delivery log list (mirrors outbound's table layout)", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F094", "description": "Delivery detail drawer (request/response/headers/latency/error)", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F095", "description": "Replay button on delivery rows", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F096", "description": "Synthetic test request UI (send custom body/headers from dialog)", "implemented": true, "prdRefs": ["Functional Requirements"] }, { "id": "F097", "description": "All new UI strings via `t('...')` i18n", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F098", "description": "All interactive elements have kebab-case `id` attributes", "implemented": true, "prdRefs": ["UX / UI Notes"] }, { "id": "F100", "description": "Feature flag gate on Settings tab visibility", "implemented": true, "prdRefs": ["Rollout / Migration"] }, { "id": "F101", "description": "Feature flag gate on `/api/inbound/*` route (returns 404 when disabled)", "implemented": true, "prdRefs": ["Rollout / Migration"] }, { "id": "F102", "description": "Permission check on every server action (`withAuth` + `hasPermission`)", "implemented": true, "prdRefs": ["Security / Permissions"] }, { "id": "F200", "description": "REST API route: `GET /api/v1/inbound-webhooks` (list)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F201", "description": "REST API route: `POST /api/v1/inbound-webhooks` (create)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F202", "description": "REST API route: `GET/PUT/DELETE /api/v1/inbound-webhooks/{id}`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F203", "description": "REST API route: `POST /api/v1/inbound-webhooks/{id}/rotate-secret`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F204", "description": "REST API route: `POST /api/v1/inbound-webhooks/{id}/test` (synthetic dispatch)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F205", "description": "REST API route: `POST/DELETE /api/v1/inbound-webhooks/{id}/capture-sample`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F206", "description": "REST API route: `GET /api/v1/inbound-webhooks/{id}/deliveries` (paginated, filterable)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F207", "description": "REST API route: `GET /api/v1/inbound-webhooks/{id}/deliveries/{deliveryId}`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F208", "description": "REST API route: `POST /api/v1/inbound-webhooks/{id}/deliveries/{deliveryId}/replay`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F209", "description": "REST API route: `GET /api/v1/inbound-webhooks/actions` (action discovery — returns registry contents with target field schemas)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F210", "description": "OpenAPI registry file: `server/src/lib/api/openapi/routes/inboundWebhooks.ts` with all management endpoints", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F211", "description": "OpenAPI registration for templated receiver endpoint `/api/inbound/{tenantSlug}/{webhookSlug}` (headers, response codes, generic JSON body)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F212", "description": "OpenAPI component schema: `InboundWebhookConfig`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F213", "description": "OpenAPI component schemas: `InboundWebhookCreateInput`, `InboundWebhookUpdateInput`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F214", "description": "OpenAPI component schema: `InboundWebhookAuthConfig` (discriminated union by auth_type)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F215", "description": "OpenAPI component schema: `InboundWebhookHandlerConfig` (discriminated union by handler_type)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F216", "description": "OpenAPI component schema: `InboundWebhookDelivery`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F217", "description": "OpenAPI component schemas: `InboundActionDefinition`, `InboundActionTargetField`", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F218", "description": "OpenAPI component schema: `WorkflowWebhookEnvelope` (envelope shape workflow handlers receive)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F220", "description": "Regenerate `sdk/docs/openapi/alga-openapi.{ce,ee}.{yaml,json}` and commit", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F221", "description": "Contract test for each management route (pattern: `projectTasksOpenApi.contract.test.ts`)", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F222", "description": "Contract test for action discovery endpoint", "implemented": true, "prdRefs": ["Public REST API and OpenAPI registration"] }, { "id": "F223", "description": "REST API routes share the same `withAuth` + permission checks as server actions; no parallel auth path", "implemented": true, "prdRefs": ["Security / Permissions"] } ]