@shipfox/api-triggers 10.1.0 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  $ shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js
2
- Successfully compiled: 58 files with swc (388.21ms)
3
- 2026-07-28T09:17:44.226Z [INFO] asset workflow-bundle-69915b80080285c7230d.js 3.17 MiB [emitted] [immutable] (name: main)
2
+ Successfully compiled: 58 files with swc (490.65ms)
3
+ 2026-07-28T22:45:34.093Z [INFO] asset workflow-bundle-69915b80080285c7230d.js 3.17 MiB [emitted] [immutable] (name: main)
4
4
  orphan modules 33.5 KiB [orphan] 21 modules
5
5
  runtime modules 1.13 KiB 5 modules
6
6
  modules by path ../../../node_modules/.pnpm/ 970 KiB 196 modules
@@ -13,6 +13,6 @@ optional modules 30 bytes [optional]
13
13
  __temporal_custom_payload_converter (ignored) 15 bytes [optional] [built] [code generated]
14
14
  __temporal_custom_failure_converter (ignored) 15 bytes [optional] [built] [code generated]
15
15
  ../../shared/node/temporal/dist/workflow-error-interceptor.js 1.21 KiB [built] [code generated]
16
- webpack 5.107.2 compiled successfully in 6857 ms
17
- 2026-07-28T09:17:44.232Z [INFO] Workflow bundle created { size: '3.17MB' }
16
+ webpack 5.107.2 compiled successfully in 7195 ms
17
+ 2026-07-28T22:45:34.114Z [INFO] Workflow bundle created { size: '3.17MB' }
18
18
  /home/runner/work/shipfox/shipfox/libs/api/triggers/dist/temporal/workflows/index.js: 3329015 bytes
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @shipfox/api-triggers
2
2
 
3
+ ## 11.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 25158c8: Carry workspace lifecycle status in JWT membership claims and enforce suspended or inactive access at the stateless workspace gate while keeping access-token verification stateless.
8
+
9
+ `getAuthenticatedSessionContext()` now reads refresh-session metadata from verified access-token claims without checking active refresh-session state; revoking a refresh session does not invalidate an already-issued access token.
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [71d9ba4]
14
+ - Updated dependencies [25158c8]
15
+ - @shipfox/expression@1.2.1
16
+ - @shipfox/api-auth-context@11.0.0
17
+ - @shipfox/api-definitions-dto@11.0.0
18
+
19
+ ## 10.2.0
20
+
21
+ ### Patch Changes
22
+
23
+ - @shipfox/api-auth-context@10.2.0
24
+
3
25
  ## 10.1.0
4
26
 
5
27
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"fire-manual.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/fire-manual.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AAanF,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,qBAAqB,mDAkF5E"}
1
+ {"version":3,"file":"fire-manual.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/fire-manual.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AAanF,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,qBAAqB,mDA0F5E"}
@@ -1,4 +1,4 @@
1
- import { requireUserContext } from '@shipfox/api-auth-context';
1
+ import { requireUserContext, requireWorkspaceResourceAccess } from '@shipfox/api-auth-context';
2
2
  import { fireManualTriggerBodySchema, fireManualTriggerResponseSchema } from '@shipfox/api-triggers-dto';
3
3
  import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
4
  import { z } from 'zod';
@@ -70,10 +70,18 @@ export function createFireManualTriggerRoute(workflows) {
70
70
  const { definitionId } = request.params;
71
71
  const userContext = requireUserContext(request);
72
72
  const subscription = await getManualSubscriptionByDefinitionId(definitionId);
73
- // 404 covers both "no such manual trigger" and "not your workspace" to avoid leaking existence.
74
- if (!subscription || !userContext.canAccess(subscription.workspaceId)) {
73
+ // Missing triggers and memberships remain 404 to avoid leaking existence; lifecycle claims
74
+ // propagate their stable access errors.
75
+ if (!subscription) {
75
76
  throw new ManualTriggerNotFoundError(definitionId);
76
77
  }
78
+ requireWorkspaceResourceAccess({
79
+ request,
80
+ workspaceId: subscription.workspaceId,
81
+ notFoundError: new ClientError('Manual trigger not found', 'manual-trigger-not-found', {
82
+ status: 404
83
+ })
84
+ });
77
85
  const run = await fireManualSubscription({
78
86
  workflows,
79
87
  subscriptionId: subscription.id,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/fire-manual.ts"],"sourcesContent":["import {requireUserContext} from '@shipfox/api-auth-context';\nimport {\n fireManualTriggerBodySchema,\n fireManualTriggerResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {ManualTriggerNotFoundError} from '#core/errors.js';\nimport {fireManualSubscription} from '#core/fire-manual.js';\nimport {\n isInterpolationUnresolvableError,\n isWorkspaceDeletedError,\n isWorkspaceNotFoundError,\n isWorkspaceSuspendedError,\n} from '#core/workflows-client.js';\nimport {getManualSubscriptionByDefinitionId} from '#db/subscriptions.js';\n\nexport function createFireManualTriggerRoute(workflows: WorkflowsModuleClient) {\n return defineRoute({\n method: 'POST',\n path: '/:definitionId/fire-manual',\n description: 'Fire the manual trigger of a workflow definition, creating a workflow run.',\n schema: {\n params: z.object({\n definitionId: z.string().uuid(),\n }),\n body: fireManualTriggerBodySchema,\n response: {\n 201: fireManualTriggerResponseSchema,\n 422: z.object({\n code: z.string(),\n details: z.object({\n field: z.string(),\n source: z.string(),\n env_key: z.string().optional(),\n }),\n }),\n },\n },\n errorHandler: (error) => {\n if (error instanceof ManualTriggerNotFoundError) {\n throw new ClientError(error.message, 'manual-trigger-not-found', {status: 404});\n }\n if (isWorkspaceSuspendedError(error)) {\n throw new ClientError('Workspace is suspended', 'workspace-suspended', {\n status: 409,\n cause: error,\n });\n }\n if (isWorkspaceDeletedError(error)) {\n throw new ClientError('Workspace is deleted', 'workspace-deleted', {\n status: 404,\n cause: error,\n });\n }\n if (isWorkspaceNotFoundError(error)) {\n throw new ClientError('Workspace not found', 'workspace-not-found', {\n status: 404,\n cause: error,\n });\n }\n if (isInterpolationUnresolvableError(error)) {\n throw new ClientError(\n 'Workflow interpolation cannot be resolved',\n 'workflow-interpolation-unresolvable',\n {\n status: 422,\n details: {\n field: error.details.field,\n source: error.details.source,\n ...(error.details.envKey === undefined ? {} : {env_key: error.details.envKey}),\n },\n },\n );\n }\n throw error;\n },\n handler: async (request, reply) => {\n const {definitionId} = request.params;\n const userContext = requireUserContext(request);\n\n const subscription = await getManualSubscriptionByDefinitionId(definitionId);\n // 404 covers both \"no such manual trigger\" and \"not your workspace\" to avoid leaking existence.\n if (!subscription || !userContext.canAccess(subscription.workspaceId)) {\n throw new ManualTriggerNotFoundError(definitionId);\n }\n\n const run = await fireManualSubscription({\n workflows,\n subscriptionId: subscription.id,\n callerWorkspaceId: subscription.workspaceId,\n userId: userContext.userId,\n inputs: request.body.inputs,\n });\n\n reply.status(201);\n return {workflow_run_id: run.id};\n },\n });\n}\n"],"names":["requireUserContext","fireManualTriggerBodySchema","fireManualTriggerResponseSchema","ClientError","defineRoute","z","ManualTriggerNotFoundError","fireManualSubscription","isInterpolationUnresolvableError","isWorkspaceDeletedError","isWorkspaceNotFoundError","isWorkspaceSuspendedError","getManualSubscriptionByDefinitionId","createFireManualTriggerRoute","workflows","method","path","description","schema","params","object","definitionId","string","uuid","body","response","code","details","field","source","env_key","optional","errorHandler","error","message","status","cause","envKey","undefined","handler","request","reply","userContext","subscription","canAccess","workspaceId","run","subscriptionId","id","callerWorkspaceId","userId","inputs","workflow_run_id"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,4BAA4B;AAC7D,SACEC,2BAA2B,EAC3BC,+BAA+B,QAC1B,4BAA4B;AAEnC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,0BAA0B,QAAO,kBAAkB;AAC3D,SAAQC,sBAAsB,QAAO,uBAAuB;AAC5D,SACEC,gCAAgC,EAChCC,uBAAuB,EACvBC,wBAAwB,EACxBC,yBAAyB,QACpB,4BAA4B;AACnC,SAAQC,mCAAmC,QAAO,uBAAuB;AAEzE,OAAO,SAASC,6BAA6BC,SAAgC;IAC3E,OAAOV,YAAY;QACjBW,QAAQ;QACRC,MAAM;QACNC,aAAa;QACbC,QAAQ;YACNC,QAAQd,EAAEe,MAAM,CAAC;gBACfC,cAAchB,EAAEiB,MAAM,GAAGC,IAAI;YAC/B;YACAC,MAAMvB;YACNwB,UAAU;gBACR,KAAKvB;gBACL,KAAKG,EAAEe,MAAM,CAAC;oBACZM,MAAMrB,EAAEiB,MAAM;oBACdK,SAAStB,EAAEe,MAAM,CAAC;wBAChBQ,OAAOvB,EAAEiB,MAAM;wBACfO,QAAQxB,EAAEiB,MAAM;wBAChBQ,SAASzB,EAAEiB,MAAM,GAAGS,QAAQ;oBAC9B;gBACF;YACF;QACF;QACAC,cAAc,CAACC;YACb,IAAIA,iBAAiB3B,4BAA4B;gBAC/C,MAAM,IAAIH,YAAY8B,MAAMC,OAAO,EAAE,4BAA4B;oBAACC,QAAQ;gBAAG;YAC/E;YACA,IAAIxB,0BAA0BsB,QAAQ;gBACpC,MAAM,IAAI9B,YAAY,0BAA0B,uBAAuB;oBACrEgC,QAAQ;oBACRC,OAAOH;gBACT;YACF;YACA,IAAIxB,wBAAwBwB,QAAQ;gBAClC,MAAM,IAAI9B,YAAY,wBAAwB,qBAAqB;oBACjEgC,QAAQ;oBACRC,OAAOH;gBACT;YACF;YACA,IAAIvB,yBAAyBuB,QAAQ;gBACnC,MAAM,IAAI9B,YAAY,uBAAuB,uBAAuB;oBAClEgC,QAAQ;oBACRC,OAAOH;gBACT;YACF;YACA,IAAIzB,iCAAiCyB,QAAQ;gBAC3C,MAAM,IAAI9B,YACR,6CACA,uCACA;oBACEgC,QAAQ;oBACRR,SAAS;wBACPC,OAAOK,MAAMN,OAAO,CAACC,KAAK;wBAC1BC,QAAQI,MAAMN,OAAO,CAACE,MAAM;wBAC5B,GAAII,MAAMN,OAAO,CAACU,MAAM,KAAKC,YAAY,CAAC,IAAI;4BAACR,SAASG,MAAMN,OAAO,CAACU,MAAM;wBAAA,CAAC;oBAC/E;gBACF;YAEJ;YACA,MAAMJ;QACR;QACAM,SAAS,OAAOC,SAASC;YACvB,MAAM,EAACpB,YAAY,EAAC,GAAGmB,QAAQrB,MAAM;YACrC,MAAMuB,cAAc1C,mBAAmBwC;YAEvC,MAAMG,eAAe,MAAM/B,oCAAoCS;YAC/D,gGAAgG;YAChG,IAAI,CAACsB,gBAAgB,CAACD,YAAYE,SAAS,CAACD,aAAaE,WAAW,GAAG;gBACrE,MAAM,IAAIvC,2BAA2Be;YACvC;YAEA,MAAMyB,MAAM,MAAMvC,uBAAuB;gBACvCO;gBACAiC,gBAAgBJ,aAAaK,EAAE;gBAC/BC,mBAAmBN,aAAaE,WAAW;gBAC3CK,QAAQR,YAAYQ,MAAM;gBAC1BC,QAAQX,QAAQhB,IAAI,CAAC2B,MAAM;YAC7B;YAEAV,MAAMN,MAAM,CAAC;YACb,OAAO;gBAACiB,iBAAiBN,IAAIE,EAAE;YAAA;QACjC;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/fire-manual.ts"],"sourcesContent":["import {requireUserContext, requireWorkspaceResourceAccess} from '@shipfox/api-auth-context';\nimport {\n fireManualTriggerBodySchema,\n fireManualTriggerResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport type {WorkflowsModuleClient} from '@shipfox/api-workflows-dto/inter-module';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {ManualTriggerNotFoundError} from '#core/errors.js';\nimport {fireManualSubscription} from '#core/fire-manual.js';\nimport {\n isInterpolationUnresolvableError,\n isWorkspaceDeletedError,\n isWorkspaceNotFoundError,\n isWorkspaceSuspendedError,\n} from '#core/workflows-client.js';\nimport {getManualSubscriptionByDefinitionId} from '#db/subscriptions.js';\n\nexport function createFireManualTriggerRoute(workflows: WorkflowsModuleClient) {\n return defineRoute({\n method: 'POST',\n path: '/:definitionId/fire-manual',\n description: 'Fire the manual trigger of a workflow definition, creating a workflow run.',\n schema: {\n params: z.object({\n definitionId: z.string().uuid(),\n }),\n body: fireManualTriggerBodySchema,\n response: {\n 201: fireManualTriggerResponseSchema,\n 422: z.object({\n code: z.string(),\n details: z.object({\n field: z.string(),\n source: z.string(),\n env_key: z.string().optional(),\n }),\n }),\n },\n },\n errorHandler: (error) => {\n if (error instanceof ManualTriggerNotFoundError) {\n throw new ClientError(error.message, 'manual-trigger-not-found', {status: 404});\n }\n if (isWorkspaceSuspendedError(error)) {\n throw new ClientError('Workspace is suspended', 'workspace-suspended', {\n status: 409,\n cause: error,\n });\n }\n if (isWorkspaceDeletedError(error)) {\n throw new ClientError('Workspace is deleted', 'workspace-deleted', {\n status: 404,\n cause: error,\n });\n }\n if (isWorkspaceNotFoundError(error)) {\n throw new ClientError('Workspace not found', 'workspace-not-found', {\n status: 404,\n cause: error,\n });\n }\n if (isInterpolationUnresolvableError(error)) {\n throw new ClientError(\n 'Workflow interpolation cannot be resolved',\n 'workflow-interpolation-unresolvable',\n {\n status: 422,\n details: {\n field: error.details.field,\n source: error.details.source,\n ...(error.details.envKey === undefined ? {} : {env_key: error.details.envKey}),\n },\n },\n );\n }\n throw error;\n },\n handler: async (request, reply) => {\n const {definitionId} = request.params;\n const userContext = requireUserContext(request);\n\n const subscription = await getManualSubscriptionByDefinitionId(definitionId);\n // Missing triggers and memberships remain 404 to avoid leaking existence; lifecycle claims\n // propagate their stable access errors.\n if (!subscription) {\n throw new ManualTriggerNotFoundError(definitionId);\n }\n requireWorkspaceResourceAccess({\n request,\n workspaceId: subscription.workspaceId,\n notFoundError: new ClientError('Manual trigger not found', 'manual-trigger-not-found', {\n status: 404,\n }),\n });\n\n const run = await fireManualSubscription({\n workflows,\n subscriptionId: subscription.id,\n callerWorkspaceId: subscription.workspaceId,\n userId: userContext.userId,\n inputs: request.body.inputs,\n });\n\n reply.status(201);\n return {workflow_run_id: run.id};\n },\n });\n}\n"],"names":["requireUserContext","requireWorkspaceResourceAccess","fireManualTriggerBodySchema","fireManualTriggerResponseSchema","ClientError","defineRoute","z","ManualTriggerNotFoundError","fireManualSubscription","isInterpolationUnresolvableError","isWorkspaceDeletedError","isWorkspaceNotFoundError","isWorkspaceSuspendedError","getManualSubscriptionByDefinitionId","createFireManualTriggerRoute","workflows","method","path","description","schema","params","object","definitionId","string","uuid","body","response","code","details","field","source","env_key","optional","errorHandler","error","message","status","cause","envKey","undefined","handler","request","reply","userContext","subscription","workspaceId","notFoundError","run","subscriptionId","id","callerWorkspaceId","userId","inputs","workflow_run_id"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-trigger-event.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/get-trigger-event.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,iDA6B/B,CAAC"}
1
+ {"version":3,"file":"get-trigger-event.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/get-trigger-event.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,iDAkC/B,CAAC"}
@@ -1,4 +1,4 @@
1
- import { requireUserContext } from '@shipfox/api-auth-context';
1
+ import { requireWorkspaceResourceAccess } from '@shipfox/api-auth-context';
2
2
  import { triggerEventDetailResponseSchema } from '@shipfox/api-triggers-dto';
3
3
  import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
4
  import { z } from 'zod';
@@ -18,14 +18,21 @@ export const getTriggerEventRoute = defineRoute({
18
18
  },
19
19
  handler: async (request)=>{
20
20
  const { id } = request.params;
21
- const userContext = requireUserContext(request);
22
21
  const event = await getTriggerEventById(id);
23
- // 404 covers both "no such event" and "not your workspace" to avoid leaking existence.
24
- if (!event || !userContext.canAccess(event.workspaceId)) {
22
+ // Missing events and memberships remain 404 to avoid leaking existence; lifecycle claims
23
+ // propagate their stable access errors.
24
+ if (!event) {
25
25
  throw new ClientError('Trigger event not found', 'not-found', {
26
26
  status: 404
27
27
  });
28
28
  }
29
+ requireWorkspaceResourceAccess({
30
+ request,
31
+ workspaceId: event.workspaceId,
32
+ notFoundError: new ClientError('Trigger event not found', 'not-found', {
33
+ status: 404
34
+ })
35
+ });
29
36
  const decisions = await listDecisionsByReceivedEventId(event.id);
30
37
  return {
31
38
  ...toTriggerEventDto(event),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/get-trigger-event.ts"],"sourcesContent":["import {requireUserContext} from '@shipfox/api-auth-context';\nimport {triggerEventDetailResponseSchema} from '@shipfox/api-triggers-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {getTriggerEventById, listDecisionsByReceivedEventId} from '#db/index.js';\nimport {toTriggerDecisionDto, toTriggerEventDto} from '#presentation/dto/trigger-events.js';\n\nexport const getTriggerEventRoute = defineRoute({\n method: 'GET',\n path: '/:id',\n description: 'Get a trigger event by ID with its routing decisions.',\n schema: {\n params: z.object({\n id: z.string().uuid(),\n }),\n response: {\n 200: triggerEventDetailResponseSchema,\n },\n },\n handler: async (request) => {\n const {id} = request.params;\n const userContext = requireUserContext(request);\n\n const event = await getTriggerEventById(id);\n // 404 covers both \"no such event\" and \"not your workspace\" to avoid leaking existence.\n if (!event || !userContext.canAccess(event.workspaceId)) {\n throw new ClientError('Trigger event not found', 'not-found', {status: 404});\n }\n\n const decisions = await listDecisionsByReceivedEventId(event.id);\n\n return {\n ...toTriggerEventDto(event),\n decisions: decisions.map(toTriggerDecisionDto),\n };\n },\n});\n"],"names":["requireUserContext","triggerEventDetailResponseSchema","ClientError","defineRoute","z","getTriggerEventById","listDecisionsByReceivedEventId","toTriggerDecisionDto","toTriggerEventDto","getTriggerEventRoute","method","path","description","schema","params","object","id","string","uuid","response","handler","request","userContext","event","canAccess","workspaceId","status","decisions","map"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,4BAA4B;AAC7D,SAAQC,gCAAgC,QAAO,4BAA4B;AAC3E,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,mBAAmB,EAAEC,8BAA8B,QAAO,eAAe;AACjF,SAAQC,oBAAoB,EAAEC,iBAAiB,QAAO,sCAAsC;AAE5F,OAAO,MAAMC,uBAAuBN,YAAY;IAC9CO,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,QAAQV,EAAEW,MAAM,CAAC;YACfC,IAAIZ,EAAEa,MAAM,GAAGC,IAAI;QACrB;QACAC,UAAU;YACR,KAAKlB;QACP;IACF;IACAmB,SAAS,OAAOC;QACd,MAAM,EAACL,EAAE,EAAC,GAAGK,QAAQP,MAAM;QAC3B,MAAMQ,cAActB,mBAAmBqB;QAEvC,MAAME,QAAQ,MAAMlB,oBAAoBW;QACxC,uFAAuF;QACvF,IAAI,CAACO,SAAS,CAACD,YAAYE,SAAS,CAACD,MAAME,WAAW,GAAG;YACvD,MAAM,IAAIvB,YAAY,2BAA2B,aAAa;gBAACwB,QAAQ;YAAG;QAC5E;QAEA,MAAMC,YAAY,MAAMrB,+BAA+BiB,MAAMP,EAAE;QAE/D,OAAO;YACL,GAAGR,kBAAkBe,MAAM;YAC3BI,WAAWA,UAAUC,GAAG,CAACrB;QAC3B;IACF;AACF,GAAG"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/get-trigger-event.ts"],"sourcesContent":["import {requireWorkspaceResourceAccess} from '@shipfox/api-auth-context';\nimport {triggerEventDetailResponseSchema} from '@shipfox/api-triggers-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {getTriggerEventById, listDecisionsByReceivedEventId} from '#db/index.js';\nimport {toTriggerDecisionDto, toTriggerEventDto} from '#presentation/dto/trigger-events.js';\n\nexport const getTriggerEventRoute = defineRoute({\n method: 'GET',\n path: '/:id',\n description: 'Get a trigger event by ID with its routing decisions.',\n schema: {\n params: z.object({\n id: z.string().uuid(),\n }),\n response: {\n 200: triggerEventDetailResponseSchema,\n },\n },\n handler: async (request) => {\n const {id} = request.params;\n\n const event = await getTriggerEventById(id);\n // Missing events and memberships remain 404 to avoid leaking existence; lifecycle claims\n // propagate their stable access errors.\n if (!event) {\n throw new ClientError('Trigger event not found', 'not-found', {status: 404});\n }\n requireWorkspaceResourceAccess({\n request,\n workspaceId: event.workspaceId,\n notFoundError: new ClientError('Trigger event not found', 'not-found', {status: 404}),\n });\n\n const decisions = await listDecisionsByReceivedEventId(event.id);\n\n return {\n ...toTriggerEventDto(event),\n decisions: decisions.map(toTriggerDecisionDto),\n };\n },\n});\n"],"names":["requireWorkspaceResourceAccess","triggerEventDetailResponseSchema","ClientError","defineRoute","z","getTriggerEventById","listDecisionsByReceivedEventId","toTriggerDecisionDto","toTriggerEventDto","getTriggerEventRoute","method","path","description","schema","params","object","id","string","uuid","response","handler","request","event","status","workspaceId","notFoundError","decisions","map"],"mappings":"AAAA,SAAQA,8BAA8B,QAAO,4BAA4B;AACzE,SAAQC,gCAAgC,QAAO,4BAA4B;AAC3E,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,mBAAmB,EAAEC,8BAA8B,QAAO,eAAe;AACjF,SAAQC,oBAAoB,EAAEC,iBAAiB,QAAO,sCAAsC;AAE5F,OAAO,MAAMC,uBAAuBN,YAAY;IAC9CO,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,QAAQV,EAAEW,MAAM,CAAC;YACfC,IAAIZ,EAAEa,MAAM,GAAGC,IAAI;QACrB;QACAC,UAAU;YACR,KAAKlB;QACP;IACF;IACAmB,SAAS,OAAOC;QACd,MAAM,EAACL,EAAE,EAAC,GAAGK,QAAQP,MAAM;QAE3B,MAAMQ,QAAQ,MAAMjB,oBAAoBW;QACxC,yFAAyF;QACzF,wCAAwC;QACxC,IAAI,CAACM,OAAO;YACV,MAAM,IAAIpB,YAAY,2BAA2B,aAAa;gBAACqB,QAAQ;YAAG;QAC5E;QACAvB,+BAA+B;YAC7BqB;YACAG,aAAaF,MAAME,WAAW;YAC9BC,eAAe,IAAIvB,YAAY,2BAA2B,aAAa;gBAACqB,QAAQ;YAAG;QACrF;QAEA,MAAMG,YAAY,MAAMpB,+BAA+BgB,MAAMN,EAAE;QAE/D,OAAO;YACL,GAAGR,kBAAkBc,MAAM;YAC3BI,WAAWA,UAAUC,GAAG,CAACpB;QAC3B;IACF;AACF,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"list-trigger-event-facets.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/list-trigger-event-facets.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,2BAA2B,iDAoBtC,CAAC"}
1
+ {"version":3,"file":"list-trigger-event-facets.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/list-trigger-event-facets.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,2BAA2B,iDAiBtC,CAAC"}
@@ -1,6 +1,6 @@
1
- import { requireUserContext } from '@shipfox/api-auth-context';
1
+ import { requireWorkspaceAccess } from '@shipfox/api-auth-context';
2
2
  import { triggerEventFacetsQuerySchema, triggerEventFacetsResponseSchema } from '@shipfox/api-triggers-dto';
3
- import { ClientError, defineRoute } from '@shipfox/node-fastify';
3
+ import { defineRoute } from '@shipfox/node-fastify';
4
4
  import { listTriggerEventFacets } from '#db/index.js';
5
5
  export const listTriggerEventFacetsRoute = defineRoute({
6
6
  method: 'GET',
@@ -14,12 +14,10 @@ export const listTriggerEventFacetsRoute = defineRoute({
14
14
  },
15
15
  handler: async (request)=>{
16
16
  const { workspace_id: workspaceId } = request.query;
17
- const userContext = requireUserContext(request);
18
- if (!userContext.canAccess(workspaceId)) {
19
- throw new ClientError('Not a member of this workspace', 'forbidden', {
20
- status: 403
21
- });
22
- }
17
+ requireWorkspaceAccess({
18
+ request,
19
+ workspaceId
20
+ });
23
21
  return await listTriggerEventFacets({
24
22
  workspaceId
25
23
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/list-trigger-event-facets.ts"],"sourcesContent":["import {requireUserContext} from '@shipfox/api-auth-context';\nimport {\n triggerEventFacetsQuerySchema,\n triggerEventFacetsResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {listTriggerEventFacets} from '#db/index.js';\n\nexport const listTriggerEventFacetsRoute = defineRoute({\n method: 'GET',\n path: '/facets',\n description: 'Distinct source and event filter values (with counts) for a workspace.',\n schema: {\n querystring: triggerEventFacetsQuerySchema,\n response: {\n 200: triggerEventFacetsResponseSchema,\n },\n },\n handler: async (request) => {\n const {workspace_id: workspaceId} = request.query;\n\n const userContext = requireUserContext(request);\n if (!userContext.canAccess(workspaceId)) {\n throw new ClientError('Not a member of this workspace', 'forbidden', {status: 403});\n }\n\n return await listTriggerEventFacets({workspaceId});\n },\n});\n"],"names":["requireUserContext","triggerEventFacetsQuerySchema","triggerEventFacetsResponseSchema","ClientError","defineRoute","listTriggerEventFacets","listTriggerEventFacetsRoute","method","path","description","schema","querystring","response","handler","request","workspace_id","workspaceId","query","userContext","canAccess","status"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,4BAA4B;AAC7D,SACEC,6BAA6B,EAC7BC,gCAAgC,QAC3B,4BAA4B;AACnC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,sBAAsB,QAAO,eAAe;AAEpD,OAAO,MAAMC,8BAA8BF,YAAY;IACrDG,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,aAAaV;QACbW,UAAU;YACR,KAAKV;QACP;IACF;IACAW,SAAS,OAAOC;QACd,MAAM,EAACC,cAAcC,WAAW,EAAC,GAAGF,QAAQG,KAAK;QAEjD,MAAMC,cAAclB,mBAAmBc;QACvC,IAAI,CAACI,YAAYC,SAAS,CAACH,cAAc;YACvC,MAAM,IAAIb,YAAY,kCAAkC,aAAa;gBAACiB,QAAQ;YAAG;QACnF;QAEA,OAAO,MAAMf,uBAAuB;YAACW;QAAW;IAClD;AACF,GAAG"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/list-trigger-event-facets.ts"],"sourcesContent":["import {requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport {\n triggerEventFacetsQuerySchema,\n triggerEventFacetsResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport {defineRoute} from '@shipfox/node-fastify';\nimport {listTriggerEventFacets} from '#db/index.js';\n\nexport const listTriggerEventFacetsRoute = defineRoute({\n method: 'GET',\n path: '/facets',\n description: 'Distinct source and event filter values (with counts) for a workspace.',\n schema: {\n querystring: triggerEventFacetsQuerySchema,\n response: {\n 200: triggerEventFacetsResponseSchema,\n },\n },\n handler: async (request) => {\n const {workspace_id: workspaceId} = request.query;\n\n requireWorkspaceAccess({request, workspaceId});\n\n return await listTriggerEventFacets({workspaceId});\n },\n});\n"],"names":["requireWorkspaceAccess","triggerEventFacetsQuerySchema","triggerEventFacetsResponseSchema","defineRoute","listTriggerEventFacets","listTriggerEventFacetsRoute","method","path","description","schema","querystring","response","handler","request","workspace_id","workspaceId","query"],"mappings":"AAAA,SAAQA,sBAAsB,QAAO,4BAA4B;AACjE,SACEC,6BAA6B,EAC7BC,gCAAgC,QAC3B,4BAA4B;AACnC,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SAAQC,sBAAsB,QAAO,eAAe;AAEpD,OAAO,MAAMC,8BAA8BF,YAAY;IACrDG,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,aAAaT;QACbU,UAAU;YACR,KAAKT;QACP;IACF;IACAU,SAAS,OAAOC;QACd,MAAM,EAACC,cAAcC,WAAW,EAAC,GAAGF,QAAQG,KAAK;QAEjDhB,uBAAuB;YAACa;YAASE;QAAW;QAE5C,OAAO,MAAMX,uBAAuB;YAACW;QAAW;IAClD;AACF,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"list-trigger-events.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/list-trigger-events.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,sBAAsB,iDAyDjC,CAAC"}
1
+ {"version":3,"file":"list-trigger-events.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/list-trigger-events.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,sBAAsB,iDAsDjC,CAAC"}
@@ -1,4 +1,4 @@
1
- import { requireUserContext } from '@shipfox/api-auth-context';
1
+ import { requireWorkspaceAccess } from '@shipfox/api-auth-context';
2
2
  import { triggerEventListQuerySchema, triggerEventListResponseSchema } from '@shipfox/api-triggers-dto';
3
3
  import { decodeTimestampIdCursor, encodeTimestampIdCursor } from '@shipfox/node-drizzle';
4
4
  import { ClientError, defineRoute } from '@shipfox/node-fastify';
@@ -16,12 +16,10 @@ export const listTriggerEventsRoute = defineRoute({
16
16
  },
17
17
  handler: async (request)=>{
18
18
  const { workspace_id: workspaceId, source, event, outcome: outcomes, from, to, limit, cursor } = request.query;
19
- const userContext = requireUserContext(request);
20
- if (!userContext.canAccess(workspaceId)) {
21
- throw new ClientError('Not a member of this workspace', 'forbidden', {
22
- status: 403
23
- });
24
- }
19
+ requireWorkspaceAccess({
20
+ request,
21
+ workspaceId
22
+ });
25
23
  const decodedCursor = decodeTimestampIdCursor(cursor);
26
24
  if (cursor && !decodedCursor) {
27
25
  throw new ClientError('Invalid cursor', 'invalid-cursor', {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/list-trigger-events.ts"],"sourcesContent":["import {requireUserContext} from '@shipfox/api-auth-context';\nimport {\n triggerEventListQuerySchema,\n triggerEventListResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport {decodeTimestampIdCursor, encodeTimestampIdCursor} from '@shipfox/node-drizzle';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {listTriggerEvents} from '#db/index.js';\nimport {toTriggerEventListItemDto} from '#presentation/dto/trigger-events.js';\n\nexport const listTriggerEventsRoute = defineRoute({\n method: 'GET',\n path: '/',\n description: 'List trigger events for a workspace, newest first.',\n schema: {\n querystring: triggerEventListQuerySchema,\n response: {\n 200: triggerEventListResponseSchema,\n },\n },\n handler: async (request) => {\n const {\n workspace_id: workspaceId,\n source,\n event,\n outcome: outcomes,\n from,\n to,\n limit,\n cursor,\n } = request.query;\n\n const userContext = requireUserContext(request);\n if (!userContext.canAccess(workspaceId)) {\n throw new ClientError('Not a member of this workspace', 'forbidden', {status: 403});\n }\n\n const decodedCursor = decodeTimestampIdCursor(cursor);\n if (cursor && !decodedCursor) {\n throw new ClientError('Invalid cursor', 'invalid-cursor', {status: 400});\n }\n\n const result = await listTriggerEvents({\n workspaceId,\n limit,\n cursor: decodedCursor\n ? {receivedAt: decodedCursor.createdAt, id: decodedCursor.id}\n : undefined,\n filters: {\n source,\n event,\n outcomes,\n from: from ? new Date(from) : undefined,\n to: to ? new Date(to) : undefined,\n },\n });\n\n return {\n trigger_events: result.events.map(toTriggerEventListItemDto),\n next_cursor: result.nextCursor\n ? encodeTimestampIdCursor({\n createdAt: result.nextCursor.receivedAt,\n id: result.nextCursor.id,\n })\n : null,\n };\n },\n});\n"],"names":["requireUserContext","triggerEventListQuerySchema","triggerEventListResponseSchema","decodeTimestampIdCursor","encodeTimestampIdCursor","ClientError","defineRoute","listTriggerEvents","toTriggerEventListItemDto","listTriggerEventsRoute","method","path","description","schema","querystring","response","handler","request","workspace_id","workspaceId","source","event","outcome","outcomes","from","to","limit","cursor","query","userContext","canAccess","status","decodedCursor","result","receivedAt","createdAt","id","undefined","filters","Date","trigger_events","events","map","next_cursor","nextCursor"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,4BAA4B;AAC7D,SACEC,2BAA2B,EAC3BC,8BAA8B,QACzB,4BAA4B;AACnC,SAAQC,uBAAuB,EAAEC,uBAAuB,QAAO,wBAAwB;AACvF,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,iBAAiB,QAAO,eAAe;AAC/C,SAAQC,yBAAyB,QAAO,sCAAsC;AAE9E,OAAO,MAAMC,yBAAyBH,YAAY;IAChDI,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,aAAab;QACbc,UAAU;YACR,KAAKb;QACP;IACF;IACAc,SAAS,OAAOC;QACd,MAAM,EACJC,cAAcC,WAAW,EACzBC,MAAM,EACNC,KAAK,EACLC,SAASC,QAAQ,EACjBC,IAAI,EACJC,EAAE,EACFC,KAAK,EACLC,MAAM,EACP,GAAGV,QAAQW,KAAK;QAEjB,MAAMC,cAAc7B,mBAAmBiB;QACvC,IAAI,CAACY,YAAYC,SAAS,CAACX,cAAc;YACvC,MAAM,IAAId,YAAY,kCAAkC,aAAa;gBAAC0B,QAAQ;YAAG;QACnF;QAEA,MAAMC,gBAAgB7B,wBAAwBwB;QAC9C,IAAIA,UAAU,CAACK,eAAe;YAC5B,MAAM,IAAI3B,YAAY,kBAAkB,kBAAkB;gBAAC0B,QAAQ;YAAG;QACxE;QAEA,MAAME,SAAS,MAAM1B,kBAAkB;YACrCY;YACAO;YACAC,QAAQK,gBACJ;gBAACE,YAAYF,cAAcG,SAAS;gBAAEC,IAAIJ,cAAcI,EAAE;YAAA,IAC1DC;YACJC,SAAS;gBACPlB;gBACAC;gBACAE;gBACAC,MAAMA,OAAO,IAAIe,KAAKf,QAAQa;gBAC9BZ,IAAIA,KAAK,IAAIc,KAAKd,MAAMY;YAC1B;QACF;QAEA,OAAO;YACLG,gBAAgBP,OAAOQ,MAAM,CAACC,GAAG,CAAClC;YAClCmC,aAAaV,OAAOW,UAAU,GAC1BxC,wBAAwB;gBACtB+B,WAAWF,OAAOW,UAAU,CAACV,UAAU;gBACvCE,IAAIH,OAAOW,UAAU,CAACR,EAAE;YAC1B,KACA;QACN;IACF;AACF,GAAG"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/list-trigger-events.ts"],"sourcesContent":["import {requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport {\n triggerEventListQuerySchema,\n triggerEventListResponseSchema,\n} from '@shipfox/api-triggers-dto';\nimport {decodeTimestampIdCursor, encodeTimestampIdCursor} from '@shipfox/node-drizzle';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {listTriggerEvents} from '#db/index.js';\nimport {toTriggerEventListItemDto} from '#presentation/dto/trigger-events.js';\n\nexport const listTriggerEventsRoute = defineRoute({\n method: 'GET',\n path: '/',\n description: 'List trigger events for a workspace, newest first.',\n schema: {\n querystring: triggerEventListQuerySchema,\n response: {\n 200: triggerEventListResponseSchema,\n },\n },\n handler: async (request) => {\n const {\n workspace_id: workspaceId,\n source,\n event,\n outcome: outcomes,\n from,\n to,\n limit,\n cursor,\n } = request.query;\n\n requireWorkspaceAccess({request, workspaceId});\n\n const decodedCursor = decodeTimestampIdCursor(cursor);\n if (cursor && !decodedCursor) {\n throw new ClientError('Invalid cursor', 'invalid-cursor', {status: 400});\n }\n\n const result = await listTriggerEvents({\n workspaceId,\n limit,\n cursor: decodedCursor\n ? {receivedAt: decodedCursor.createdAt, id: decodedCursor.id}\n : undefined,\n filters: {\n source,\n event,\n outcomes,\n from: from ? new Date(from) : undefined,\n to: to ? new Date(to) : undefined,\n },\n });\n\n return {\n trigger_events: result.events.map(toTriggerEventListItemDto),\n next_cursor: result.nextCursor\n ? encodeTimestampIdCursor({\n createdAt: result.nextCursor.receivedAt,\n id: result.nextCursor.id,\n })\n : null,\n };\n },\n});\n"],"names":["requireWorkspaceAccess","triggerEventListQuerySchema","triggerEventListResponseSchema","decodeTimestampIdCursor","encodeTimestampIdCursor","ClientError","defineRoute","listTriggerEvents","toTriggerEventListItemDto","listTriggerEventsRoute","method","path","description","schema","querystring","response","handler","request","workspace_id","workspaceId","source","event","outcome","outcomes","from","to","limit","cursor","query","decodedCursor","status","result","receivedAt","createdAt","id","undefined","filters","Date","trigger_events","events","map","next_cursor","nextCursor"],"mappings":"AAAA,SAAQA,sBAAsB,QAAO,4BAA4B;AACjE,SACEC,2BAA2B,EAC3BC,8BAA8B,QACzB,4BAA4B;AACnC,SAAQC,uBAAuB,EAAEC,uBAAuB,QAAO,wBAAwB;AACvF,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SAAQC,iBAAiB,QAAO,eAAe;AAC/C,SAAQC,yBAAyB,QAAO,sCAAsC;AAE9E,OAAO,MAAMC,yBAAyBH,YAAY;IAChDI,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,aAAab;QACbc,UAAU;YACR,KAAKb;QACP;IACF;IACAc,SAAS,OAAOC;QACd,MAAM,EACJC,cAAcC,WAAW,EACzBC,MAAM,EACNC,KAAK,EACLC,SAASC,QAAQ,EACjBC,IAAI,EACJC,EAAE,EACFC,KAAK,EACLC,MAAM,EACP,GAAGV,QAAQW,KAAK;QAEjB5B,uBAAuB;YAACiB;YAASE;QAAW;QAE5C,MAAMU,gBAAgB1B,wBAAwBwB;QAC9C,IAAIA,UAAU,CAACE,eAAe;YAC5B,MAAM,IAAIxB,YAAY,kBAAkB,kBAAkB;gBAACyB,QAAQ;YAAG;QACxE;QAEA,MAAMC,SAAS,MAAMxB,kBAAkB;YACrCY;YACAO;YACAC,QAAQE,gBACJ;gBAACG,YAAYH,cAAcI,SAAS;gBAAEC,IAAIL,cAAcK,EAAE;YAAA,IAC1DC;YACJC,SAAS;gBACPhB;gBACAC;gBACAE;gBACAC,MAAMA,OAAO,IAAIa,KAAKb,QAAQW;gBAC9BV,IAAIA,KAAK,IAAIY,KAAKZ,MAAMU;YAC1B;QACF;QAEA,OAAO;YACLG,gBAAgBP,OAAOQ,MAAM,CAACC,GAAG,CAAChC;YAClCiC,aAAaV,OAAOW,UAAU,GAC1BtC,wBAAwB;gBACtB6B,WAAWF,OAAOW,UAAU,CAACV,UAAU;gBACvCE,IAAIH,OAAOW,UAAU,CAACR,EAAE;YAC1B,KACA;QACN;IACF;AACF,GAAG"}