@abyss-project/tools 2.1.0 → 2.3.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 (152) hide show
  1. package/dist/api/index.d.ts +6 -0
  2. package/dist/api/index.js +6 -0
  3. package/dist/api/index.js.map +1 -1
  4. package/dist/api/probe-scan.api.d.ts +15 -0
  5. package/dist/api/probe-scan.api.js +74 -0
  6. package/dist/api/probe-scan.api.js.map +1 -0
  7. package/dist/api/probe-scan.api.test.d.ts +1 -0
  8. package/dist/api/probe-scan.api.test.js +37 -0
  9. package/dist/api/probe-scan.api.test.js.map +1 -0
  10. package/dist/api/probe-scan.application.api.d.ts +7 -0
  11. package/dist/api/probe-scan.application.api.js +40 -0
  12. package/dist/api/probe-scan.application.api.js.map +1 -0
  13. package/dist/api/probe-scan.application.api.test.d.ts +1 -0
  14. package/dist/api/probe-scan.application.api.test.js +37 -0
  15. package/dist/api/probe-scan.application.api.test.js.map +1 -0
  16. package/dist/api/probe-usage.api.d.ts +2 -0
  17. package/dist/api/probe-usage.api.js +24 -0
  18. package/dist/api/probe-usage.api.js.map +1 -0
  19. package/dist/api/probe-usage.application.api.d.ts +2 -0
  20. package/dist/api/probe-usage.application.api.js +12 -0
  21. package/dist/api/probe-usage.application.api.js.map +1 -0
  22. package/dist/api/probe-webhook.api.d.ts +6 -0
  23. package/dist/api/probe-webhook.api.js +41 -0
  24. package/dist/api/probe-webhook.api.js.map +1 -0
  25. package/dist/api/probe-webhook.api.test.d.ts +1 -0
  26. package/dist/api/probe-webhook.api.test.js +33 -0
  27. package/dist/api/probe-webhook.api.test.js.map +1 -0
  28. package/dist/api/probe-webhook.application.api.d.ts +6 -0
  29. package/dist/api/probe-webhook.application.api.js +27 -0
  30. package/dist/api/probe-webhook.application.api.js.map +1 -0
  31. package/dist/api/probe-webhook.application.api.test.d.ts +1 -0
  32. package/dist/api/probe-webhook.application.api.test.js +33 -0
  33. package/dist/api/probe-webhook.application.api.test.js.map +1 -0
  34. package/dist/index.d.ts +43 -0
  35. package/dist/index.js +44 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/types/enum/api-error.enum.d.ts +1 -5
  38. package/dist/types/enum/api-error.enum.js +0 -4
  39. package/dist/types/enum/api-error.enum.js.map +1 -1
  40. package/dist/types/enum/index.d.ts +1 -1
  41. package/dist/types/enum/index.js +1 -1
  42. package/dist/types/enum/index.js.map +1 -1
  43. package/dist/types/enum/probe-scan.enum.d.ts +14 -0
  44. package/dist/types/enum/probe-scan.enum.js +21 -0
  45. package/dist/types/enum/probe-scan.enum.js.map +1 -0
  46. package/dist/types/interface/api/requests/index.d.ts +3 -0
  47. package/dist/types/interface/api/requests/index.js +3 -0
  48. package/dist/types/interface/api/requests/index.js.map +1 -1
  49. package/dist/types/interface/api/requests/probe-scan.request.d.ts +22 -0
  50. package/dist/types/interface/api/{responses/file-scan.response.js → requests/probe-scan.request.js} +1 -1
  51. package/dist/types/interface/api/requests/probe-scan.request.js.map +1 -0
  52. package/dist/types/interface/api/requests/probe-usage.request.d.ts +3 -0
  53. package/dist/types/{enum/file-scan-status.enum.js → interface/api/requests/probe-usage.request.js} +1 -1
  54. package/dist/types/interface/api/requests/probe-usage.request.js.map +1 -0
  55. package/dist/types/interface/api/requests/probe-webhook.request.d.ts +14 -0
  56. package/dist/types/interface/api/requests/probe-webhook.request.js +3 -0
  57. package/dist/types/interface/api/requests/probe-webhook.request.js.map +1 -0
  58. package/dist/types/interface/api/responses/beam.response.d.ts +1 -3
  59. package/dist/types/interface/api/responses/index.d.ts +3 -0
  60. package/dist/types/interface/api/responses/index.js +3 -0
  61. package/dist/types/interface/api/responses/index.js.map +1 -1
  62. package/dist/types/interface/api/responses/probe-scan.response.d.ts +19 -0
  63. package/dist/types/interface/api/responses/probe-scan.response.js +3 -0
  64. package/dist/types/interface/api/responses/probe-scan.response.js.map +1 -0
  65. package/dist/types/interface/api/responses/probe-usage.response.d.ts +7 -0
  66. package/dist/types/interface/api/responses/probe-usage.response.js +3 -0
  67. package/dist/types/interface/api/responses/probe-usage.response.js.map +1 -0
  68. package/dist/types/interface/api/responses/probe-webhook.response.d.ts +13 -0
  69. package/dist/types/interface/api/responses/probe-webhook.response.js +3 -0
  70. package/dist/types/interface/api/responses/probe-webhook.response.js.map +1 -0
  71. package/dist/types/interface/models/atlas-document.dto.d.ts +0 -3
  72. package/dist/types/interface/models/beam.dto.d.ts +0 -3
  73. package/dist/types/interface/models/board-card-document.dto.d.ts +0 -3
  74. package/dist/types/interface/models/extraction.dto.d.ts +0 -2
  75. package/dist/types/interface/models/extraction.dto.js.map +1 -1
  76. package/dist/types/interface/models/index.d.ts +3 -0
  77. package/dist/types/interface/models/index.js +3 -0
  78. package/dist/types/interface/models/index.js.map +1 -1
  79. package/dist/types/interface/models/probe-scan.dto.d.ts +30 -0
  80. package/dist/types/interface/models/{file-scan.dto.js → probe-scan.dto.js} +1 -1
  81. package/dist/types/interface/models/probe-scan.dto.js.map +1 -0
  82. package/dist/types/interface/models/probe-webhook-delivery.dto.d.ts +19 -0
  83. package/dist/types/interface/models/probe-webhook-delivery.dto.js +3 -0
  84. package/dist/types/interface/models/probe-webhook-delivery.dto.js.map +1 -0
  85. package/dist/types/interface/models/probe-webhook.dto.d.ts +8 -0
  86. package/dist/types/interface/{api/requests/file-scan.request.js → models/probe-webhook.dto.js} +1 -1
  87. package/dist/types/interface/models/probe-webhook.dto.js.map +1 -0
  88. package/dist/types/tests/probe.dto.test.d.ts +1 -0
  89. package/dist/types/tests/probe.dto.test.js +101 -0
  90. package/dist/types/tests/probe.dto.test.js.map +1 -0
  91. package/dist/utils/index.d.ts +2 -0
  92. package/dist/utils/index.js +2 -0
  93. package/dist/utils/index.js.map +1 -1
  94. package/dist/utils/probe-scan-cost.utils.d.ts +5 -0
  95. package/dist/utils/probe-scan-cost.utils.js +21 -0
  96. package/dist/utils/probe-scan-cost.utils.js.map +1 -0
  97. package/dist/utils/probe-webhook-signature.utils.d.ts +8 -0
  98. package/dist/utils/probe-webhook-signature.utils.js +22 -0
  99. package/dist/utils/probe-webhook-signature.utils.js.map +1 -0
  100. package/package.json +1 -1
  101. package/src/api/index.ts +8 -0
  102. package/src/api/probe-scan.api.test.ts +21 -0
  103. package/src/api/probe-scan.api.ts +191 -0
  104. package/src/api/probe-scan.application.api.test.ts +21 -0
  105. package/src/api/probe-scan.application.api.ts +157 -0
  106. package/src/api/probe-usage.api.ts +47 -0
  107. package/src/api/probe-usage.application.api.ts +25 -0
  108. package/src/api/probe-webhook.api.test.ts +17 -0
  109. package/src/api/probe-webhook.api.ts +119 -0
  110. package/src/api/probe-webhook.application.api.test.ts +18 -0
  111. package/src/api/probe-webhook.application.api.ts +141 -0
  112. package/src/index.ts +114 -0
  113. package/src/types/enum/api-error.enum.ts +0 -25
  114. package/src/types/enum/index.ts +1 -1
  115. package/src/types/enum/probe-scan.enum.ts +44 -0
  116. package/src/types/interface/api/requests/index.ts +3 -0
  117. package/src/types/interface/api/requests/probe-scan.request.ts +50 -0
  118. package/src/types/interface/api/requests/probe-usage.request.ts +7 -0
  119. package/src/types/interface/api/requests/probe-webhook.request.ts +33 -0
  120. package/src/types/interface/api/responses/beam.response.ts +1 -15
  121. package/src/types/interface/api/responses/index.ts +3 -0
  122. package/src/types/interface/api/responses/probe-scan.response.ts +45 -0
  123. package/src/types/interface/api/responses/probe-usage.response.ts +25 -0
  124. package/src/types/interface/api/responses/probe-webhook.response.ts +24 -0
  125. package/src/types/interface/models/atlas-document.dto.ts +0 -18
  126. package/src/types/interface/models/beam.dto.ts +0 -22
  127. package/src/types/interface/models/board-card-document.dto.ts +0 -18
  128. package/src/types/interface/models/extraction.dto.ts +0 -17
  129. package/src/types/interface/models/index.ts +3 -0
  130. package/src/types/interface/models/probe-scan.dto.ts +67 -0
  131. package/src/types/interface/models/probe-webhook-delivery.dto.ts +73 -0
  132. package/src/types/interface/models/probe-webhook.dto.ts +39 -0
  133. package/src/types/tests/beam.dto.spec.ts +0 -2
  134. package/src/types/tests/probe.dto.test.ts +159 -0
  135. package/src/utils/index.ts +2 -0
  136. package/src/utils/probe-scan-cost.utils.ts +101 -0
  137. package/src/utils/probe-webhook-signature.utils.ts +56 -0
  138. package/dist/api/file-scan.api.d.ts +0 -5
  139. package/dist/api/file-scan.api.js +0 -49
  140. package/dist/api/file-scan.api.js.map +0 -1
  141. package/dist/types/enum/analysis-status.enum.d.ts +0 -7
  142. package/dist/types/enum/analysis-status.enum.js +0 -12
  143. package/dist/types/enum/analysis-status.enum.js.map +0 -1
  144. package/dist/types/enum/file-scan-status.enum.d.ts +0 -1
  145. package/dist/types/enum/file-scan-status.enum.js.map +0 -1
  146. package/dist/types/interface/api/requests/file-scan.request.d.ts +0 -3
  147. package/dist/types/interface/api/requests/file-scan.request.js.map +0 -1
  148. package/dist/types/interface/api/responses/file-scan.response.d.ts +0 -7
  149. package/dist/types/interface/api/responses/file-scan.response.js.map +0 -1
  150. package/dist/types/interface/models/file-scan.dto.d.ts +0 -11
  151. package/dist/types/interface/models/file-scan.dto.js.map +0 -1
  152. package/src/types/enum/file-scan-status.enum.ts +0 -23
@@ -0,0 +1,47 @@
1
+ // ──────────────────────────────────────────────
2
+ // AbyssProbe usage API — WS5-3 (AbyssProbe UX rework). `GET /usage`: current
3
+ // ACCOUNT_AV_SCAN_UNITS ("tokens") used/limit/remaining for the caller's
4
+ // scope, via the same billing check the quota gate itself already uses (see
5
+ // apps/api/src/utils/probe-scan-billing.util.ts#getProbeScanUsage). Mirrors
6
+ // apps/api/src/api/controllers/probe-usage.controller.ts EXACTLY. No
7
+ // `probe/` path prefix — `@Controller({ prefixPath: '/usage' })` mounts
8
+ // directly at `usage`.
9
+ //
10
+ // See probe-usage.application.api.ts for the application/API-key-auth
11
+ // counterpart (`/application/:applicationId/usage`, Phase 3a).
12
+ // ──────────────────────────────────────────────
13
+
14
+ import { AbyssToolsCore } from '..';
15
+ import type { IProbeUsageScopeQuery, IProbeUsageResponse } from '../types';
16
+
17
+ const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
18
+
19
+ function authHeader(apiKey?: string): Record<string, string> {
20
+ return apiKey ? { [DEFAULT_API_KEY_HEADER]: apiKey } : {};
21
+ }
22
+
23
+ /** Renames `organizationId` to the wire's `organization_id` (see probe-scan.api.ts). */
24
+ function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
25
+ const out: Record<string, unknown> = {};
26
+ for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
27
+ if (value === undefined || value === null) continue;
28
+ const wireKey = key === 'organizationId' ? 'organization_id' : key;
29
+ out[wireKey] = value;
30
+ }
31
+ return out;
32
+ }
33
+
34
+ /**
35
+ * `GET /usage` — current ACCOUNT_AV_SCAN_UNITS consumption for the caller's
36
+ * scope (personal by default, `organizationId` for an organization scope).
37
+ */
38
+ export const getProbeUsage = async (
39
+ scope: IProbeUsageScopeQuery = {},
40
+ apiKey?: string,
41
+ ): Promise<IProbeUsageResponse> =>
42
+ (
43
+ await AbyssToolsCore.axios.get<IProbeUsageResponse>('usage', {
44
+ params: serializeProbeQuery(scope),
45
+ headers: authHeader(apiKey),
46
+ })
47
+ ).data;
@@ -0,0 +1,25 @@
1
+ // ──────────────────────────────────────────────
2
+ // AbyssProbe APPLICATION usage API — WS5-3 (AbyssProbe UX rework). `GET
3
+ // /application/:applicationId/usage`: current ACCOUNT_AV_SCAN_UNITS
4
+ // consumption for the calling application's resolved billing organization.
5
+ // Mirrors apps/api/src/api/controllers/probe-usage-application.controller.ts
6
+ // EXACTLY — the application counterpart of probe-usage.api.ts.
7
+ // ──────────────────────────────────────────────
8
+
9
+ import { AbyssToolsCore, API_KEY_APPLICATION_HEADER } from '..';
10
+ import type { IProbeUsageResponse } from '../types';
11
+
12
+ function authHeaderApplication(applicationApiKey?: string): Record<string, string> {
13
+ return applicationApiKey ? { [API_KEY_APPLICATION_HEADER]: applicationApiKey } : {};
14
+ }
15
+
16
+ /** `GET /application/:applicationId/usage` — current ACCOUNT_AV_SCAN_UNITS consumption for the calling application. */
17
+ export const getProbeUsageApplication = async (
18
+ applicationId: string,
19
+ applicationApiKey?: string,
20
+ ): Promise<IProbeUsageResponse> =>
21
+ (
22
+ await AbyssToolsCore.axios.get<IProbeUsageResponse>(`application/${applicationId}/usage`, {
23
+ headers: authHeaderApplication(applicationApiKey),
24
+ })
25
+ ).data;
@@ -0,0 +1,17 @@
1
+ // Type-level compile test for the probe-webhook api surface.
2
+ // No jest runner in this SDK package; compile guard only.
3
+ // Run: npx tsc --noEmit (from packages/abyss_tools_core), or `npm run build`.
4
+
5
+ import * as api from './probe-webhook.api';
6
+
7
+ // All three functions must be exported — deliberately no update/reset-secret
8
+ // (see probe-webhook.controller.ts's header comment on the small CRUD surface).
9
+ const _create: typeof api.createProbeWebhook = api.createProbeWebhook;
10
+ const _list: typeof api.listProbeWebhook = api.listProbeWebhook;
11
+ const _delete: typeof api.deleteProbeWebhook = api.deleteProbeWebhook;
12
+
13
+ void _create;
14
+ void _list;
15
+ void _delete;
16
+
17
+ export {};
@@ -0,0 +1,119 @@
1
+ // ──────────────────────────────────────────────
2
+ // AbyssProbe webhook subscription API — CRUD over registered `probe_webhooks`
3
+ // (create / list / delete / update, + paginated delivery history — mirrors
4
+ // apps/api/src/api/controllers/probe-webhook.controller.ts EXACTLY, see that
5
+ // file's header comment). No `probe/` path prefix — `@Controller({
6
+ // prefixPath: '/webhook' })` mounts directly at `webhook`.
7
+ //
8
+ // See probe-webhook.application.api.ts for the application/API-key-auth
9
+ // counterpart of this client (`/application/:applicationId/webhook...`,
10
+ // Phase 3a) — it reuses every request/response type verbatim; only the URL
11
+ // prefix, the extra `applicationId` argument, and the auth header differ.
12
+ // ──────────────────────────────────────────────
13
+
14
+ import { AbyssToolsCore } from '..';
15
+ import type {
16
+ ICreateProbeWebhookBody,
17
+ IUpdateProbeWebhookBody,
18
+ IProbeWebhookScopeQuery,
19
+ IListProbeWebhookDeliveriesQuery,
20
+ ICreateProbeWebhookResponse,
21
+ IListProbeWebhookResponse,
22
+ IDeleteProbeWebhookResponse,
23
+ IUpdateProbeWebhookResponse,
24
+ IListProbeWebhookDeliveriesResponse,
25
+ } from '../types';
26
+
27
+ const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
28
+
29
+ function authHeader(apiKey?: string): Record<string, string> {
30
+ return apiKey ? { [DEFAULT_API_KEY_HEADER]: apiKey } : {};
31
+ }
32
+
33
+ /** Renames `organizationId` to the wire's `organization_id` (see probe-scan.api.ts). */
34
+ function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
35
+ const out: Record<string, unknown> = {};
36
+ for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
37
+ if (value === undefined || value === null) continue;
38
+ const wireKey = key === 'organizationId' ? 'organization_id' : key;
39
+ out[wireKey] = value instanceof Date ? value.toISOString() : value;
40
+ }
41
+ return out;
42
+ }
43
+
44
+ /**
45
+ * `POST /webhook` — register a callbackUrl for the caller's scope. The
46
+ * response's `secret` field (HMAC signing secret) is returned ONLY here —
47
+ * store it immediately, it cannot be re-revealed later.
48
+ */
49
+ export const createProbeWebhook = async (
50
+ body: ICreateProbeWebhookBody,
51
+ scope: IProbeWebhookScopeQuery = {},
52
+ apiKey?: string,
53
+ ): Promise<ICreateProbeWebhookResponse> =>
54
+ (
55
+ await AbyssToolsCore.axios.post<ICreateProbeWebhookResponse>('webhook', body, {
56
+ params: serializeProbeQuery(scope),
57
+ headers: authHeader(apiKey),
58
+ })
59
+ ).data;
60
+
61
+ /** `GET /webhook` — flat, scope-filtered list (not paginated — bounded by WEBHOOK_MAX_PER_SCOPE server-side). */
62
+ export const listProbeWebhook = async (
63
+ scope: IProbeWebhookScopeQuery = {},
64
+ apiKey?: string,
65
+ ): Promise<IListProbeWebhookResponse> =>
66
+ (
67
+ await AbyssToolsCore.axios.get<IListProbeWebhookResponse>('webhook', {
68
+ params: serializeProbeQuery(scope),
69
+ headers: authHeader(apiKey),
70
+ })
71
+ ).data;
72
+
73
+ /** `DELETE /webhook/:webhookId`. */
74
+ export const deleteProbeWebhook = async (
75
+ webhookId: string,
76
+ scope: IProbeWebhookScopeQuery = {},
77
+ apiKey?: string,
78
+ ): Promise<IDeleteProbeWebhookResponse> =>
79
+ (
80
+ await AbyssToolsCore.axios.delete<IDeleteProbeWebhookResponse>(`webhook/${webhookId}`, {
81
+ params: serializeProbeQuery(scope),
82
+ headers: authHeader(apiKey),
83
+ })
84
+ ).data;
85
+
86
+ /**
87
+ * `PATCH /webhook/:webhookId` (WS5-5) — edit `callbackUrl` and/or `active`.
88
+ * At least one field is required. Scoped like {@link deleteProbeWebhook}
89
+ * (404, never 403, for a webhookId outside the resolved scope). The response
90
+ * includes `secret` — re-displayable now, see {@link IProbeWebhook}.
91
+ */
92
+ export const updateProbeWebhook = async (
93
+ webhookId: string,
94
+ body: IUpdateProbeWebhookBody,
95
+ scope: IProbeWebhookScopeQuery = {},
96
+ apiKey?: string,
97
+ ): Promise<IUpdateProbeWebhookResponse> =>
98
+ (
99
+ await AbyssToolsCore.axios.patch<IUpdateProbeWebhookResponse>(`webhook/${webhookId}`, body, {
100
+ params: serializeProbeQuery(scope),
101
+ headers: authHeader(apiKey),
102
+ })
103
+ ).data;
104
+
105
+ /**
106
+ * `GET /webhook/:webhookId/deliveries` (WS5-6) — paginated delivery-attempt
107
+ * history for one registered webhook. Scoped like {@link deleteProbeWebhook}.
108
+ */
109
+ export const listProbeWebhookDeliveries = async (
110
+ webhookId: string,
111
+ query: IListProbeWebhookDeliveriesQuery = {},
112
+ apiKey?: string,
113
+ ): Promise<IListProbeWebhookDeliveriesResponse> =>
114
+ (
115
+ await AbyssToolsCore.axios.get<IListProbeWebhookDeliveriesResponse>(
116
+ `webhook/${webhookId}/deliveries`,
117
+ { params: serializeProbeQuery(query), headers: authHeader(apiKey) },
118
+ )
119
+ ).data;
@@ -0,0 +1,18 @@
1
+ // Type-level compile test for the probe-webhook APPLICATION api surface.
2
+ // No jest runner in this SDK package; compile guard only (mirrors
3
+ // probe-webhook.api.test.ts).
4
+ // Run: npx tsc --noEmit (from packages/abyss_tools_core), or `npm run build`.
5
+
6
+ import * as api from './probe-webhook.application.api';
7
+
8
+ // All three functions must be exported — deliberately no update/reset-secret
9
+ // (see probe-webhook.api.ts's header comment on the small CRUD surface).
10
+ const _create: typeof api.createProbeWebhookApplication = api.createProbeWebhookApplication;
11
+ const _list: typeof api.listProbeWebhookApplication = api.listProbeWebhookApplication;
12
+ const _delete: typeof api.deleteProbeWebhookApplication = api.deleteProbeWebhookApplication;
13
+
14
+ void _create;
15
+ void _list;
16
+ void _delete;
17
+
18
+ export {};
@@ -0,0 +1,141 @@
1
+ // ──────────────────────────────────────────────
2
+ // AbyssProbe APPLICATION webhook subscription API — CRUD over registered
3
+ // `probe_webhooks` owned by a calling application (create / list / delete /
4
+ // update, + paginated delivery history — same surface as the personal/org
5
+ // client, see probe-webhook.api.ts's header comment). Mirrors
6
+ // apps/api/src/api/controllers/probe-webhook-application.controller.ts
7
+ // EXACTLY — the application counterpart of probe-webhook.api.ts, for
8
+ // inter-service callers (abyss-storage, external integrations)
9
+ // authenticating with a project API key instead of a personal/org session.
10
+ //
11
+ // Reuses every request/response TYPE verbatim (`ICreateProbeWebhookBody`,
12
+ // `ICreateProbeWebhookResponse`, `IListProbeWebhookResponse`,
13
+ // `IDeleteProbeWebhookResponse`, `IUpdateProbeWebhookBody`,
14
+ // `IUpdateProbeWebhookResponse`, `IListProbeWebhookDeliveriesQuery`,
15
+ // `IListProbeWebhookDeliveriesResponse`) — never redefined here. No scope
16
+ // argument/query on any of these calls (unlike the personal/org client's
17
+ // `IProbeWebhookScopeQuery`) — an application caller's scope is entirely its
18
+ // `:applicationId` URL segment, resolved server-side by
19
+ // ProbeApplicationMiddleware; there is nothing to select between.
20
+ //
21
+ // `authHeaderApplication` is kept LOCAL and unexported, same convention as
22
+ // the personal/org client's own `authHeader` — it sends
23
+ // `API_KEY_APPLICATION_HEADER` (`abyss-api-key-application`, imported from
24
+ // this package's root) instead of the personal `abyss-api-key` header.
25
+ // ──────────────────────────────────────────────
26
+
27
+ import { AbyssToolsCore, API_KEY_APPLICATION_HEADER } from '..';
28
+ import type {
29
+ ICreateProbeWebhookBody,
30
+ IUpdateProbeWebhookBody,
31
+ IListProbeWebhookDeliveriesQuery,
32
+ ICreateProbeWebhookResponse,
33
+ IListProbeWebhookResponse,
34
+ IDeleteProbeWebhookResponse,
35
+ IUpdateProbeWebhookResponse,
36
+ IListProbeWebhookDeliveriesResponse,
37
+ } from '../types';
38
+
39
+ function authHeaderApplication(applicationApiKey?: string): Record<string, string> {
40
+ return applicationApiKey ? { [API_KEY_APPLICATION_HEADER]: applicationApiKey } : {};
41
+ }
42
+
43
+ /** Renames nothing (no `organizationId` ever travels on an application call) — drops undefined/null and ISO-stringifies `Date`s, mirroring probe-scan.application.api.ts's own local helper. */
44
+ function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
45
+ const out: Record<string, unknown> = {};
46
+ for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
47
+ if (value === undefined || value === null) continue;
48
+ out[key] = value instanceof Date ? value.toISOString() : value;
49
+ }
50
+ return out;
51
+ }
52
+
53
+ /**
54
+ * `POST /application/:applicationId/webhook` — register a callbackUrl owned
55
+ * by the calling application. The response's `secret` field (HMAC signing
56
+ * secret) is returned ONLY here — store it immediately, it cannot be
57
+ * re-revealed later.
58
+ */
59
+ export const createProbeWebhookApplication = async (
60
+ applicationId: string,
61
+ body: ICreateProbeWebhookBody,
62
+ applicationApiKey?: string,
63
+ ): Promise<ICreateProbeWebhookResponse> =>
64
+ (
65
+ await AbyssToolsCore.axios.post<ICreateProbeWebhookResponse>(
66
+ `application/${applicationId}/webhook`,
67
+ body,
68
+ { headers: authHeaderApplication(applicationApiKey) },
69
+ )
70
+ ).data;
71
+
72
+ /**
73
+ * `GET /application/:applicationId/webhook` — flat list of the calling
74
+ * application's own webhooks (not paginated — bounded by
75
+ * WEBHOOK_MAX_PER_SCOPE server-side).
76
+ */
77
+ export const listProbeWebhookApplication = async (
78
+ applicationId: string,
79
+ applicationApiKey?: string,
80
+ ): Promise<IListProbeWebhookResponse> =>
81
+ (
82
+ await AbyssToolsCore.axios.get<IListProbeWebhookResponse>(
83
+ `application/${applicationId}/webhook`,
84
+ { headers: authHeaderApplication(applicationApiKey) },
85
+ )
86
+ ).data;
87
+
88
+ /**
89
+ * `DELETE /application/:applicationId/webhook/:webhookId` — cross-tenant
90
+ * guarded server-side by a direct `applicationId` comparison (404, never
91
+ * 403).
92
+ */
93
+ export const deleteProbeWebhookApplication = async (
94
+ applicationId: string,
95
+ webhookId: string,
96
+ applicationApiKey?: string,
97
+ ): Promise<IDeleteProbeWebhookResponse> =>
98
+ (
99
+ await AbyssToolsCore.axios.delete<IDeleteProbeWebhookResponse>(
100
+ `application/${applicationId}/webhook/${webhookId}`,
101
+ { headers: authHeaderApplication(applicationApiKey) },
102
+ )
103
+ ).data;
104
+
105
+ /**
106
+ * `PATCH /application/:applicationId/webhook/:webhookId` (WS5-5) — edit
107
+ * `callbackUrl` and/or `active` on a webhook owned by the calling
108
+ * application. Cross-tenant guarded server-side (404, never 403). The
109
+ * response includes `secret` — re-displayable now, see {@link IProbeWebhook}.
110
+ */
111
+ export const updateProbeWebhookApplication = async (
112
+ applicationId: string,
113
+ webhookId: string,
114
+ body: IUpdateProbeWebhookBody,
115
+ applicationApiKey?: string,
116
+ ): Promise<IUpdateProbeWebhookResponse> =>
117
+ (
118
+ await AbyssToolsCore.axios.patch<IUpdateProbeWebhookResponse>(
119
+ `application/${applicationId}/webhook/${webhookId}`,
120
+ body,
121
+ { headers: authHeaderApplication(applicationApiKey) },
122
+ )
123
+ ).data;
124
+
125
+ /**
126
+ * `GET /application/:applicationId/webhook/:webhookId/deliveries` (WS5-6) —
127
+ * paginated delivery-attempt history for one webhook owned by the calling
128
+ * application. Cross-tenant guarded server-side (404, never 403).
129
+ */
130
+ export const listProbeWebhookDeliveriesApplication = async (
131
+ applicationId: string,
132
+ webhookId: string,
133
+ query: Omit<IListProbeWebhookDeliveriesQuery, 'organizationId'> = {},
134
+ applicationApiKey?: string,
135
+ ): Promise<IListProbeWebhookDeliveriesResponse> =>
136
+ (
137
+ await AbyssToolsCore.axios.get<IListProbeWebhookDeliveriesResponse>(
138
+ `application/${applicationId}/webhook/${webhookId}/deliveries`,
139
+ { params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
140
+ )
141
+ ).data;
package/src/index.ts CHANGED
@@ -32,6 +32,12 @@ import * as extractionApi from './api/extraction.api';
32
32
  import * as extractionSettingsApi from './api/extraction-settings.api';
33
33
  import * as extractionPlanPresetApi from './api/extraction-plan-preset.api';
34
34
  import * as monitorApi from './api/monitor.api';
35
+ import * as probeScanApi from './api/probe-scan.api';
36
+ import * as probeWebhookApi from './api/probe-webhook.api';
37
+ import * as probeScanApplicationApi from './api/probe-scan.application.api';
38
+ import * as probeWebhookApplicationApi from './api/probe-webhook.application.api';
39
+ import * as probeUsageApi from './api/probe-usage.api';
40
+ import * as probeUsageApplicationApi from './api/probe-usage.application.api';
35
41
 
36
42
  export * from './api';
37
43
  export * from './types';
@@ -42,8 +48,24 @@ export * from './server-sent-events';
42
48
  const DEFAULT_BASE_URL = 'https://tools-api.abyss-project.fr/api/';
43
49
 
44
50
  export const API_KEY_HEADER = 'abyss-api-key';
51
+ /**
52
+ * Application-level API key header (Phase 3a — AbyssProbe application/API-key
53
+ * authentication). Same literal value every other Abyss service's own core
54
+ * package independently declares for its `ApplicationMiddleware` (abyss-
55
+ * storage, abyss-monitor, abyss-console — see
56
+ * probe-application.middleware.ts for the mirrored resolution logic).
57
+ */
58
+ export const API_KEY_APPLICATION_HEADER = 'abyss-api-key-application';
45
59
  export const ADMIN_TOKEN_HEADER = 'abyss-admin-token';
46
60
 
61
+ /**
62
+ * Header carrying the HMAC-SHA256 signature of a probe webhook delivery's
63
+ * raw JSON body (see apps/api/src/services/probe-webhook-delivery.service.ts).
64
+ * Verify it with {@link verifyProbeWebhookSignature} (re-exported from './utils').
65
+ */
66
+ export const PROBE_WEBHOOK_SIGNATURE_HEADER = 'x-probe-signature';
67
+ export const PROBE_WEBHOOK_SIGNATURE_ALGORITHM = 'sha256';
68
+
47
69
  const NUMBER_RETRY_API = 10;
48
70
  const BASE_DELAY_BETWEEN_RETRY = 5000;
49
71
  const RETRY_CODES = [
@@ -316,6 +338,64 @@ type AbyssToolsCoreSDK = {
316
338
  monitor: {
317
339
  up: typeof monitorApi.upMonitor;
318
340
  };
341
+ probe: {
342
+ /** `POST /scan` — sync (default) or async depending on `options.mode`. */
343
+ scan: typeof probeScanApi.scan;
344
+ /** `POST /scan` forced to `mode: sync` — precisely-typed 200 response. */
345
+ scanSync: typeof probeScanApi.scanSync;
346
+ /** `POST /scan?mode=async` — precisely-typed 202 response. */
347
+ scanAsync: typeof probeScanApi.scanAsync;
348
+ /** `GET /scan/:scanId` — poll a scan's status/verdict. */
349
+ getScan: typeof probeScanApi.getScan;
350
+ /** `GET /scan` — paginated history/search. */
351
+ listScans: typeof probeScanApi.listScans;
352
+ /** `GET /usage` — current ACCOUNT_AV_SCAN_UNITS used/limit/remaining for the caller's scope. */
353
+ usage: {
354
+ get: typeof probeUsageApi.getProbeUsage;
355
+ };
356
+ webhook: {
357
+ create: typeof probeWebhookApi.createProbeWebhook;
358
+ list: typeof probeWebhookApi.listProbeWebhook;
359
+ delete: typeof probeWebhookApi.deleteProbeWebhook;
360
+ /** `PATCH /webhook/:webhookId` — edit callbackUrl and/or active. */
361
+ update: typeof probeWebhookApi.updateProbeWebhook;
362
+ /** `GET /webhook/:webhookId/deliveries` — paginated delivery-attempt history. */
363
+ listDeliveries: typeof probeWebhookApi.listProbeWebhookDeliveries;
364
+ };
365
+ /**
366
+ * Application/API-key-auth counterpart (Phase 3a) — for inter-service
367
+ * callers (abyss-storage, external integrations) instead of a
368
+ * personal/org session. Same request/response contracts as the methods
369
+ * above, hitting `/application/:applicationId/...` and authenticated
370
+ * with the `abyss-api-key-application` header ({@link
371
+ * API_KEY_APPLICATION_HEADER}) instead of the personal `abyss-api-key`.
372
+ */
373
+ application: {
374
+ /** `POST /application/:applicationId/scan` — sync (default) or async depending on `options.mode`. */
375
+ scan: typeof probeScanApplicationApi.scanApplication;
376
+ /** `POST /application/:applicationId/scan` forced to `mode: sync` — precisely-typed 200 response. */
377
+ scanSync: typeof probeScanApplicationApi.scanSyncApplication;
378
+ /** `POST /application/:applicationId/scan?mode=async` — precisely-typed 202 response. */
379
+ scanAsync: typeof probeScanApplicationApi.scanAsyncApplication;
380
+ /** `GET /application/:applicationId/scan/:scanId` — poll a scan's status/verdict. */
381
+ getScan: typeof probeScanApplicationApi.getScanApplication;
382
+ /** `GET /application/:applicationId/scan` — paginated history/search. */
383
+ listScans: typeof probeScanApplicationApi.listScansApplication;
384
+ /** `GET /application/:applicationId/usage` — current ACCOUNT_AV_SCAN_UNITS used/limit/remaining for the calling application. */
385
+ usage: {
386
+ get: typeof probeUsageApplicationApi.getProbeUsageApplication;
387
+ };
388
+ webhook: {
389
+ create: typeof probeWebhookApplicationApi.createProbeWebhookApplication;
390
+ list: typeof probeWebhookApplicationApi.listProbeWebhookApplication;
391
+ delete: typeof probeWebhookApplicationApi.deleteProbeWebhookApplication;
392
+ /** `PATCH /application/:applicationId/webhook/:webhookId` — edit callbackUrl and/or active. */
393
+ update: typeof probeWebhookApplicationApi.updateProbeWebhookApplication;
394
+ /** `GET /application/:applicationId/webhook/:webhookId/deliveries` — paginated delivery-attempt history. */
395
+ listDeliveries: typeof probeWebhookApplicationApi.listProbeWebhookDeliveriesApplication;
396
+ };
397
+ };
398
+ };
319
399
  tag: {
320
400
  list: typeof tagApi.listTag;
321
401
  create: typeof tagApi.createTag;
@@ -707,6 +787,40 @@ export class AbyssToolsCore {
707
787
  monitor: {
708
788
  up: monitorApi.upMonitor,
709
789
  },
790
+ probe: {
791
+ scan: probeScanApi.scan,
792
+ scanSync: probeScanApi.scanSync,
793
+ scanAsync: probeScanApi.scanAsync,
794
+ getScan: probeScanApi.getScan,
795
+ listScans: probeScanApi.listScans,
796
+ usage: {
797
+ get: probeUsageApi.getProbeUsage,
798
+ },
799
+ webhook: {
800
+ create: probeWebhookApi.createProbeWebhook,
801
+ list: probeWebhookApi.listProbeWebhook,
802
+ delete: probeWebhookApi.deleteProbeWebhook,
803
+ update: probeWebhookApi.updateProbeWebhook,
804
+ listDeliveries: probeWebhookApi.listProbeWebhookDeliveries,
805
+ },
806
+ application: {
807
+ scan: probeScanApplicationApi.scanApplication,
808
+ scanSync: probeScanApplicationApi.scanSyncApplication,
809
+ scanAsync: probeScanApplicationApi.scanAsyncApplication,
810
+ getScan: probeScanApplicationApi.getScanApplication,
811
+ listScans: probeScanApplicationApi.listScansApplication,
812
+ usage: {
813
+ get: probeUsageApplicationApi.getProbeUsageApplication,
814
+ },
815
+ webhook: {
816
+ create: probeWebhookApplicationApi.createProbeWebhookApplication,
817
+ list: probeWebhookApplicationApi.listProbeWebhookApplication,
818
+ delete: probeWebhookApplicationApi.deleteProbeWebhookApplication,
819
+ update: probeWebhookApplicationApi.updateProbeWebhookApplication,
820
+ listDeliveries: probeWebhookApplicationApi.listProbeWebhookDeliveriesApplication,
821
+ },
822
+ },
823
+ },
710
824
  tag: {
711
825
  list: tagApi.listTag,
712
826
  create: tagApi.createTag,
@@ -20,29 +20,4 @@ export enum Code {
20
20
  atlasDocumentLimitReached = 'atlas_document_limit_reached',
21
21
  boardCardDocumentLimitReached = 'board_card_document_limit_reached',
22
22
  boardCardMoveInvalidDestination = 'board_card_move_invalid_destination',
23
- // AV v3 P2 async-enforce: thrown by assertNotPendingScan while a document's
24
- // antivirus scan is still running (scanStatus === 'pending_scan'). Mapped
25
- // to HTTP 423 in http-response-error.module.ts.
26
- boardCardDocumentAnalysing = 'board_card_document_analysing',
27
- atlasDocumentAnalysing = 'atlas_document_analysing',
28
- // AV v3 P3 async-enforce: thrown by extractionFileService.assertNotPendingScan
29
- // while an ARCHIVE-OWNED extraction_files row's antivirus scan is still
30
- // running (scanStatus === 'pending_scan'). Gates only derived OUTPUTS
31
- // (bundle/records/diff/export/share) — never the extraction metadata
32
- // itself, which already ran synchronously before any verdict was known.
33
- // Mapped to HTTP 423 in http-response-error.module.ts.
34
- extractionFileAnalysing = 'extraction_file_analysing',
35
- // AV v3 P3 async-enforce server backstop: thrown by
36
- // beamUploadService.attachFiles when a resolved storage file's scanStatus
37
- // is not PENDING_SCAN at attach time. AbyssBeam's presign is front-driven
38
- // (resumable-upload.ts calls AbyssStorage directly, never through this
39
- // backend), so a client could omit `antivirus: { scan: true }` on its own
40
- // presign request; a properly-enrolled fresh upload is always
41
- // PENDING_SCAN the moment attach is called (the async worker has not run
42
- // yet), so anything else — most tellingly a null/absent scanStatus,
43
- // meaning no scan was ever requested — means enrollment was bypassed and
44
- // the attach is rejected outright. Not mapped in http-response-error
45
- // .module.ts's statusByCode table, so it falls through to the default 400
46
- // (a rejected request, not a "still analysing" 423 state).
47
- beamFileNotEnrolled = 'beam_file_not_enrolled',
48
23
  }
@@ -11,4 +11,4 @@ export * from './extraction-feedback-issue-type.enum';
11
11
  export * from './provider-kind.enum';
12
12
  export * from './interpreter-kind.enum';
13
13
  export * from './combine-strategy.enum';
14
- export * from './file-scan-status.enum';
14
+ export * from './probe-scan.enum';
@@ -0,0 +1,44 @@
1
+ // Mirrors apps/api/src/database/probe-scan.enum.ts EXACTLY (same string
2
+ // values — this SDK talks to that API over the wire, so the values must
3
+ // match byte-for-byte). Kept as a single file here too, on purpose: the
4
+ // server groups all three enums in one file for the same reason (they are
5
+ // one cohesive scan vocabulary), see that file's header comment.
6
+
7
+ /**
8
+ * Antivirus scan verdict. `null` on the wire while the scan has not reached
9
+ * `DONE` yet (see {@link ProbeScanStatus}) — a scan that never completes
10
+ * (e.g. the engine throws) is left at its last real status with no
11
+ * fabricated verdict.
12
+ */
13
+ export enum ProbeScanVerdict {
14
+ CLEAN = 'clean',
15
+ INFECTED = 'infected',
16
+ }
17
+
18
+ /**
19
+ * How the scan was (or will be) run: `SYNC` blocks the request until the
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`.
23
+ */
24
+ export enum ProbeScanMode {
25
+ SYNC = 'sync',
26
+ ASYNC = 'async',
27
+ }
28
+
29
+ /**
30
+ * Scan lifecycle. A SYNC scan skips `QUEUED` entirely (created directly at
31
+ * `SCANNING`). An ASYNC scan is created at `QUEUED`, flipped to `SCANNING`
32
+ * once a worker picks the job off the queue, then to `DONE` or `ERROR`.
33
+ *
34
+ * `ERROR` (async-only) is a TERMINAL, no-verdict state — there is no
35
+ * automatic requeue/retry (the uploaded bytes are deleted the moment the job
36
+ * ends, success or failure). A caller that wants to retry submits a brand
37
+ * new `POST /scan?mode=async`.
38
+ */
39
+ export enum ProbeScanStatus {
40
+ QUEUED = 'queued',
41
+ SCANNING = 'scanning',
42
+ DONE = 'done',
43
+ ERROR = 'error',
44
+ }
@@ -27,3 +27,6 @@ export * from './metrics.request';
27
27
  export * from './tag.request';
28
28
  export * from './transfer.request';
29
29
  export * from './extraction.request';
30
+ export * from './probe-scan.request';
31
+ export * from './probe-webhook.request';
32
+ export * from './probe-usage.request';
@@ -0,0 +1,50 @@
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
+ /** Content-Type hint used when constructing a Blob from a raw buffer/Uint8Array in a browser context. */
25
+ mimeType?: string;
26
+ }
27
+
28
+ /**
29
+ * `GET /scan` query — all filters optional, combined with AND.
30
+ * `contextKey`/`contextValue` must be supplied together (business-reference
31
+ * search inside the free-form `context` JSONB column) — supplying one
32
+ * without the other is rejected by the API (400).
33
+ */
34
+ export interface IListScansQuery {
35
+ organizationId?: string;
36
+ verdict?: ProbeScanVerdict;
37
+ mode?: ProbeScanMode;
38
+ status?: ProbeScanStatus;
39
+ /** Date range on `createdAt`, inclusive at both ends. */
40
+ from?: Date;
41
+ to?: Date;
42
+ /** Case-insensitive partial match on the original file name. */
43
+ fileName?: string;
44
+ contextKey?: string;
45
+ contextValue?: string;
46
+ /** @default 1 */
47
+ page?: number;
48
+ /** @default 20, server max 200. */
49
+ limit?: number;
50
+ }
@@ -0,0 +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
+ }