@abyss-project/probe 2.0.0 → 3.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.
Files changed (90) hide show
  1. package/.eslintrc.js +32 -32
  2. package/.prettierrc +5 -5
  3. package/README.md +22 -22
  4. package/dist/api/index.d.ts +2 -1
  5. package/dist/api/index.js +2 -1
  6. package/dist/api/index.js.map +1 -1
  7. package/dist/api/probe-delivery-subscription.api.d.ts +11 -0
  8. package/dist/api/probe-delivery-subscription.api.js +42 -0
  9. package/dist/api/probe-delivery-subscription.api.js.map +1 -0
  10. package/dist/api/probe-delivery-subscription.application.api.d.ts +11 -0
  11. package/dist/api/probe-delivery-subscription.application.api.js +38 -0
  12. package/dist/api/probe-delivery-subscription.application.api.js.map +1 -0
  13. package/dist/api/probe-webhook.application.api.d.ts +1 -1
  14. package/dist/api/probe-webhook.application.api.js.map +1 -1
  15. package/dist/index.d.ts +29 -7
  16. package/dist/index.js +29 -7
  17. package/dist/index.js.map +1 -1
  18. package/dist/types/enum/api-error.enum.d.ts +2 -1
  19. package/dist/types/enum/api-error.enum.js +1 -0
  20. package/dist/types/enum/api-error.enum.js.map +1 -1
  21. package/dist/types/enum/probe-scan.enum.js.map +1 -1
  22. package/dist/types/interface/api/requests/index.d.ts +1 -0
  23. package/dist/types/interface/api/requests/index.js +1 -0
  24. package/dist/types/interface/api/requests/index.js.map +1 -1
  25. package/dist/types/interface/api/requests/probe-delivery-subscription.request.d.ts +23 -0
  26. package/dist/types/interface/api/requests/probe-delivery-subscription.request.js +3 -0
  27. package/dist/types/interface/api/requests/probe-delivery-subscription.request.js.map +1 -0
  28. package/dist/types/interface/api/requests/probe-webhook.request.d.ts +1 -4
  29. package/dist/types/interface/api/responses/index.d.ts +1 -0
  30. package/dist/types/interface/api/responses/index.js +1 -0
  31. package/dist/types/interface/api/responses/index.js.map +1 -1
  32. package/dist/types/interface/api/responses/probe-delivery-subscription.response.d.ts +10 -0
  33. package/dist/types/interface/api/responses/probe-delivery-subscription.response.js +3 -0
  34. package/dist/types/interface/api/responses/probe-delivery-subscription.response.js.map +1 -0
  35. package/dist/types/tests/probe.dto.test.js +22 -0
  36. package/dist/types/tests/probe.dto.test.js.map +1 -1
  37. package/dist/utils/probe-webhook-signature.utils.js.map +1 -1
  38. package/package.json +19 -15
  39. package/src/api/index.ts +2 -1
  40. package/src/api/probe-delivery-subscription.api.ts +183 -0
  41. package/src/api/probe-delivery-subscription.application.api.ts +186 -0
  42. package/src/api/probe-scan.api.test.ts +47 -47
  43. package/src/api/probe-scan.api.ts +203 -203
  44. package/src/api/probe-scan.application.api.test.ts +35 -35
  45. package/src/api/probe-scan.application.api.ts +157 -157
  46. package/src/api/probe-usage.api.ts +47 -47
  47. package/src/api/probe-usage.application.api.ts +25 -25
  48. package/src/api/probe-webhook.application.api.test.ts +18 -18
  49. package/src/api/probe-webhook.application.api.ts +10 -23
  50. package/src/constants/index.ts +1 -1
  51. package/src/index.ts +73 -16
  52. package/src/types/enum/api-error.enum.ts +2 -0
  53. package/src/types/enum/index.ts +2 -2
  54. package/src/types/enum/probe-scan.enum.ts +3 -2
  55. package/src/types/index.ts +2 -2
  56. package/src/types/interface/api/index.ts +5 -5
  57. package/src/types/interface/api/requests/index.ts +1 -0
  58. package/src/types/interface/api/requests/probe-delivery-subscription.request.ts +42 -0
  59. package/src/types/interface/api/requests/probe-scan.request.ts +54 -54
  60. package/src/types/interface/api/requests/probe-usage.request.ts +7 -7
  61. package/src/types/interface/api/requests/probe-webhook.request.ts +9 -11
  62. package/src/types/interface/api/responses/index.ts +1 -0
  63. package/src/types/interface/api/responses/probe-delivery-subscription.response.ts +27 -0
  64. package/src/types/interface/api/responses/probe-scan.response.ts +45 -45
  65. package/src/types/interface/api/responses/probe-usage.response.ts +25 -25
  66. package/src/types/interface/api/responses/probe-webhook.response.ts +24 -24
  67. package/src/types/interface/api/type-message/api-error.ts +7 -7
  68. package/src/types/interface/api/type-message/base-paginate.ts +11 -11
  69. package/src/types/interface/api/type-message/response.ts +6 -6
  70. package/src/types/interface/index.ts +2 -2
  71. package/src/types/interface/models/index.ts +3 -3
  72. package/src/types/interface/models/probe-scan.dto.ts +67 -67
  73. package/src/types/interface/models/probe-webhook-delivery.dto.ts +11 -14
  74. package/src/types/interface/models/probe-webhook.dto.ts +29 -29
  75. package/src/types/tests/probe.dto.test.ts +40 -4
  76. package/src/utils/enum.utils.ts +1 -1
  77. package/src/utils/error.utils.ts +30 -30
  78. package/src/utils/index.ts +4 -4
  79. package/src/utils/probe-scan-cost.utils.ts +101 -101
  80. package/src/utils/probe-webhook-signature.utils.ts +4 -3
  81. package/tsconfig.check.json +15 -15
  82. package/tsconfig.json +36 -36
  83. package/dist/api/probe-webhook.api.d.ts +0 -6
  84. package/dist/api/probe-webhook.api.js +0 -41
  85. package/dist/api/probe-webhook.api.js.map +0 -1
  86. package/dist/api/probe-webhook.api.test.d.ts +0 -1
  87. package/dist/api/probe-webhook.api.test.js +0 -43
  88. package/dist/api/probe-webhook.api.test.js.map +0 -1
  89. package/src/api/probe-webhook.api.test.ts +0 -17
  90. package/src/api/probe-webhook.api.ts +0 -119
package/src/index.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import axios from 'axios';
2
2
  import axiosRetry, { IAxiosRetryConfig, isNetworkOrIdempotentRequestError } from 'axios-retry';
3
3
  import * as probeScanApi from './api/probe-scan.api';
4
- import * as probeWebhookApi from './api/probe-webhook.api';
4
+ import * as probeDeliverySubscriptionApi from './api/probe-delivery-subscription.api';
5
5
  import * as probeScanApplicationApi from './api/probe-scan.application.api';
6
+ import * as probeDeliverySubscriptionApplicationApi from './api/probe-delivery-subscription.application.api';
6
7
  import * as probeWebhookApplicationApi from './api/probe-webhook.application.api';
7
8
  import * as probeUsageApi from './api/probe-usage.api';
8
9
  import * as probeUsageApplicationApi from './api/probe-usage.application.api';
@@ -26,7 +27,9 @@ export const ADMIN_TOKEN_HEADER = 'abyss-admin-token';
26
27
  /**
27
28
  * Header carrying the HMAC-SHA256 signature of a probe webhook delivery's
28
29
  * raw JSON body. Verify it with {@link verifyProbeWebhookSignature}
29
- * (re-exported from './utils').
30
+ * (re-exported from './utils'). INTERNAL (P5 #792): AbyssStorage's antivirus
31
+ * subscription is the only receiver until L2 — the deliveries of a client's
32
+ * subscription are signed by Flow.
30
33
  */
31
34
  export const PROBE_WEBHOOK_SIGNATURE_HEADER = 'x-probe-signature';
32
35
  export const PROBE_WEBHOOK_SIGNATURE_ALGORITHM = 'sha256';
@@ -61,14 +64,25 @@ type AbyssProbeCoreSDK = {
61
64
  usage: {
62
65
  get: typeof probeUsageApi.getProbeUsage;
63
66
  };
64
- webhook: {
65
- create: typeof probeWebhookApi.createProbeWebhook;
66
- list: typeof probeWebhookApi.listProbeWebhook;
67
- delete: typeof probeWebhookApi.deleteProbeWebhook;
68
- /** `PATCH /webhook/:webhookId` — edit callbackUrl and/or active. */
69
- update: typeof probeWebhookApi.updateProbeWebhook;
70
- /** `GET /webhook/:webhookId/deliveries` — paginated delivery-attempt history. */
71
- listDeliveries: typeof probeWebhookApi.listProbeWebhookDeliveries;
67
+ /**
68
+ * The subscriptions to the verdict of the caller's scans (`PROBE_SCAN_COMPLETED`), kept in
69
+ * Flow: personal scope, or an organization with `organizationId`. The deliveries are signed
70
+ * by Flow; the secret leaves with `create` and `resetSecret` only.
71
+ */
72
+ deliverySubscription: {
73
+ paginate: typeof probeDeliverySubscriptionApi.paginateProbeDeliverySubscription;
74
+ get: typeof probeDeliverySubscriptionApi.getProbeDeliverySubscription;
75
+ create: typeof probeDeliverySubscriptionApi.createProbeDeliverySubscription;
76
+ update: typeof probeDeliverySubscriptionApi.updateProbeDeliverySubscription;
77
+ delete: typeof probeDeliverySubscriptionApi.deleteProbeDeliverySubscription;
78
+ resetSecret: typeof probeDeliverySubscriptionApi.resetSecretProbeDeliverySubscription;
79
+ delivery: {
80
+ /** Deliveries of every subscription of the scope. */
81
+ paginateByScope: typeof probeDeliverySubscriptionApi.paginateProbeScopeDelivery;
82
+ paginate: typeof probeDeliverySubscriptionApi.paginateProbeDelivery;
83
+ get: typeof probeDeliverySubscriptionApi.getProbeDelivery;
84
+ replay: typeof probeDeliverySubscriptionApi.replayProbeDelivery;
85
+ };
72
86
  };
73
87
  /**
74
88
  * Application/API-key-auth counterpart (Phase 3a) — for inter-service
@@ -93,6 +107,22 @@ type AbyssProbeCoreSDK = {
93
107
  usage: {
94
108
  get: typeof probeUsageApplicationApi.getProbeUsageApplication;
95
109
  };
110
+ /** Same as `probe.deliverySubscription`, for the application (`FULL_ACCESS`). */
111
+ deliverySubscription: {
112
+ paginate: typeof probeDeliverySubscriptionApplicationApi.paginateProbeDeliverySubscriptionApplication;
113
+ get: typeof probeDeliverySubscriptionApplicationApi.getProbeDeliverySubscriptionApplication;
114
+ create: typeof probeDeliverySubscriptionApplicationApi.createProbeDeliverySubscriptionApplication;
115
+ update: typeof probeDeliverySubscriptionApplicationApi.updateProbeDeliverySubscriptionApplication;
116
+ delete: typeof probeDeliverySubscriptionApplicationApi.deleteProbeDeliverySubscriptionApplication;
117
+ resetSecret: typeof probeDeliverySubscriptionApplicationApi.resetSecretProbeDeliverySubscriptionApplication;
118
+ delivery: {
119
+ paginateByScope: typeof probeDeliverySubscriptionApplicationApi.paginateProbeScopeDeliveryApplication;
120
+ paginate: typeof probeDeliverySubscriptionApplicationApi.paginateProbeDeliveryApplication;
121
+ get: typeof probeDeliverySubscriptionApplicationApi.getProbeDeliveryApplication;
122
+ replay: typeof probeDeliverySubscriptionApplicationApi.replayProbeDeliveryApplication;
123
+ };
124
+ };
125
+ /** INTERNAL (P5 #792): AbyssStorage's antivirus subscription, until L2. */
96
126
  webhook: {
97
127
  create: typeof probeWebhookApplicationApi.createProbeWebhookApplication;
98
128
  list: typeof probeWebhookApplicationApi.listProbeWebhookApplication;
@@ -138,12 +168,19 @@ export class AbyssProbeCore {
138
168
  usage: {
139
169
  get: probeUsageApi.getProbeUsage,
140
170
  },
141
- webhook: {
142
- create: probeWebhookApi.createProbeWebhook,
143
- list: probeWebhookApi.listProbeWebhook,
144
- delete: probeWebhookApi.deleteProbeWebhook,
145
- update: probeWebhookApi.updateProbeWebhook,
146
- listDeliveries: probeWebhookApi.listProbeWebhookDeliveries,
171
+ deliverySubscription: {
172
+ paginate: probeDeliverySubscriptionApi.paginateProbeDeliverySubscription,
173
+ get: probeDeliverySubscriptionApi.getProbeDeliverySubscription,
174
+ create: probeDeliverySubscriptionApi.createProbeDeliverySubscription,
175
+ update: probeDeliverySubscriptionApi.updateProbeDeliverySubscription,
176
+ delete: probeDeliverySubscriptionApi.deleteProbeDeliverySubscription,
177
+ resetSecret: probeDeliverySubscriptionApi.resetSecretProbeDeliverySubscription,
178
+ delivery: {
179
+ paginateByScope: probeDeliverySubscriptionApi.paginateProbeScopeDelivery,
180
+ paginate: probeDeliverySubscriptionApi.paginateProbeDelivery,
181
+ get: probeDeliverySubscriptionApi.getProbeDelivery,
182
+ replay: probeDeliverySubscriptionApi.replayProbeDelivery,
183
+ },
147
184
  },
148
185
  application: {
149
186
  scan: probeScanApplicationApi.scanApplication,
@@ -154,6 +191,26 @@ export class AbyssProbeCore {
154
191
  usage: {
155
192
  get: probeUsageApplicationApi.getProbeUsageApplication,
156
193
  },
194
+ deliverySubscription: {
195
+ paginate:
196
+ probeDeliverySubscriptionApplicationApi.paginateProbeDeliverySubscriptionApplication,
197
+ get: probeDeliverySubscriptionApplicationApi.getProbeDeliverySubscriptionApplication,
198
+ create:
199
+ probeDeliverySubscriptionApplicationApi.createProbeDeliverySubscriptionApplication,
200
+ update:
201
+ probeDeliverySubscriptionApplicationApi.updateProbeDeliverySubscriptionApplication,
202
+ delete:
203
+ probeDeliverySubscriptionApplicationApi.deleteProbeDeliverySubscriptionApplication,
204
+ resetSecret:
205
+ probeDeliverySubscriptionApplicationApi.resetSecretProbeDeliverySubscriptionApplication,
206
+ delivery: {
207
+ paginateByScope:
208
+ probeDeliverySubscriptionApplicationApi.paginateProbeScopeDeliveryApplication,
209
+ paginate: probeDeliverySubscriptionApplicationApi.paginateProbeDeliveryApplication,
210
+ get: probeDeliverySubscriptionApplicationApi.getProbeDeliveryApplication,
211
+ replay: probeDeliverySubscriptionApplicationApi.replayProbeDeliveryApplication,
212
+ },
213
+ },
157
214
  webhook: {
158
215
  create: probeWebhookApplicationApi.createProbeWebhookApplication,
159
216
  list: probeWebhookApplicationApi.listProbeWebhookApplication,
@@ -30,4 +30,6 @@ export enum Code {
30
30
  drawImageLimitReached = 'draw_image_limit_reached',
31
31
  drawImageOwnerRequired = 'draw_image_owner_required',
32
32
  drawImageNotInDraw = 'draw_image_not_in_draw',
33
+ /** A scan `callbackUrl` in a scope with no enabled delivery subscription to sign it with (422). */
34
+ probeCallbackRequiresSubscription = 'probe_callback_requires_subscription',
33
35
  }
@@ -1,2 +1,2 @@
1
- export * from './api-error.enum';
2
- export * from './probe-scan.enum';
1
+ export * from './api-error.enum';
2
+ export * from './probe-scan.enum';
@@ -18,8 +18,9 @@ export enum ProbeScanVerdict {
18
18
  /**
19
19
  * How the scan was (or will be) run: `SYNC` blocks the request until the
20
20
  * engine returns the verdict inline; `ASYNC` queues the job and delivers the
21
- * verdict later via a registered webhook and/or the per-request
22
- * `callbackUrl`, and/or by polling `GET /scan/:scanId`.
21
+ * verdict later through the scope's delivery subscriptions (Flow) and/or the
22
+ * per-request `callbackUrl` (delivered once through such a subscription), and/or by
23
+ * polling `GET /scan/:scanId`.
23
24
  */
24
25
  export enum ProbeScanMode {
25
26
  SYNC = 'sync',
@@ -1,2 +1,2 @@
1
- export * from './enum';
2
- export * from './interface';
1
+ export * from './enum';
2
+ export * from './interface';
@@ -1,5 +1,5 @@
1
- export * from './requests';
2
- export * from './responses';
3
- export * from './type-message/response';
4
- export * from './type-message/api-error';
5
- export * from './type-message/base-paginate';
1
+ export * from './requests';
2
+ export * from './responses';
3
+ export * from './type-message/response';
4
+ export * from './type-message/api-error';
5
+ export * from './type-message/base-paginate';
@@ -1,3 +1,4 @@
1
1
  export * from './probe-scan.request';
2
2
  export * from './probe-usage.request';
3
3
  export * from './probe-webhook.request';
4
+ export * from './probe-delivery-subscription.request';
@@ -0,0 +1,42 @@
1
+ import type { DeliveryStatus } from '@abyss-project/flow';
2
+
3
+ // Mirrors apps/api/src/api/validators/probe-delivery-subscription.validator.ts. A client's
4
+ // subscriptions to the verdict of its scans live in Flow; AbyssProbe checks who may manage them
5
+ // and calls Flow for the scope (the caller, an organisation, or an application).
6
+
7
+ /** Personal scope (default) or an organization, for the personal/org client. */
8
+ export interface IProbeDeliverySubscriptionScopeQuery {
9
+ organizationId?: string;
10
+ }
11
+
12
+ export interface IPaginateProbeDeliverySubscriptionQuery
13
+ extends IProbeDeliverySubscriptionScopeQuery {
14
+ /** @default 1 */
15
+ page?: number;
16
+ /** @default 20 */
17
+ limit?: number;
18
+ isEnabled?: boolean;
19
+ }
20
+
21
+ export interface ICreateProbeDeliverySubscriptionBody {
22
+ /** Only `PROBE_SCAN_COMPLETED` (`DeliveryEventType.PROBE_SCAN_COMPLETED` of `@abyss-project/flow`). */
23
+ eventTypes: string[];
24
+ /** HTTPS endpoint the verdict is POSTed to. */
25
+ url: string;
26
+ }
27
+
28
+ /** At least one field is required. */
29
+ export interface IUpdateProbeDeliverySubscriptionBody {
30
+ eventTypes?: string[];
31
+ url?: string;
32
+ isEnabled?: boolean;
33
+ }
34
+
35
+ /** Deliveries of one subscription, or of every subscription of the scope. */
36
+ export interface IPaginateProbeDeliveryQuery extends IProbeDeliverySubscriptionScopeQuery {
37
+ /** @default 1 */
38
+ page?: number;
39
+ /** @default 20 */
40
+ limit?: number;
41
+ status?: DeliveryStatus;
42
+ }
@@ -1,54 +1,54 @@
1
- import { ProbeScanMode, ProbeScanStatus, ProbeScanVerdict } from '../../../enum';
2
-
3
- // Mirrors apps/api/src/api/controllers/probe-scan.controller.ts's ScanBody +
4
- // HistoryQuery, and apps/api/src/api/validators/probe-scan.validator.ts's
5
- // historyQuery() Joi schema (field names/optionality).
6
-
7
- /**
8
- * Options accepted by `sdk.probe.scan(file, options)` — `POST /scan`. `mode`
9
- * and `organizationId` travel as query params (`?mode=async&organization_id=`);
10
- * `context` and `callbackUrl` travel as multipart text fields alongside the
11
- * file — the sdk client handles that split, callers just pass one object.
12
- */
13
- export interface IScanOptions {
14
- /** sync (default — verdict returned inline) or async (queued, 202 + webhook/poll). */
15
- mode?: ProbeScanMode;
16
- /** Personal scope (default) or an organization the caller belongs to. */
17
- organizationId?: string;
18
- /** Free-form caller reference (e.g. `{ applicationFileId }`), stored verbatim. */
19
- context?: Record<string, unknown>;
20
- /** ASYNC-only per-request delivery override (https only). Ignored for a SYNC scan. */
21
- callbackUrl?: string;
22
- /** Filename reported to the server (defaults to `'file'`). Cosmetic only. */
23
- filename?: string;
24
- /**
25
- * Content-Type stamped on the file part when the caller passes raw bytes
26
- * (`Buffer`/`Uint8Array`). Ignored when the file is already a `Blob` — a
27
- * browser `File` and `fs.openAsBlob(path)` carry their own type.
28
- */
29
- mimeType?: string;
30
- }
31
-
32
- /**
33
- * `GET /scan` query — all filters optional, combined with AND.
34
- * `contextKey`/`contextValue` must be supplied together (business-reference
35
- * search inside the free-form `context` JSONB column) — supplying one
36
- * without the other is rejected by the API (400).
37
- */
38
- export interface IListScansQuery {
39
- organizationId?: string;
40
- verdict?: ProbeScanVerdict;
41
- mode?: ProbeScanMode;
42
- status?: ProbeScanStatus;
43
- /** Date range on `createdAt`, inclusive at both ends. */
44
- from?: Date;
45
- to?: Date;
46
- /** Case-insensitive partial match on the original file name. */
47
- fileName?: string;
48
- contextKey?: string;
49
- contextValue?: string;
50
- /** @default 1 */
51
- page?: number;
52
- /** @default 20, server max 200. */
53
- limit?: number;
54
- }
1
+ import { ProbeScanMode, ProbeScanStatus, ProbeScanVerdict } from '../../../enum';
2
+
3
+ // Mirrors apps/api/src/api/controllers/probe-scan.controller.ts's ScanBody +
4
+ // HistoryQuery, and apps/api/src/api/validators/probe-scan.validator.ts's
5
+ // historyQuery() Joi schema (field names/optionality).
6
+
7
+ /**
8
+ * Options accepted by `sdk.probe.scan(file, options)` — `POST /scan`. `mode`
9
+ * and `organizationId` travel as query params (`?mode=async&organization_id=`);
10
+ * `context` and `callbackUrl` travel as multipart text fields alongside the
11
+ * file — the sdk client handles that split, callers just pass one object.
12
+ */
13
+ export interface IScanOptions {
14
+ /** sync (default — verdict returned inline) or async (queued, 202 + webhook/poll). */
15
+ mode?: ProbeScanMode;
16
+ /** Personal scope (default) or an organization the caller belongs to. */
17
+ organizationId?: string;
18
+ /** Free-form caller reference (e.g. `{ applicationFileId }`), stored verbatim. */
19
+ context?: Record<string, unknown>;
20
+ /** ASYNC-only per-request delivery override (https only). Ignored for a SYNC scan. */
21
+ callbackUrl?: string;
22
+ /** Filename reported to the server (defaults to `'file'`). Cosmetic only. */
23
+ filename?: string;
24
+ /**
25
+ * Content-Type stamped on the file part when the caller passes raw bytes
26
+ * (`Buffer`/`Uint8Array`). Ignored when the file is already a `Blob` — a
27
+ * browser `File` and `fs.openAsBlob(path)` carry their own type.
28
+ */
29
+ mimeType?: string;
30
+ }
31
+
32
+ /**
33
+ * `GET /scan` query — all filters optional, combined with AND.
34
+ * `contextKey`/`contextValue` must be supplied together (business-reference
35
+ * search inside the free-form `context` JSONB column) — supplying one
36
+ * without the other is rejected by the API (400).
37
+ */
38
+ export interface IListScansQuery {
39
+ organizationId?: string;
40
+ verdict?: ProbeScanVerdict;
41
+ mode?: ProbeScanMode;
42
+ status?: ProbeScanStatus;
43
+ /** Date range on `createdAt`, inclusive at both ends. */
44
+ from?: Date;
45
+ to?: Date;
46
+ /** Case-insensitive partial match on the original file name. */
47
+ fileName?: string;
48
+ contextKey?: string;
49
+ contextValue?: string;
50
+ /** @default 1 */
51
+ page?: number;
52
+ /** @default 20, server max 200. */
53
+ limit?: number;
54
+ }
@@ -1,7 +1,7 @@
1
- // WS5-3 (AbyssProbe UX rework) — `GET /usage` / `GET /application/:applicationId/usage`.
2
- // Mirrors apps/api/src/api/validators/probe-usage.validator.ts's Joi schema.
3
-
4
- /** `GET /usage` query — personal scope (default) or an organization. Not needed for the application variant (its scope is the `:applicationId` URL segment). */
5
- export interface IProbeUsageScopeQuery {
6
- organizationId?: string;
7
- }
1
+ // WS5-3 (AbyssProbe UX rework) — `GET /usage` / `GET /application/:applicationId/usage`.
2
+ // Mirrors apps/api/src/api/validators/probe-usage.validator.ts's Joi schema.
3
+
4
+ /** `GET /usage` query — personal scope (default) or an organization. Not needed for the application variant (its scope is the `:applicationId` URL segment). */
5
+ export interface IProbeUsageScopeQuery {
6
+ organizationId?: string;
7
+ }
@@ -1,11 +1,9 @@
1
- // Mirrors apps/api/src/api/controllers/probe-webhook.controller.ts's
2
- // ScopeQuery/CreateBody/UpdateBody and probe-webhook.validator.ts's Joi
3
- // schemas.
4
-
5
- /** Shared by create/list/delete/update — personal scope (default) or an organization. */
6
- export interface IProbeWebhookScopeQuery {
7
- organizationId?: string;
8
- }
1
+ // Mirrors apps/api/src/api/controllers/probe-webhook-application.controller.ts's
2
+ // CreateBody/UpdateBody and probe-webhook.validator.ts's Joi schemas.
3
+ //
4
+ // INTERNAL (P5 #792): the application webhooks serve AbyssStorage's antivirus subscription until
5
+ // its client subscriptions move to Flow (L2). A client's own subscriptions are the Flow
6
+ // delivery subscriptions (probe-delivery-subscription.request.ts).
9
7
 
10
8
  export interface ICreateProbeWebhookBody {
11
9
  /** HTTPS endpoint the verdict is POSTed to. Required, `https://` only. */
@@ -13,7 +11,7 @@ export interface ICreateProbeWebhookBody {
13
11
  }
14
12
 
15
13
  /**
16
- * `PATCH /webhook/:webhookId` body (WS5-5) — at least one field required
14
+ * `PATCH /application/:applicationId/webhook/:webhookId` body (WS5-5) — at least one field required
17
15
  * (mirrors probe-webhook.validator.ts#updateBody's `.min(1)`); omitted
18
16
  * fields are left unchanged.
19
17
  */
@@ -24,8 +22,8 @@ export interface IUpdateProbeWebhookBody {
24
22
  active?: boolean;
25
23
  }
26
24
 
27
- /** `GET /webhook/:webhookId/deliveries` query (WS5-6) — paginated. */
28
- export interface IListProbeWebhookDeliveriesQuery extends IProbeWebhookScopeQuery {
25
+ /** `GET /application/:applicationId/webhook/:webhookId/deliveries` query (WS5-6) — paginated. */
26
+ export interface IListProbeWebhookDeliveriesQuery {
29
27
  /** @default 1 */
30
28
  page?: number;
31
29
  /** @default 20 */
@@ -1,3 +1,4 @@
1
1
  export * from './probe-scan.response';
2
2
  export * from './probe-usage.response';
3
3
  export * from './probe-webhook.response';
4
+ export * from './probe-delivery-subscription.response';
@@ -0,0 +1,27 @@
1
+ import type {
2
+ ICreateDeliverySubscriptionResponse,
3
+ IDeleteDeliverySubscriptionResponse,
4
+ IGetDeliveryResponse,
5
+ IGetDeliverySubscriptionResponse,
6
+ IPaginateDeliveryResponse,
7
+ IPaginateDeliverySubscriptionResponse,
8
+ IReplayDeliveryResponse,
9
+ IResetSecretDeliverySubscriptionResponse,
10
+ IUpdateDeliverySubscriptionResponse,
11
+ } from '@abyss-project/flow';
12
+
13
+ // The answers are Flow's own, passed through: the subscription and delivery models of
14
+ // `@abyss-project/flow`. The secret leaves only with a creation and a reset.
15
+
16
+ export type IPaginateProbeDeliverySubscriptionResponse = IPaginateDeliverySubscriptionResponse;
17
+ export type IGetProbeDeliverySubscriptionResponse = IGetDeliverySubscriptionResponse;
18
+ /** `secret` is returned here once. */
19
+ export type ICreateProbeDeliverySubscriptionResponse = ICreateDeliverySubscriptionResponse;
20
+ export type IUpdateProbeDeliverySubscriptionResponse = IUpdateDeliverySubscriptionResponse;
21
+ export type IDeleteProbeDeliverySubscriptionResponse = IDeleteDeliverySubscriptionResponse;
22
+ /** The new `secret` is returned here once; the previous one stops signing. */
23
+ export type IResetSecretProbeDeliverySubscriptionResponse =
24
+ IResetSecretDeliverySubscriptionResponse;
25
+ export type IPaginateProbeDeliveryResponse = IPaginateDeliveryResponse;
26
+ export type IGetProbeDeliveryResponse = IGetDeliveryResponse;
27
+ export type IReplayProbeDeliveryResponse = IReplayDeliveryResponse;
@@ -1,45 +1,45 @@
1
- import { IResponse } from '../type-message/response';
2
- import { BasePaginate } from '../type-message/base-paginate';
3
- import { ProbeScanStatus, ProbeScanVerdict } from '../../../enum';
4
- import { IProbeScanDetail, IProbeScanHistoryItem } from '../../models';
5
-
6
- // Mirrors apps/api/src/api/controllers/probe-scan.controller.ts's local
7
- // ScanSyncResponseData / ScanAsyncResponseData / GetScanResponseData /
8
- // PaginateScanResponseData EXACTLY.
9
-
10
- /** `POST /scan` (default, or explicit `?mode=sync`) — HTTP 200. */
11
- export interface IScanSyncData {
12
- scanId: string;
13
- verdict: ProbeScanVerdict;
14
- viruses: string[];
15
- /**
16
- * `ACCOUNT_AV_SCAN_UNITS` this scan consumed (WS5-1/2 — see
17
- * `estimateProbeScanCost`). Always a number here (never null): a SYNC
18
- * response is only ever sent once the scan has reached a verdict, at
19
- * which point the cost is always known and already billed.
20
- */
21
- costUnits: number;
22
- }
23
- export type IScanSyncResponse = IResponse<IScanSyncData>;
24
-
25
- /** `POST /scan?mode=async` — HTTP 202, job queued. */
26
- export interface IScanAsyncData {
27
- scanId: string;
28
- status: ProbeScanStatus.QUEUED;
29
- }
30
- export type IScanAsyncResponse = IResponse<IScanAsyncData>;
31
-
32
- /**
33
- * `POST /scan`'s actual response body is one or the other of the two data
34
- * shapes above, discriminated by the request's own `mode` (sync -> 200 +
35
- * {@link IScanSyncData}, async -> 202 + {@link IScanAsyncData}). A caller
36
- * that only ever uses one mode should prefer the sdk's `scanSync`/`scanAsync`
37
- * wrappers, which return the precise, non-union type.
38
- */
39
- export type IScanResponse = IScanSyncResponse | IScanAsyncResponse;
40
-
41
- /** `GET /scan/:scanId` — HTTP 200. */
42
- export type IGetScanResponse = IResponse<IProbeScanDetail>;
43
-
44
- /** `GET /scan` — HTTP 200, paginated history/search. */
45
- export type IPaginateScanResponse = IResponse<BasePaginate<IProbeScanHistoryItem>>;
1
+ import { IResponse } from '../type-message/response';
2
+ import { BasePaginate } from '../type-message/base-paginate';
3
+ import { ProbeScanStatus, ProbeScanVerdict } from '../../../enum';
4
+ import { IProbeScanDetail, IProbeScanHistoryItem } from '../../models';
5
+
6
+ // Mirrors apps/api/src/api/controllers/probe-scan.controller.ts's local
7
+ // ScanSyncResponseData / ScanAsyncResponseData / GetScanResponseData /
8
+ // PaginateScanResponseData EXACTLY.
9
+
10
+ /** `POST /scan` (default, or explicit `?mode=sync`) — HTTP 200. */
11
+ export interface IScanSyncData {
12
+ scanId: string;
13
+ verdict: ProbeScanVerdict;
14
+ viruses: string[];
15
+ /**
16
+ * `ACCOUNT_AV_SCAN_UNITS` this scan consumed (WS5-1/2 — see
17
+ * `estimateProbeScanCost`). Always a number here (never null): a SYNC
18
+ * response is only ever sent once the scan has reached a verdict, at
19
+ * which point the cost is always known and already billed.
20
+ */
21
+ costUnits: number;
22
+ }
23
+ export type IScanSyncResponse = IResponse<IScanSyncData>;
24
+
25
+ /** `POST /scan?mode=async` — HTTP 202, job queued. */
26
+ export interface IScanAsyncData {
27
+ scanId: string;
28
+ status: ProbeScanStatus.QUEUED;
29
+ }
30
+ export type IScanAsyncResponse = IResponse<IScanAsyncData>;
31
+
32
+ /**
33
+ * `POST /scan`'s actual response body is one or the other of the two data
34
+ * shapes above, discriminated by the request's own `mode` (sync -> 200 +
35
+ * {@link IScanSyncData}, async -> 202 + {@link IScanAsyncData}). A caller
36
+ * that only ever uses one mode should prefer the sdk's `scanSync`/`scanAsync`
37
+ * wrappers, which return the precise, non-union type.
38
+ */
39
+ export type IScanResponse = IScanSyncResponse | IScanAsyncResponse;
40
+
41
+ /** `GET /scan/:scanId` — HTTP 200. */
42
+ export type IGetScanResponse = IResponse<IProbeScanDetail>;
43
+
44
+ /** `GET /scan` — HTTP 200, paginated history/search. */
45
+ export type IPaginateScanResponse = IResponse<BasePaginate<IProbeScanHistoryItem>>;
@@ -1,25 +1,25 @@
1
- import { IResponse } from '../type-message/response';
2
-
3
- // WS5-3 (AbyssProbe UX rework) — mirrors
4
- // apps/api/src/api/controllers/probe-usage.controller.ts's local response
5
- // shape EXACTLY. Current ACCOUNT_AV_SCAN_UNITS ("tokens") consumption for the
6
- // caller's scope, via the same billing check the quota gate itself uses.
7
-
8
- export interface IProbeUsageData {
9
- /** Units consumed so far in the current billing period. */
10
- used: number;
11
- /**
12
- * Plan cap. `-1` is this codebase's established "unlimited" sentinel (see
13
- * `utils/billing-emit.util.ts#UNLIMITED_EXPIRY_DAYS` server-side) — an
14
- * unmetered plan tier reports `-1` here rather than `Infinity`/`null`, so
15
- * treat a negative value as "no cap", never a literal negative quota.
16
- */
17
- limit: number;
18
- /**
19
- * `limit - used`, floored at 0 — except it mirrors `limit`'s own `-1`
20
- * sentinel unchanged when `limit` is unlimited (never a finite number in
21
- * that case).
22
- */
23
- remaining: number;
24
- }
25
- export type IProbeUsageResponse = IResponse<IProbeUsageData>;
1
+ import { IResponse } from '../type-message/response';
2
+
3
+ // WS5-3 (AbyssProbe UX rework) — mirrors
4
+ // apps/api/src/api/controllers/probe-usage.controller.ts's local response
5
+ // shape EXACTLY. Current ACCOUNT_AV_SCAN_UNITS ("tokens") consumption for the
6
+ // caller's scope, via the same billing check the quota gate itself uses.
7
+
8
+ export interface IProbeUsageData {
9
+ /** Units consumed so far in the current billing period. */
10
+ used: number;
11
+ /**
12
+ * Plan cap. `-1` is this codebase's established "unlimited" sentinel (see
13
+ * `utils/billing-emit.util.ts#UNLIMITED_EXPIRY_DAYS` server-side) — an
14
+ * unmetered plan tier reports `-1` here rather than `Infinity`/`null`, so
15
+ * treat a negative value as "no cap", never a literal negative quota.
16
+ */
17
+ limit: number;
18
+ /**
19
+ * `limit - used`, floored at 0 — except it mirrors `limit`'s own `-1`
20
+ * sentinel unchanged when `limit` is unlimited (never a finite number in
21
+ * that case).
22
+ */
23
+ remaining: number;
24
+ }
25
+ export type IProbeUsageResponse = IResponse<IProbeUsageData>;
@@ -1,24 +1,24 @@
1
- import { IResponse } from '../type-message/response';
2
- import { BasePaginate } from '../type-message/base-paginate';
3
- import { IProbeWebhook, IProbeWebhookDelivery } from '../../models';
4
-
5
- // Mirrors apps/api/src/api/controllers/probe-webhook.controller.ts's local
6
- // response shapes EXACTLY.
7
-
8
- /** `POST /webhook` — HTTP 201. `secret` is re-displayable (WS5-7) — also returned by GET/PATCH, not just here. */
9
- export type ICreateProbeWebhookResponse = IResponse<IProbeWebhook>;
10
-
11
- /** `GET /webhook` — HTTP 200. A flat scope-filtered list, NOT paginated. `secret` included per row (WS5-7). */
12
- export interface IListProbeWebhookData {
13
- webhooks: IProbeWebhook[];
14
- }
15
- export type IListProbeWebhookResponse = IResponse<IListProbeWebhookData>;
16
-
17
- /** `DELETE /webhook/:webhookId` — HTTP 200. */
18
- export type IDeleteProbeWebhookResponse = IResponse<{ ok: true }>;
19
-
20
- /** `PATCH /webhook/:webhookId` — HTTP 200 (WS5-5). `secret` included, same as every other webhook read. */
21
- export type IUpdateProbeWebhookResponse = IResponse<IProbeWebhook>;
22
-
23
- /** `GET /webhook/:webhookId/deliveries` — HTTP 200, paginated (WS5-6). */
24
- export type IListProbeWebhookDeliveriesResponse = IResponse<BasePaginate<IProbeWebhookDelivery>>;
1
+ import { IResponse } from '../type-message/response';
2
+ import { BasePaginate } from '../type-message/base-paginate';
3
+ import { IProbeWebhook, IProbeWebhookDelivery } from '../../models';
4
+
5
+ // Mirrors apps/api/src/api/controllers/probe-webhook.controller.ts's local
6
+ // response shapes EXACTLY.
7
+
8
+ /** `POST /webhook` — HTTP 201. `secret` is re-displayable (WS5-7) — also returned by GET/PATCH, not just here. */
9
+ export type ICreateProbeWebhookResponse = IResponse<IProbeWebhook>;
10
+
11
+ /** `GET /webhook` — HTTP 200. A flat scope-filtered list, NOT paginated. `secret` included per row (WS5-7). */
12
+ export interface IListProbeWebhookData {
13
+ webhooks: IProbeWebhook[];
14
+ }
15
+ export type IListProbeWebhookResponse = IResponse<IListProbeWebhookData>;
16
+
17
+ /** `DELETE /webhook/:webhookId` — HTTP 200. */
18
+ export type IDeleteProbeWebhookResponse = IResponse<{ ok: true }>;
19
+
20
+ /** `PATCH /webhook/:webhookId` — HTTP 200 (WS5-5). `secret` included, same as every other webhook read. */
21
+ export type IUpdateProbeWebhookResponse = IResponse<IProbeWebhook>;
22
+
23
+ /** `GET /webhook/:webhookId/deliveries` — HTTP 200, paginated (WS5-6). */
24
+ export type IListProbeWebhookDeliveriesResponse = IResponse<BasePaginate<IProbeWebhookDelivery>>;
@@ -1,7 +1,7 @@
1
- import { Code, ErrorType } from '../../../enum';
2
-
3
- export interface IApiError {
4
- code: Code;
5
- type: ErrorType;
6
- message?: string;
7
- }
1
+ import { Code, ErrorType } from '../../../enum';
2
+
3
+ export interface IApiError {
4
+ code: Code;
5
+ type: ErrorType;
6
+ message?: string;
7
+ }