@abyss-project/tools 2.2.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.
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/probe-usage.api.d.ts +2 -0
- package/dist/api/probe-usage.api.js +24 -0
- package/dist/api/probe-usage.api.js.map +1 -0
- package/dist/api/probe-usage.application.api.d.ts +2 -0
- package/dist/api/probe-usage.application.api.js +12 -0
- package/dist/api/probe-usage.application.api.js.map +1 -0
- package/dist/api/probe-webhook.api.d.ts +3 -1
- package/dist/api/probe-webhook.api.js +8 -1
- package/dist/api/probe-webhook.api.js.map +1 -1
- package/dist/api/probe-webhook.application.api.d.ts +3 -1
- package/dist/api/probe-webhook.application.api.js +14 -1
- package/dist/api/probe-webhook.application.api.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/types/interface/api/requests/index.d.ts +1 -0
- package/dist/types/interface/api/requests/index.js +1 -0
- package/dist/types/interface/api/requests/index.js.map +1 -1
- package/dist/types/interface/api/requests/probe-usage.request.d.ts +3 -0
- package/dist/types/interface/api/requests/probe-usage.request.js +3 -0
- package/dist/types/interface/api/requests/probe-usage.request.js.map +1 -0
- package/dist/types/interface/api/requests/probe-webhook.request.d.ts +8 -0
- package/dist/types/interface/api/responses/index.d.ts +1 -0
- package/dist/types/interface/api/responses/index.js +1 -0
- package/dist/types/interface/api/responses/index.js.map +1 -1
- package/dist/types/interface/api/responses/probe-scan.response.d.ts +1 -0
- package/dist/types/interface/api/responses/probe-usage.response.d.ts +7 -0
- package/dist/types/interface/api/responses/probe-usage.response.js +3 -0
- package/dist/types/interface/api/responses/probe-usage.response.js.map +1 -0
- package/dist/types/interface/api/responses/probe-webhook.response.d.ts +4 -1
- package/dist/types/interface/models/probe-scan.dto.d.ts +8 -0
- package/dist/types/interface/models/probe-webhook-delivery.dto.d.ts +12 -0
- package/dist/types/interface/models/probe-webhook.dto.d.ts +2 -3
- package/dist/types/tests/probe.dto.test.js +40 -1
- package/dist/types/tests/probe.dto.test.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/probe-scan-cost.utils.d.ts +5 -0
- package/dist/utils/probe-scan-cost.utils.js +21 -0
- package/dist/utils/probe-scan-cost.utils.js.map +1 -0
- package/package.json +1 -1
- package/src/api/index.ts +2 -0
- package/src/api/probe-usage.api.ts +47 -0
- package/src/api/probe-usage.application.api.ts +25 -0
- package/src/api/probe-webhook.api.ts +43 -5
- package/src/api/probe-webhook.application.api.ts +58 -4
- package/src/index.ts +28 -0
- package/src/types/interface/api/requests/index.ts +1 -0
- package/src/types/interface/api/requests/probe-usage.request.ts +7 -0
- package/src/types/interface/api/requests/probe-webhook.request.ts +23 -2
- package/src/types/interface/api/responses/index.ts +1 -0
- package/src/types/interface/api/responses/probe-scan.response.ts +7 -0
- package/src/types/interface/api/responses/probe-usage.response.ts +25 -0
- package/src/types/interface/api/responses/probe-webhook.response.ts +10 -3
- package/src/types/interface/models/probe-scan.dto.ts +27 -8
- package/src/types/interface/models/probe-webhook-delivery.dto.ts +47 -0
- package/src/types/interface/models/probe-webhook.dto.ts +25 -11
- package/src/types/tests/probe.dto.test.ts +73 -11
- package/src/utils/index.ts +1 -0
- package/src/utils/probe-scan-cost.utils.ts +101 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.estimateProbeScanCost = exports.PROBE_SCAN_COST_MODE_WEIGHT = exports.PROBE_SCAN_COST_K_MB = exports.PROBE_SCAN_COST_BASE = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
exports.PROBE_SCAN_COST_BASE = 1;
|
|
6
|
+
exports.PROBE_SCAN_COST_K_MB = 1;
|
|
7
|
+
exports.PROBE_SCAN_COST_MODE_WEIGHT = {
|
|
8
|
+
[types_1.ProbeScanMode.ASYNC]: 1,
|
|
9
|
+
[types_1.ProbeScanMode.SYNC]: 3,
|
|
10
|
+
};
|
|
11
|
+
const ONE_MB = 1024 * 1024;
|
|
12
|
+
const estimateProbeScanCost = (sizeOctet, mode) => {
|
|
13
|
+
if (!Number.isFinite(sizeOctet) || sizeOctet <= 0) {
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
const megabytes = Math.ceil(sizeOctet / ONE_MB);
|
|
17
|
+
const weight = exports.PROBE_SCAN_COST_MODE_WEIGHT[mode] ?? exports.PROBE_SCAN_COST_MODE_WEIGHT[types_1.ProbeScanMode.ASYNC];
|
|
18
|
+
return Math.round((exports.PROBE_SCAN_COST_BASE + exports.PROBE_SCAN_COST_K_MB * megabytes) * weight);
|
|
19
|
+
};
|
|
20
|
+
exports.estimateProbeScanCost = estimateProbeScanCost;
|
|
21
|
+
//# sourceMappingURL=probe-scan-cost.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe-scan-cost.utils.js","sourceRoot":"","sources":["../../src/utils/probe-scan-cost.utils.ts"],"names":[],"mappings":";;;AAuCA,oCAAyC;AAG5B,QAAA,oBAAoB,GAAG,CAAC,CAAC;AAGzB,QAAA,oBAAoB,GAAG,CAAC,CAAC;AAUzB,QAAA,2BAA2B,GAAkC;IACxE,CAAC,qBAAa,CAAC,KAAK,CAAC,EAAE,CAAC;IACxB,CAAC,qBAAa,CAAC,IAAI,CAAC,EAAE,CAAC;CACxB,CAAC;AAGF,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AA4BpB,MAAM,qBAAqB,GAAG,CACnC,SAAiB,EACjB,IAAsC,EAC9B,EAAE;IACV,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;IAChD,MAAM,MAAM,GACV,mCAA2B,CAAC,IAAI,CAAC,IAAI,mCAA2B,CAAC,qBAAa,CAAC,KAAK,CAAC,CAAC;IACxF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,4BAAoB,GAAG,4BAAoB,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC;AACxF,CAAC,CAAC;AAXW,QAAA,qBAAqB,yBAWhC"}
|
package/package.json
CHANGED
package/src/api/index.ts
CHANGED
|
@@ -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;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// ──────────────────────────────────────────────
|
|
2
2
|
// AbyssProbe webhook subscription API — CRUD over registered `probe_webhooks`
|
|
3
|
-
// (create / list / delete
|
|
4
|
-
// apps/api/src/api/controllers/probe-webhook.controller.ts
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// `webhook`.
|
|
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`.
|
|
8
7
|
//
|
|
9
8
|
// See probe-webhook.application.api.ts for the application/API-key-auth
|
|
10
9
|
// counterpart of this client (`/application/:applicationId/webhook...`,
|
|
@@ -15,10 +14,14 @@
|
|
|
15
14
|
import { AbyssToolsCore } from '..';
|
|
16
15
|
import type {
|
|
17
16
|
ICreateProbeWebhookBody,
|
|
17
|
+
IUpdateProbeWebhookBody,
|
|
18
18
|
IProbeWebhookScopeQuery,
|
|
19
|
+
IListProbeWebhookDeliveriesQuery,
|
|
19
20
|
ICreateProbeWebhookResponse,
|
|
20
21
|
IListProbeWebhookResponse,
|
|
21
22
|
IDeleteProbeWebhookResponse,
|
|
23
|
+
IUpdateProbeWebhookResponse,
|
|
24
|
+
IListProbeWebhookDeliveriesResponse,
|
|
22
25
|
} from '../types';
|
|
23
26
|
|
|
24
27
|
const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
|
|
@@ -79,3 +82,38 @@ export const deleteProbeWebhook = async (
|
|
|
79
82
|
headers: authHeader(apiKey),
|
|
80
83
|
})
|
|
81
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;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// ──────────────────────────────────────────────
|
|
2
2
|
// AbyssProbe APPLICATION webhook subscription API — CRUD over registered
|
|
3
|
-
// `probe_webhooks` owned by a calling application (create / list / delete
|
|
4
|
-
//
|
|
5
|
-
//
|
|
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
6
|
// apps/api/src/api/controllers/probe-webhook-application.controller.ts
|
|
7
7
|
// EXACTLY — the application counterpart of probe-webhook.api.ts, for
|
|
8
8
|
// inter-service callers (abyss-storage, external integrations)
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
//
|
|
11
11
|
// Reuses every request/response TYPE verbatim (`ICreateProbeWebhookBody`,
|
|
12
12
|
// `ICreateProbeWebhookResponse`, `IListProbeWebhookResponse`,
|
|
13
|
-
// `IDeleteProbeWebhookResponse`
|
|
13
|
+
// `IDeleteProbeWebhookResponse`, `IUpdateProbeWebhookBody`,
|
|
14
|
+
// `IUpdateProbeWebhookResponse`, `IListProbeWebhookDeliveriesQuery`,
|
|
15
|
+
// `IListProbeWebhookDeliveriesResponse`) — never redefined here. No scope
|
|
14
16
|
// argument/query on any of these calls (unlike the personal/org client's
|
|
15
17
|
// `IProbeWebhookScopeQuery`) — an application caller's scope is entirely its
|
|
16
18
|
// `:applicationId` URL segment, resolved server-side by
|
|
@@ -25,15 +27,29 @@
|
|
|
25
27
|
import { AbyssToolsCore, API_KEY_APPLICATION_HEADER } from '..';
|
|
26
28
|
import type {
|
|
27
29
|
ICreateProbeWebhookBody,
|
|
30
|
+
IUpdateProbeWebhookBody,
|
|
31
|
+
IListProbeWebhookDeliveriesQuery,
|
|
28
32
|
ICreateProbeWebhookResponse,
|
|
29
33
|
IListProbeWebhookResponse,
|
|
30
34
|
IDeleteProbeWebhookResponse,
|
|
35
|
+
IUpdateProbeWebhookResponse,
|
|
36
|
+
IListProbeWebhookDeliveriesResponse,
|
|
31
37
|
} from '../types';
|
|
32
38
|
|
|
33
39
|
function authHeaderApplication(applicationApiKey?: string): Record<string, string> {
|
|
34
40
|
return applicationApiKey ? { [API_KEY_APPLICATION_HEADER]: applicationApiKey } : {};
|
|
35
41
|
}
|
|
36
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
|
+
|
|
37
53
|
/**
|
|
38
54
|
* `POST /application/:applicationId/webhook` — register a callbackUrl owned
|
|
39
55
|
* by the calling application. The response's `secret` field (HMAC signing
|
|
@@ -85,3 +101,41 @@ export const deleteProbeWebhookApplication = async (
|
|
|
85
101
|
{ headers: authHeaderApplication(applicationApiKey) },
|
|
86
102
|
)
|
|
87
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
|
@@ -36,6 +36,8 @@ import * as probeScanApi from './api/probe-scan.api';
|
|
|
36
36
|
import * as probeWebhookApi from './api/probe-webhook.api';
|
|
37
37
|
import * as probeScanApplicationApi from './api/probe-scan.application.api';
|
|
38
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';
|
|
39
41
|
|
|
40
42
|
export * from './api';
|
|
41
43
|
export * from './types';
|
|
@@ -347,10 +349,18 @@ type AbyssToolsCoreSDK = {
|
|
|
347
349
|
getScan: typeof probeScanApi.getScan;
|
|
348
350
|
/** `GET /scan` — paginated history/search. */
|
|
349
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
|
+
};
|
|
350
356
|
webhook: {
|
|
351
357
|
create: typeof probeWebhookApi.createProbeWebhook;
|
|
352
358
|
list: typeof probeWebhookApi.listProbeWebhook;
|
|
353
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;
|
|
354
364
|
};
|
|
355
365
|
/**
|
|
356
366
|
* Application/API-key-auth counterpart (Phase 3a) — for inter-service
|
|
@@ -371,10 +381,18 @@ type AbyssToolsCoreSDK = {
|
|
|
371
381
|
getScan: typeof probeScanApplicationApi.getScanApplication;
|
|
372
382
|
/** `GET /application/:applicationId/scan` — paginated history/search. */
|
|
373
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
|
+
};
|
|
374
388
|
webhook: {
|
|
375
389
|
create: typeof probeWebhookApplicationApi.createProbeWebhookApplication;
|
|
376
390
|
list: typeof probeWebhookApplicationApi.listProbeWebhookApplication;
|
|
377
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;
|
|
378
396
|
};
|
|
379
397
|
};
|
|
380
398
|
};
|
|
@@ -775,10 +793,15 @@ export class AbyssToolsCore {
|
|
|
775
793
|
scanAsync: probeScanApi.scanAsync,
|
|
776
794
|
getScan: probeScanApi.getScan,
|
|
777
795
|
listScans: probeScanApi.listScans,
|
|
796
|
+
usage: {
|
|
797
|
+
get: probeUsageApi.getProbeUsage,
|
|
798
|
+
},
|
|
778
799
|
webhook: {
|
|
779
800
|
create: probeWebhookApi.createProbeWebhook,
|
|
780
801
|
list: probeWebhookApi.listProbeWebhook,
|
|
781
802
|
delete: probeWebhookApi.deleteProbeWebhook,
|
|
803
|
+
update: probeWebhookApi.updateProbeWebhook,
|
|
804
|
+
listDeliveries: probeWebhookApi.listProbeWebhookDeliveries,
|
|
782
805
|
},
|
|
783
806
|
application: {
|
|
784
807
|
scan: probeScanApplicationApi.scanApplication,
|
|
@@ -786,10 +809,15 @@ export class AbyssToolsCore {
|
|
|
786
809
|
scanAsync: probeScanApplicationApi.scanAsyncApplication,
|
|
787
810
|
getScan: probeScanApplicationApi.getScanApplication,
|
|
788
811
|
listScans: probeScanApplicationApi.listScansApplication,
|
|
812
|
+
usage: {
|
|
813
|
+
get: probeUsageApplicationApi.getProbeUsageApplication,
|
|
814
|
+
},
|
|
789
815
|
webhook: {
|
|
790
816
|
create: probeWebhookApplicationApi.createProbeWebhookApplication,
|
|
791
817
|
list: probeWebhookApplicationApi.listProbeWebhookApplication,
|
|
792
818
|
delete: probeWebhookApplicationApi.deleteProbeWebhookApplication,
|
|
819
|
+
update: probeWebhookApplicationApi.updateProbeWebhookApplication,
|
|
820
|
+
listDeliveries: probeWebhookApplicationApi.listProbeWebhookDeliveriesApplication,
|
|
793
821
|
},
|
|
794
822
|
},
|
|
795
823
|
},
|
|
@@ -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
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Mirrors apps/api/src/api/controllers/probe-webhook.controller.ts's
|
|
2
|
-
// ScopeQuery/CreateBody and probe-webhook.validator.ts's Joi
|
|
2
|
+
// ScopeQuery/CreateBody/UpdateBody and probe-webhook.validator.ts's Joi
|
|
3
|
+
// schemas.
|
|
3
4
|
|
|
4
|
-
/** Shared by create/list/delete — personal scope (default) or an organization. */
|
|
5
|
+
/** Shared by create/list/delete/update — personal scope (default) or an organization. */
|
|
5
6
|
export interface IProbeWebhookScopeQuery {
|
|
6
7
|
organizationId?: string;
|
|
7
8
|
}
|
|
@@ -10,3 +11,23 @@ export interface ICreateProbeWebhookBody {
|
|
|
10
11
|
/** HTTPS endpoint the verdict is POSTed to. Required, `https://` only. */
|
|
11
12
|
callbackUrl: string;
|
|
12
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
|
+
}
|
|
@@ -12,6 +12,13 @@ export interface IScanSyncData {
|
|
|
12
12
|
scanId: string;
|
|
13
13
|
verdict: ProbeScanVerdict;
|
|
14
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;
|
|
15
22
|
}
|
|
16
23
|
export type IScanSyncResponse = IResponse<IScanSyncData>;
|
|
17
24
|
|
|
@@ -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>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { IResponse } from '../type-message/response';
|
|
2
|
-
import {
|
|
2
|
+
import { BasePaginate } from '../type-message/base-paginate';
|
|
3
|
+
import { IProbeWebhook, IProbeWebhookCreated, IProbeWebhookDelivery } from '../../models';
|
|
3
4
|
|
|
4
5
|
// Mirrors apps/api/src/api/controllers/probe-webhook.controller.ts's local
|
|
5
6
|
// response shapes EXACTLY.
|
|
6
7
|
|
|
7
|
-
/** `POST /webhook` — HTTP 201.
|
|
8
|
+
/** `POST /webhook` — HTTP 201. `secret` is re-displayable (WS5-7) — also returned by GET/PATCH, not just here. */
|
|
8
9
|
export type ICreateProbeWebhookResponse = IResponse<IProbeWebhookCreated>;
|
|
9
10
|
|
|
10
|
-
/** `GET /webhook` — HTTP 200. A flat scope-filtered list, NOT paginated. */
|
|
11
|
+
/** `GET /webhook` — HTTP 200. A flat scope-filtered list, NOT paginated. `secret` included per row (WS5-7). */
|
|
11
12
|
export interface IListProbeWebhookData {
|
|
12
13
|
webhooks: IProbeWebhook[];
|
|
13
14
|
}
|
|
@@ -15,3 +16,9 @@ export type IListProbeWebhookResponse = IResponse<IListProbeWebhookData>;
|
|
|
15
16
|
|
|
16
17
|
/** `DELETE /webhook/:webhookId` — HTTP 200. */
|
|
17
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>>;
|
|
@@ -8,9 +8,13 @@ import { ProbeScanMode, ProbeScanStatus, ProbeScanVerdict } from '../../enum';
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* `GET /scan/:scanId` shape (poll the queued -> scanning -> done/error
|
|
11
|
-
* progression).
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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.
|
|
14
18
|
*/
|
|
15
19
|
export interface IProbeScanDetail {
|
|
16
20
|
scanId: string;
|
|
@@ -21,14 +25,27 @@ export interface IProbeScanDetail {
|
|
|
21
25
|
viruses: string[] | null;
|
|
22
26
|
/** Free-form caller reference echoed back verbatim (see IProbeScanHistoryItem#context). */
|
|
23
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;
|
|
24
43
|
}
|
|
25
44
|
|
|
26
45
|
/**
|
|
27
|
-
* One row of `GET /scan`'s paginated history/search list.
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* callbackUrl) — a caller already knows their own scope from the request
|
|
31
|
-
* they made.
|
|
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.
|
|
32
49
|
*/
|
|
33
50
|
export interface IProbeScanHistoryItem {
|
|
34
51
|
scanId: string;
|
|
@@ -44,5 +61,7 @@ export interface IProbeScanHistoryItem {
|
|
|
44
61
|
startedAt: Date;
|
|
45
62
|
/** Set once the engine call returns. null while status is not DONE. */
|
|
46
63
|
finishedAt: Date | null;
|
|
64
|
+
/** See {@link IProbeScanDetail#costUnits}. */
|
|
65
|
+
costUnits: number | null;
|
|
47
66
|
createdAt: Date;
|
|
48
67
|
}
|
|
@@ -23,4 +23,51 @@ export interface IProbeWebhookDeliveryPayload {
|
|
|
23
23
|
verdict: ProbeScanVerdict;
|
|
24
24
|
/** [] when clean. */
|
|
25
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;
|
|
26
73
|
}
|
|
@@ -1,25 +1,39 @@
|
|
|
1
1
|
// Mirrors apps/api/src/api/controllers/probe-webhook.controller.ts's local
|
|
2
2
|
// WebhookResponseData / CreateWebhookResponseData. Public shape of a
|
|
3
|
-
// registered `probe_webhooks` row — never
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
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.
|
|
7
16
|
|
|
8
17
|
export interface IProbeWebhook {
|
|
9
18
|
id: string;
|
|
10
19
|
/** HTTPS endpoint the verdict is POSTed to. */
|
|
11
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;
|
|
12
27
|
/** Disabled webhooks are skipped by dispatch (soft-off, not deleted). */
|
|
13
28
|
active: boolean;
|
|
14
29
|
createdAt: Date;
|
|
15
30
|
}
|
|
16
31
|
|
|
17
32
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
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.
|
|
22
38
|
*/
|
|
23
|
-
export
|
|
24
|
-
secret: string;
|
|
25
|
-
}
|
|
39
|
+
export type IProbeWebhookCreated = IProbeWebhook;
|