feat: outgoing webhooks
Owners and admins can point a project at other systems: a signed JSON POST (HMAC-SHA256 of the body) when tickets, comments, releases or sprints change, filtered by event or family. Deliveries are retried a couple of times, the last one is shown, and a ping can be sent from the settings. Private addresses are refused unless WEBHOOKS_ALLOW_PRIVATE is set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -167,6 +167,14 @@ stateDiagram-v2
|
||||
actor `system`); el mismo enlace solo vuelve a contar si cambia (una PR fusionada). Proyecto desconocido,
|
||||
integración apagada o firma mala responden igual: 403. El secreto vive en MongoDB (`git_integrations`), no en el
|
||||
event store.
|
||||
- **Webhooks salientes**: owners y admins dan de alta URLs (hasta 20 por proyecto) suscritas a eventos
|
||||
(`issue.created`, `issue.status_changed`, `comment.added`, `release.shipped`, `sprint.closed`… — la lista en
|
||||
`webhookEvents` / `GET /api/webhook-events`), a familias (`issue.*`) o a todo (`*`). Cada envío es un `POST` JSON con
|
||||
`event`, `deliveryId`, `occurredAt`, `actorId`, `project`, `issue` (si va de un ticket) y `data` (los campos del evento),
|
||||
y las cabeceras `X-TaskStream-Event`, `X-TaskStream-Delivery` y `X-TaskStream-Signature: sha256=<HMAC del cuerpo con el
|
||||
secreto>`. El secreto solo se muestra al crearlo. Se reintenta a los 2 y 10 s (no ante un 4xx), con 5 s de espera
|
||||
máxima; se guarda el último envío. Salen en segundo plano y no son duraderos: si la API se reinicia a mitad, ese
|
||||
envío se pierde. No llaman a direcciones privadas salvo con `WEBHOOKS_ALLOW_PRIVATE=true`.
|
||||
- **Límite WIP**: cada estado puede tener `wipLimit` (1-999) en la configuración del proyecto. Es un aviso, no un
|
||||
bloqueo: la API acepta pasarse y el tablero marca la columna.
|
||||
- **Sprints**: los planifica y gestiona quien administra el proyecto (owner o admin); mete tickets cualquier miembro.
|
||||
@@ -259,6 +267,7 @@ que funcionan también sin token.
|
||||
| `publicProjects` | Proyectos públicos (sin token) |
|
||||
| `project(idOrKey)` | Un proyecto (mío, o público) con su `settings`. Campos calculados: `board(releaseId, assigneeId, unassigned, area, types, priorities, labels, search, perColumn)`, `stats`, `analytics(days)`, `releases` |
|
||||
| `issues(filter, limit, offset)` | Búsqueda de tickets (estado, tipo, área, prioridad, persona, release, etiquetas, ticket padre, texto); `sort: RANK` para el orden del backlog |
|
||||
| `webhooks(projectId)`, `webhookEvents` | Webhooks salientes del proyecto (owners y admins) y los eventos a los que se pueden suscribir |
|
||||
| `gitIntegration(projectId)` | Si el webhook de Git está activo, su ruta y (para owners y admins) el secreto |
|
||||
| `sprints(projectId)`, `sprint(id)` | Sprints del proyecto (en curso, planificados, cerrados). Campos calculados: `progress`, `burndown`, `issues` |
|
||||
| `savedFilters(projectId)` | Mis vistas guardadas del tablero y las compartidas con el proyecto |
|
||||
@@ -276,6 +285,7 @@ Todas devuelven `CommandResult { id, key, version }`.
|
||||
| Proyectos | `createProject`, `updateProject`, `updateProjectSettings`, `deleteProject(confirmKey)`, `addProjectMember`, `changeProjectMemberRole`, `removeProjectMember` |
|
||||
| Tickets | `createIssue`, `updateIssue`, `changeIssueStatus`, `assignIssue`, `linkIssues`, `unlinkIssues`, `setIssueRelease`, `setIssueParent`, `rankIssue`, `addChecklistItem`, `updateChecklistItem`, `removeChecklistItem`, `watchIssue`, `unwatchIssue`, `removeAttachment` (subir: por REST) |
|
||||
| Comentarios | `addComment`, `editComment`, `deleteComment` |
|
||||
| Webhooks | `createWebhook` (devuelve el secreto), `updateWebhook`, `deleteWebhook`, `testWebhook` |
|
||||
| Git | `enableGitIntegration` (también para cambiar el secreto), `disableGitIntegration` |
|
||||
| Sprints | `createSprint`, `updateSprint`, `startSprint`, `closeSprint(carryOverToSprintId)`, `deleteSprint`, `setIssueSprint` |
|
||||
| Vistas | `saveFilter(input)` (devuelve el id), `deleteSavedFilter(id)` |
|
||||
@@ -489,6 +499,7 @@ Proyectos y tickets se pueden indicar por **id o por clave** (`WEB`, `WEB-12`).
|
||||
| Adjuntos | `POST /api/issues/{issue}/attachments` (multipart: `file` y opcional `commentId`), `GET/DELETE /api/issues/{issue}/attachments/{id}` |
|
||||
| Releases | `GET /api/me/releases` (próximas), `GET/POST /api/projects/{project}/releases`, `GET/PATCH /api/releases/{id}`, `PUT …/notes`, `GET …/notes/draft`, `…/progress`, `…/burnup`, `…/issues`, `POST …/publish`, `POST …/archive` |
|
||||
| Explorar | `GET /api/explore/projects` (proyectos públicos, sin token) |
|
||||
| Webhooks | `GET /api/webhook-events`, `GET/POST /api/projects/{project}/webhooks`, `PATCH/DELETE /api/outgoing-webhooks/{id}`, `POST …/test` |
|
||||
| Git | `GET/POST/DELETE /api/projects/{project}/git-integration`, `POST /api/webhooks/git/{project}` (lo llama el host de Git) |
|
||||
| Sistema | `GET /api/health`, `GET /api/auth/config`, `POST /api/auth/token`, `POST /api/webhooks/pireon` |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user