@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,33 @@
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
+ }
9
+
10
+ export interface ICreateProbeWebhookBody {
11
+ /** HTTPS endpoint the verdict is POSTed to. Required, `https://` only. */
12
+ callbackUrl: string;
13
+ }
14
+
15
+ /**
16
+ * `PATCH /webhook/:webhookId` body (WS5-5) — at least one field required
17
+ * (mirrors probe-webhook.validator.ts#updateBody's `.min(1)`); omitted
18
+ * fields are left unchanged.
19
+ */
20
+ export interface IUpdateProbeWebhookBody {
21
+ /** HTTPS endpoint the verdict is POSTed to, `https://` only. */
22
+ callbackUrl?: string;
23
+ /** Disabled webhooks are skipped by dispatch (soft-off, not deleted). */
24
+ active?: boolean;
25
+ }
26
+
27
+ /** `GET /webhook/:webhookId/deliveries` query (WS5-6) — paginated. */
28
+ export interface IListProbeWebhookDeliveriesQuery extends IProbeWebhookScopeQuery {
29
+ /** @default 1 */
30
+ page?: number;
31
+ /** @default 20 */
32
+ limit?: number;
33
+ }
@@ -3,7 +3,6 @@ import { IResponse } from '../type-message/response';
3
3
  import { IBeamTransfer, IBeamFile, IBeamRecipient } from '../../models/beam.dto';
4
4
  import { IContentShare } from '../../models/content-share.dto';
5
5
  import { BeamVisibility, BeamServeDenyReasonCode, BeamDownloadKind } from '../../../enum/beam.enum';
6
- import { FileScanStatus } from '../../../enum/file-scan-status.enum';
7
6
 
8
7
  export interface IGetBeamData {
9
8
  beamTransfer: IBeamTransfer;
@@ -41,16 +40,7 @@ export type IFinalizeBeamResponse = IResponse<IFinalizeBeamData>;
41
40
  // browser-facing view: no owner ids, no password/manage hashes; adds
42
41
  // hasPassword/isLocked/hasThumbnail so the front can render the locked state.
43
42
  export interface IBeamPublicFile {
44
- // AV v3 P3 async-enforce — the listing endpoint (GET /b/:slug) is the ONE
45
- // beam serve path that is not gated by beamServingService.gateFile (it is
46
- // a metadata list, not a byte stream). Per the link-live-gate-per-file
47
- // decision the share link itself always works, but a file whose own
48
- // scanStatus is not (yet) CLEAN must not hand out a servable identifier:
49
- // id is null and hasThumbnail is forced false so the front cannot build a
50
- // download/thumb URL for a pending or quarantined file. A legacy NULL
51
- // scanStatus (row written before this column existed) is treated as
52
- // servable, matching gateFile.
53
- id: string | null;
43
+ id: string;
54
44
  name: string;
55
45
  sizeOctet: number;
56
46
  mimeType: string | null;
@@ -58,10 +48,6 @@ export interface IBeamPublicFile {
58
48
  hasThumbnail: boolean;
59
49
  width: number | null;
60
50
  height: number | null;
61
- // Exposed as-is (never redacted) regardless of servability, so the front
62
- // can render an "analysing" placeholder for a withheld file instead of it
63
- // just silently vanishing from the list.
64
- scanStatus: FileScanStatus | null;
65
51
  }
66
52
 
67
53
  export interface IBeamPublicView {
@@ -31,3 +31,6 @@ export * from './recent.response';
31
31
  export * from './transfer.response';
32
32
  export * from './extraction.response';
33
33
  export * from './monitor.response';
34
+ export * from './probe-scan.response';
35
+ export * from './probe-webhook.response';
36
+ export * from './probe-usage.response';
@@ -0,0 +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>>;
@@ -0,0 +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>;
@@ -0,0 +1,24 @@
1
+ import { IResponse } from '../type-message/response';
2
+ import { BasePaginate } from '../type-message/base-paginate';
3
+ import { IProbeWebhook, IProbeWebhookCreated, 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<IProbeWebhookCreated>;
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,19 +1,11 @@
1
1
  import { IAtlasPage } from './atlas-page.dto';
2
2
  import { IAtlas } from './atlas.dto';
3
- import { FileScanStatus } from '../../enum/file-scan-status.enum';
4
3
 
5
4
  export interface IAtlasDocument {
6
5
  id: string;
7
6
  atlasPageId: string;
8
7
  atlasId: string;
9
8
  name: string;
10
- // AV v3 P2 async-enforce — WIRE CAVEAT: these 4 fields type as always-present
11
- // here (the true, always-populated stored/model shape), but the HTTP JSON
12
- // response actually redacts all four to `null` while scanStatus is
13
- // 'pending_scan' (see the AtlasDocument model's toJSON() override) —
14
- // pending_scan grants no servable identifier to any caller, owner included.
15
- // A future front consumer of this DTO must treat them as possibly-null at
16
- // runtime whenever scanStatus === 'pending_scan', despite the `string` type.
17
9
  externalId: string;
18
10
  publicAccessId: string;
19
11
  thumbnailId: string | null;
@@ -21,16 +13,6 @@ export interface IAtlasDocument {
21
13
  sizeOctet: number;
22
14
  mimeType: string;
23
15
  checksum: string;
24
- // AV v3 P2 async-enforce: antivirus verdict mirrored from AbyssStorage,
25
- // seeded pending_scan at the UPLOAD webhook, updated by applyScanResult /
26
- // purgeInfected on the SCAN_RESULT webhook. Null for rows created before
27
- // this column existed. See assertNotPendingScan for the 423 gate.
28
- scanStatus: FileScanStatus | null;
29
- // Id of the user who requested this upload (currentUser at presign time),
30
- // resolved server-side — never client-supplied. Null for an API-key/
31
- // anonymous upload. Used ONLY to notify the uploader if the file is later
32
- // found infected (purgeInfected) — not a permission/ownership field.
33
- uploadedByUserId: string | null;
34
16
  createdAt?: Date;
35
17
  updatedAt?: Date;
36
18
 
@@ -2,7 +2,6 @@ import { IOrganization } from './organization.dto';
2
2
  import { IUser } from './user.dto';
3
3
  import { IProject } from './project.dto';
4
4
  import { BeamVisibility, BeamDownloadKind } from '../../enum/beam.enum';
5
- import { FileScanStatus } from '../../enum/file-scan-status.enum';
6
5
 
7
6
  export interface IBeamTransfer {
8
7
  id: string;
@@ -39,13 +38,6 @@ export interface IBeamTransfer {
39
38
  export interface IBeamFile {
40
39
  id: string;
41
40
  transferId: string;
42
- // AV v3 P3 async-enforce — WIRE CAVEAT: typed as always-present here (the
43
- // true, always-populated stored/model shape), but the HTTP JSON response
44
- // actually redacts this (and thumbnailStorageFileId) to null while
45
- // scanStatus is 'pending_scan' (see the BeamFile model's get() override) —
46
- // pending_scan grants no servable identifier to any caller. A future front
47
- // consumer of this DTO must treat it as possibly-null at runtime whenever
48
- // scanStatus === 'pending_scan', despite the `string` type.
49
41
  // abyss-storage applicationFileId (PRIVATE bucket); resolved at serve time (B4).
50
42
  storageFileId: string;
51
43
  thumbnailStorageFileId: string | null;
@@ -59,20 +51,6 @@ export interface IBeamFile {
59
51
  position: number;
60
52
  createdAt?: Date;
61
53
 
62
- // AV v3 P3 async-enforce: antivirus verdict mirrored from AbyssStorage,
63
- // seeded at attach time (beamUploadService#attachFiles — REQUIRES
64
- // pending_scan, a server-side backstop against a client presign that
65
- // omitted antivirus enrollment; see resumable-upload.ts) and updated by
66
- // applyScanResult / purgeInfected on the SCAN_RESULT webhook. Null for
67
- // rows created before this column existed. See
68
- // beamServingService#gateFile for the per-file serve gate.
69
- scanStatus: FileScanStatus | null;
70
- // Id of the user who requested this attach (currentUser at attach time,
71
- // resolved server-side — never client-supplied). Null for an anonymous
72
- // transfer's attach. Used ONLY to notify the uploader if the file is later
73
- // found infected (purgeInfected) — not a permission/ownership field.
74
- uploadedByUserId: string | null;
75
-
76
54
  transfer?: IBeamTransfer;
77
55
  }
78
56
 
@@ -1,19 +1,11 @@
1
1
  import { IBoardCard } from './board-card.dto';
2
2
  import { IBoard } from './board.dto';
3
- import { FileScanStatus } from '../../enum/file-scan-status.enum';
4
3
 
5
4
  export interface IBoardCardDocument {
6
5
  id: string;
7
6
  boardCardId: string;
8
7
  boardId: string;
9
8
  name: string;
10
- // AV v3 P2 async-enforce — WIRE CAVEAT: these 4 fields type as always-present
11
- // here (the true, always-populated stored/model shape), but the HTTP JSON
12
- // response actually redacts all four to `null` while scanStatus is
13
- // 'pending_scan' (see the BoardCardDocument model's toJSON() override) —
14
- // pending_scan grants no servable identifier to any caller, owner included.
15
- // A future front consumer of this DTO must treat them as possibly-null at
16
- // runtime whenever scanStatus === 'pending_scan', despite the `string` type.
17
9
  externalId: string;
18
10
  publicAccessId: string;
19
11
  thumbnailId: string | null;
@@ -21,16 +13,6 @@ export interface IBoardCardDocument {
21
13
  checksum: string;
22
14
  mimeType: string;
23
15
  sizeOctet: number;
24
- // AV v3 P2 async-enforce: antivirus verdict mirrored from AbyssStorage,
25
- // seeded pending_scan at the UPLOAD webhook, updated by applyScanResult /
26
- // purgeInfected on the SCAN_RESULT webhook. Null for rows created before
27
- // this column existed. See assertNotPendingScan for the 423 gate.
28
- scanStatus: FileScanStatus | null;
29
- // Id of the user who requested this upload (currentUser at presign time),
30
- // resolved server-side — never client-supplied. Null for an API-key/
31
- // anonymous upload. Used ONLY to notify the uploader if the file is later
32
- // found infected (purgeInfected) — not a permission/ownership field.
33
- uploadedByUserId: string | null;
34
16
  updatedAt?: Date;
35
17
  createdAt?: Date;
36
18
 
@@ -6,7 +6,6 @@
6
6
  import { ExtractionWarningCode } from '../../../types/enum/extraction-warning.enum';
7
7
  import { ExtractionFeedbackIssueType } from '../../../types/enum/extraction-feedback-issue-type.enum';
8
8
  import { DocumentType } from '../../../types/enum/document-type.enum';
9
- import { FileScanStatus } from '../../enum/file-scan-status.enum';
10
9
  import type { IFieldValue, IExecutionManifest, IGlobalConfidence } from './extraction-plan.dto';
11
10
 
12
11
  // Re-export so consumers can import ExtractionFeedbackIssueType from the DTO barrel.
@@ -67,13 +66,6 @@ export interface IExtractionFile {
67
66
  pdfMimeType: string;
68
67
  pdfPageCount: number | null;
69
68
  pdfFilename: string | null;
70
- // AV v3 P3 async-enforce — WIRE CAVEAT: typed always-present here (the
71
- // stored/model shape), but the HTTP JSON response redacts this to `null`
72
- // while scanStatus is 'pending_scan' (see the ExtractionFile model's
73
- // get() override) — pending_scan grants no servable identifier to any
74
- // caller, owner included. Never gated for a by-reference (caller-owned)
75
- // file: AbyssExtract never mirrors a scan verdict locally for those (see
76
- // scanStatus below), gating on the caller's live verdict instead.
77
69
  applicationFileId: string | null;
78
70
  userExternalId: string | null;
79
71
  userMetadata: Record<string, unknown> | null;
@@ -82,15 +74,6 @@ export interface IExtractionFile {
82
74
  detectedIban: string | null;
83
75
  detectedBic: string | null;
84
76
  detectedCurrency: string | null;
85
- // AV v3 P3 async-enforce: antivirus verdict mirrored from AbyssStorage for
86
- // an ARCHIVE-OWNED file only (seeded at extractionFileService.upsert from
87
- // the archive-upload response — see extraction-extract.service.ts#archivePdf).
88
- // Null for by-reference files (gated live on the caller's own verdict
89
- // instead — no local mirror, since AbyssExtract never receives a
90
- // SCAN_RESULT webhook for a file it did not request the scan for) and for
91
- // rows created before this column existed. See assertNotPendingScan for
92
- // the 423 gate this enables on derived-output endpoints.
93
- scanStatus: FileScanStatus | null;
94
77
  createdAt: string;
95
78
  updatedAt: string;
96
79
  }
@@ -32,3 +32,6 @@ export * from './content-share.dto';
32
32
  export * from './extraction.dto';
33
33
  export * from './extraction-plan.dto';
34
34
  export * from './extraction-spatial-template.dto';
35
+ export * from './probe-scan.dto';
36
+ export * from './probe-webhook.dto';
37
+ export * from './probe-webhook-delivery.dto';
@@ -0,0 +1,67 @@
1
+ import { ProbeScanMode, ProbeScanStatus, ProbeScanVerdict } from '../../enum';
2
+
3
+ // Mirrors apps/api/src/api/controllers/probe-scan.controller.ts's local
4
+ // response interfaces. AbyssProbe deliberately returns TWO different scan
5
+ // shapes depending on the endpoint — never the raw `probe_scans` row, and
6
+ // never a single one-size-fits-all model — so this file mirrors that with
7
+ // two distinct interfaces rather than forcing one canonical "IProbeScan".
8
+
9
+ /**
10
+ * `GET /scan/:scanId` shape (poll the queued -> scanning -> done/error
11
+ * progression). WS5-4 (AbyssProbe UX rework) widened this to full metadata
12
+ * parity with {@link IProbeScanHistoryItem} (fileName/fileSize/mimeType/
13
+ * mode/startedAt/finishedAt/costUnits) — the scanner UI's "Détails" section
14
+ * needs the same info whether it got there via the list or via a direct
15
+ * poll — still never echoing internal ownership columns (userId,
16
+ * organizationId, callbackUrl) — a caller polling by id already knows what
17
+ * it submitted.
18
+ */
19
+ export interface IProbeScanDetail {
20
+ scanId: string;
21
+ status: ProbeScanStatus;
22
+ /** null until `status` is DONE. */
23
+ verdict: ProbeScanVerdict | null;
24
+ /** null until `status` is DONE; [] when DONE and clean. */
25
+ viruses: string[] | null;
26
+ /** Free-form caller reference echoed back verbatim (see IProbeScanHistoryItem#context). */
27
+ context: Record<string, unknown> | null;
28
+ fileName: string;
29
+ fileSize: number;
30
+ mimeType: string;
31
+ mode: ProbeScanMode;
32
+ /** Set the moment the engine call starts (SYNC: row-creation time; ASYNC: when a worker picks the job off the queue). */
33
+ startedAt: Date;
34
+ /** Set once the engine call returns. null while status is not DONE. */
35
+ finishedAt: Date | null;
36
+ /**
37
+ * `ACCOUNT_AV_SCAN_UNITS` this scan consumed (see `estimateProbeScanCost`
38
+ * — this package's own shared pure cost model). null until `status` is
39
+ * DONE; stays null forever for a scan that errors out (no verdict was ever
40
+ * reached, so nothing was ever billed).
41
+ */
42
+ costUnits: number | null;
43
+ }
44
+
45
+ /**
46
+ * One row of `GET /scan`'s paginated history/search list. Never echoes
47
+ * internal ownership columns (userId, organizationId, callbackUrl) — a
48
+ * caller already knows their own scope from the request they made.
49
+ */
50
+ export interface IProbeScanHistoryItem {
51
+ scanId: string;
52
+ fileName: string;
53
+ fileSize: number;
54
+ mimeType: string;
55
+ verdict: ProbeScanVerdict | null;
56
+ viruses: string[] | null;
57
+ mode: ProbeScanMode;
58
+ status: ProbeScanStatus;
59
+ context: Record<string, unknown> | null;
60
+ /** Set the moment the engine call starts (SYNC: row-creation time; ASYNC: when a worker picks the job off the queue). */
61
+ startedAt: Date;
62
+ /** Set once the engine call returns. null while status is not DONE. */
63
+ finishedAt: Date | null;
64
+ /** See {@link IProbeScanDetail#costUnits}. */
65
+ costUnits: number | null;
66
+ createdAt: Date;
67
+ }
@@ -0,0 +1,73 @@
1
+ import { ProbeScanVerdict } from '../../enum';
2
+
3
+ // Mirrors apps/api/src/services/probe-webhook-delivery.service.ts's
4
+ // ProbeWebhookPayload EXACTLY (same field set, same JSON.stringify'd body a
5
+ // receiver's raw request body will deserialize into) — this is the payload
6
+ // AbyssProbe POSTs to every registered webhook's `callbackUrl` (and to a
7
+ // scan's own per-request `callbackUrl`, see probe-scan docs) once an ASYNC
8
+ // scan reaches a verdict (`status: DONE`).
9
+ //
10
+ // `verdict` is typed as the concrete enum here (not `string` like the
11
+ // server's internal type) because delivery only ever happens on a DONE scan,
12
+ // where the verdict is always set — see dispatchProbeScanWebhooks's guard.
13
+
14
+ /**
15
+ * Body of a webhook delivery, signed via HMAC-SHA256 of
16
+ * `JSON.stringify(payload)` — see {@link PROBE_WEBHOOK_SIGNATURE_HEADER} and
17
+ * {@link verifyProbeWebhookSignature} (this package's root / utils).
18
+ */
19
+ export interface IProbeWebhookDeliveryPayload {
20
+ scanId: string;
21
+ /** Free-form caller reference, echoed back verbatim (see IProbeScanHistoryItem#context). */
22
+ context: Record<string, unknown> | null;
23
+ verdict: ProbeScanVerdict;
24
+ /** [] when clean. */
25
+ viruses: string[];
26
+ /**
27
+ * `ACCOUNT_AV_SCAN_UNITS` this scan consumed (WS5-1). Delivery only ever
28
+ * happens on a DONE scan, where the cost is always already computed and
29
+ * billed — see {@link IProbeScanHistoryItem#costUnits}.
30
+ */
31
+ costUnits: number | null;
32
+ }
33
+
34
+ // ─── Delivery HISTORY (WS5-6) ────────────────
35
+ //
36
+ // The interface above is the PAYLOAD a webhook receiver gets POSTed. This
37
+ // section is a DIFFERENT concept: the persisted AUDIT ROW AbyssProbe keeps
38
+ // of its OWN delivery attempts (one row per attempt — mirrors
39
+ // apps/api/src/database/models/probe-webhook-delivery.model.ts EXACTLY,
40
+ // itself modelled after this package's own extraction-webhook
41
+ // delivery-history shape, trimmed to AbyssProbe's simpler
42
+ // one-attempt-per-row reality — see that model's header comment). Read via
43
+ // `GET /webhook/:webhookId/deliveries` (`sdk.probe.webhook.listDeliveries`).
44
+
45
+ /**
46
+ * One persisted delivery-attempt row, as returned (paginated) by
47
+ * `GET /webhook/:webhookId/deliveries`.
48
+ */
49
+ export interface IProbeWebhookDelivery {
50
+ id: string;
51
+ /**
52
+ * The registered webhook this delivery targeted. null for a delivery to a
53
+ * scan's own ad-hoc per-request `callbackUrl` that matched no registered
54
+ * webhook (see the server model's own doc comment) — such a row is never
55
+ * reachable via this webhook-scoped endpoint in practice (there is no
56
+ * webhookId to query it under), but the field stays nullable to mirror the
57
+ * server column's real type.
58
+ */
59
+ webhookId: string | null;
60
+ /** The scan whose verdict this delivery carried. */
61
+ scanId: string;
62
+ /** The exact URL this attempt POSTed to. */
63
+ url: string;
64
+ /** HTTP status code received. null when the request never got a response (network error / timeout / abort). */
65
+ statusCode: number | null;
66
+ /** true only for a 2xx response. */
67
+ success: boolean;
68
+ /** When this attempt was made. */
69
+ attemptedAt: Date;
70
+ /** Failure reason (HTTP non-2xx status, or the caught network/timeout error's message). null on success. */
71
+ error: string | null;
72
+ createdAt: Date;
73
+ }
@@ -0,0 +1,39 @@
1
+ // Mirrors apps/api/src/api/controllers/probe-webhook.controller.ts's local
2
+ // WebhookResponseData / CreateWebhookResponseData. Public shape of a
3
+ // registered `probe_webhooks` row — never echoes the internal ownership
4
+ // columns (userId/organizationId/applicationId), same discipline as the
5
+ // scan models.
6
+ //
7
+ // WS5-7 (AbyssProbe UX rework): `secret` is ALWAYS re-displayable now —
8
+ // returned on every read (GET /webhook list, and PATCH /webhook/:id), not
9
+ // just once on create. Mirrors how AbyssExtract's own webhook model
10
+ // (`IExtractionWebhookDelivery`'s sibling `ExtractionWebhook` — see
11
+ // apps/api/src/database/models/extraction-webhook.model.ts /
12
+ // extraction-webhook.controller.ts) has always exposed its
13
+ // `webhookSecret` column on every response, never a once-only reveal. This
14
+ // lets a consumer (e.g. abyss-storage's own webhook registration) read its
15
+ // secret back at any time instead of relying on a log-once bootstrap.
16
+
17
+ export interface IProbeWebhook {
18
+ id: string;
19
+ /** HTTPS endpoint the verdict is POSTed to. */
20
+ callbackUrl: string;
21
+ /**
22
+ * Server-generated HMAC-SHA256 signing secret. Re-displayable: returned on
23
+ * every read (list/create/update), not once-only — see this interface's
24
+ * own header note (WS5-7).
25
+ */
26
+ secret: string;
27
+ /** Disabled webhooks are skipped by dispatch (soft-off, not deleted). */
28
+ active: boolean;
29
+ createdAt: Date;
30
+ }
31
+
32
+ /**
33
+ * @deprecated Structurally identical to {@link IProbeWebhook} now that
34
+ * `secret` is always re-displayable (WS5-7) — kept as a source-compatible
35
+ * alias (no removal, no consumer breakage) for existing imports that named
36
+ * this type explicitly for the old "only right after creation" contract.
37
+ * Prefer {@link IProbeWebhook} directly in new code.
38
+ */
39
+ export type IProbeWebhookCreated = IProbeWebhook;
@@ -46,8 +46,6 @@ describe('beam DTOs', () => {
46
46
  height: 600,
47
47
  downloadCount: 0,
48
48
  position: 0,
49
- scanStatus: null,
50
- uploadedByUserId: null,
51
49
  };
52
50
  const recipient: IBeamRecipient = {
53
51
  id: 'r1',