@abyss-project/probe 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.d.ts +2 -1
- package/dist/api/index.js +2 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/probe-delivery-subscription.api.d.ts +11 -0
- package/dist/api/probe-delivery-subscription.api.js +42 -0
- package/dist/api/probe-delivery-subscription.api.js.map +1 -0
- package/dist/api/probe-delivery-subscription.application.api.d.ts +11 -0
- package/dist/api/probe-delivery-subscription.application.api.js +38 -0
- package/dist/api/probe-delivery-subscription.application.api.js.map +1 -0
- package/dist/api/probe-webhook.application.api.d.ts +1 -1
- package/dist/api/probe-webhook.application.api.js.map +1 -1
- package/dist/index.d.ts +29 -7
- package/dist/index.js +29 -7
- package/dist/index.js.map +1 -1
- package/dist/types/enum/api-error.enum.d.ts +2 -1
- package/dist/types/enum/api-error.enum.js +1 -0
- package/dist/types/enum/api-error.enum.js.map +1 -1
- package/dist/types/enum/probe-scan.enum.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-delivery-subscription.request.d.ts +23 -0
- package/dist/types/interface/api/requests/probe-delivery-subscription.request.js +3 -0
- package/dist/types/interface/api/requests/probe-delivery-subscription.request.js.map +1 -0
- package/dist/types/interface/api/requests/probe-webhook.request.d.ts +1 -4
- 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-delivery-subscription.response.d.ts +10 -0
- package/dist/types/interface/api/responses/probe-delivery-subscription.response.js +3 -0
- package/dist/types/interface/api/responses/probe-delivery-subscription.response.js.map +1 -0
- package/dist/types/tests/probe.dto.test.js +22 -0
- package/dist/types/tests/probe.dto.test.js.map +1 -1
- package/dist/utils/probe-webhook-signature.utils.js.map +1 -1
- package/package.json +10 -1
- package/src/api/index.ts +7 -6
- package/src/api/probe-delivery-subscription.api.ts +183 -0
- package/src/api/probe-delivery-subscription.application.api.ts +186 -0
- package/src/api/probe-webhook.application.api.ts +128 -141
- package/src/index.ts +262 -205
- package/src/types/enum/api-error.enum.ts +35 -33
- package/src/types/enum/probe-scan.enum.ts +45 -44
- package/src/types/interface/api/requests/index.ts +4 -3
- package/src/types/interface/api/requests/probe-delivery-subscription.request.ts +42 -0
- package/src/types/interface/api/requests/probe-webhook.request.ts +31 -33
- package/src/types/interface/api/responses/index.ts +4 -3
- package/src/types/interface/api/responses/probe-delivery-subscription.response.ts +27 -0
- package/src/types/interface/models/probe-webhook-delivery.dto.ts +70 -73
- package/src/types/tests/probe.dto.test.ts +192 -156
- package/src/utils/probe-webhook-signature.utils.ts +57 -56
- package/dist/api/probe-webhook.api.d.ts +0 -6
- package/dist/api/probe-webhook.api.js +0 -41
- package/dist/api/probe-webhook.api.js.map +0 -1
- package/dist/api/probe-webhook.api.test.d.ts +0 -1
- package/dist/api/probe-webhook.api.test.js +0 -43
- package/dist/api/probe-webhook.api.test.js.map +0 -1
- package/src/api/probe-webhook.api.test.ts +0 -17
- package/src/api/probe-webhook.api.ts +0 -119
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// ──────────────────────────────────────────────
|
|
2
|
+
// AbyssProbe delivery-subscription API for a personal or organization caller: the endpoints that
|
|
3
|
+
// receive the verdict of the caller's scans (`PROBE_SCAN_COMPLETED`). The subscriptions live in
|
|
4
|
+
// Flow; AbyssProbe checks the caller's access to the scope (self, or a member of the organization
|
|
5
|
+
// named by `organizationId`) and calls Flow for it. Mirrors
|
|
6
|
+
// apps/api/src/api/controllers/probe-delivery-subscription.controller.ts.
|
|
7
|
+
//
|
|
8
|
+
// See probe-delivery-subscription.application.api.ts for the application counterpart.
|
|
9
|
+
// ──────────────────────────────────────────────
|
|
10
|
+
|
|
11
|
+
import { AbyssProbeCore } from '..';
|
|
12
|
+
import type {
|
|
13
|
+
ICreateProbeDeliverySubscriptionBody,
|
|
14
|
+
ICreateProbeDeliverySubscriptionResponse,
|
|
15
|
+
IDeleteProbeDeliverySubscriptionResponse,
|
|
16
|
+
IGetProbeDeliveryResponse,
|
|
17
|
+
IGetProbeDeliverySubscriptionResponse,
|
|
18
|
+
IPaginateProbeDeliveryQuery,
|
|
19
|
+
IPaginateProbeDeliveryResponse,
|
|
20
|
+
IPaginateProbeDeliverySubscriptionQuery,
|
|
21
|
+
IPaginateProbeDeliverySubscriptionResponse,
|
|
22
|
+
IProbeDeliverySubscriptionScopeQuery,
|
|
23
|
+
IReplayProbeDeliveryResponse,
|
|
24
|
+
IResetSecretProbeDeliverySubscriptionResponse,
|
|
25
|
+
IUpdateProbeDeliverySubscriptionBody,
|
|
26
|
+
IUpdateProbeDeliverySubscriptionResponse,
|
|
27
|
+
} from '../types';
|
|
28
|
+
|
|
29
|
+
const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
|
|
30
|
+
|
|
31
|
+
function authHeader(apiKey?: string): Record<string, string> {
|
|
32
|
+
return apiKey ? { [DEFAULT_API_KEY_HEADER]: apiKey } : {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Renames `organizationId` to the wire's `organization_id` (see probe-scan.api.ts). */
|
|
36
|
+
function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
|
|
37
|
+
const out: Record<string, unknown> = {};
|
|
38
|
+
for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
|
|
39
|
+
if (value === undefined || value === null) continue;
|
|
40
|
+
out[key === 'organizationId' ? 'organization_id' : key] = value;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const SUBSCRIPTIONS_PATH = 'delivery-subscription';
|
|
46
|
+
|
|
47
|
+
/** `GET /delivery-subscription` — the subscriptions of the scope. */
|
|
48
|
+
export const paginateProbeDeliverySubscription = async (
|
|
49
|
+
query: IPaginateProbeDeliverySubscriptionQuery = {},
|
|
50
|
+
apiKey?: string,
|
|
51
|
+
): Promise<IPaginateProbeDeliverySubscriptionResponse> =>
|
|
52
|
+
(
|
|
53
|
+
await AbyssProbeCore.axios.get<IPaginateProbeDeliverySubscriptionResponse>(SUBSCRIPTIONS_PATH, {
|
|
54
|
+
params: serializeProbeQuery(query),
|
|
55
|
+
headers: authHeader(apiKey),
|
|
56
|
+
})
|
|
57
|
+
).data;
|
|
58
|
+
|
|
59
|
+
/** `GET /delivery-subscription/:deliverySubscriptionId` — never carries the secret. */
|
|
60
|
+
export const getProbeDeliverySubscription = async (
|
|
61
|
+
deliverySubscriptionId: string,
|
|
62
|
+
scope: IProbeDeliverySubscriptionScopeQuery = {},
|
|
63
|
+
apiKey?: string,
|
|
64
|
+
): Promise<IGetProbeDeliverySubscriptionResponse> =>
|
|
65
|
+
(
|
|
66
|
+
await AbyssProbeCore.axios.get<IGetProbeDeliverySubscriptionResponse>(
|
|
67
|
+
`${SUBSCRIPTIONS_PATH}/${deliverySubscriptionId}`,
|
|
68
|
+
{ params: serializeProbeQuery(scope), headers: authHeader(apiKey) },
|
|
69
|
+
)
|
|
70
|
+
).data;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* `POST /delivery-subscription` — HTTP 201. The response's `secret` (signing secret of the
|
|
74
|
+
* deliveries) is returned ONLY here and by {@link resetSecretProbeDeliverySubscription}.
|
|
75
|
+
*/
|
|
76
|
+
export const createProbeDeliverySubscription = async (
|
|
77
|
+
body: ICreateProbeDeliverySubscriptionBody,
|
|
78
|
+
scope: IProbeDeliverySubscriptionScopeQuery = {},
|
|
79
|
+
apiKey?: string,
|
|
80
|
+
): Promise<ICreateProbeDeliverySubscriptionResponse> =>
|
|
81
|
+
(
|
|
82
|
+
await AbyssProbeCore.axios.post<ICreateProbeDeliverySubscriptionResponse>(
|
|
83
|
+
SUBSCRIPTIONS_PATH,
|
|
84
|
+
body,
|
|
85
|
+
{ params: serializeProbeQuery(scope), headers: authHeader(apiKey) },
|
|
86
|
+
)
|
|
87
|
+
).data;
|
|
88
|
+
|
|
89
|
+
/** `PUT /delivery-subscription/:deliverySubscriptionId` — at least one field. */
|
|
90
|
+
export const updateProbeDeliverySubscription = async (
|
|
91
|
+
deliverySubscriptionId: string,
|
|
92
|
+
body: IUpdateProbeDeliverySubscriptionBody,
|
|
93
|
+
scope: IProbeDeliverySubscriptionScopeQuery = {},
|
|
94
|
+
apiKey?: string,
|
|
95
|
+
): Promise<IUpdateProbeDeliverySubscriptionResponse> =>
|
|
96
|
+
(
|
|
97
|
+
await AbyssProbeCore.axios.put<IUpdateProbeDeliverySubscriptionResponse>(
|
|
98
|
+
`${SUBSCRIPTIONS_PATH}/${deliverySubscriptionId}`,
|
|
99
|
+
body,
|
|
100
|
+
{ params: serializeProbeQuery(scope), headers: authHeader(apiKey) },
|
|
101
|
+
)
|
|
102
|
+
).data;
|
|
103
|
+
|
|
104
|
+
/** `DELETE /delivery-subscription/:deliverySubscriptionId`. */
|
|
105
|
+
export const deleteProbeDeliverySubscription = async (
|
|
106
|
+
deliverySubscriptionId: string,
|
|
107
|
+
scope: IProbeDeliverySubscriptionScopeQuery = {},
|
|
108
|
+
apiKey?: string,
|
|
109
|
+
): Promise<IDeleteProbeDeliverySubscriptionResponse> =>
|
|
110
|
+
(
|
|
111
|
+
await AbyssProbeCore.axios.delete<IDeleteProbeDeliverySubscriptionResponse>(
|
|
112
|
+
`${SUBSCRIPTIONS_PATH}/${deliverySubscriptionId}`,
|
|
113
|
+
{ params: serializeProbeQuery(scope), headers: authHeader(apiKey) },
|
|
114
|
+
)
|
|
115
|
+
).data;
|
|
116
|
+
|
|
117
|
+
/** `POST /delivery-subscription/:deliverySubscriptionId/reset-secret` — the new secret, once. */
|
|
118
|
+
export const resetSecretProbeDeliverySubscription = async (
|
|
119
|
+
deliverySubscriptionId: string,
|
|
120
|
+
scope: IProbeDeliverySubscriptionScopeQuery = {},
|
|
121
|
+
apiKey?: string,
|
|
122
|
+
): Promise<IResetSecretProbeDeliverySubscriptionResponse> =>
|
|
123
|
+
(
|
|
124
|
+
await AbyssProbeCore.axios.post<IResetSecretProbeDeliverySubscriptionResponse>(
|
|
125
|
+
`${SUBSCRIPTIONS_PATH}/${deliverySubscriptionId}/reset-secret`,
|
|
126
|
+
undefined,
|
|
127
|
+
{ params: serializeProbeQuery(scope), headers: authHeader(apiKey) },
|
|
128
|
+
)
|
|
129
|
+
).data;
|
|
130
|
+
|
|
131
|
+
/** `GET /delivery-subscription/delivery` — the deliveries of every subscription of the scope. */
|
|
132
|
+
export const paginateProbeScopeDelivery = async (
|
|
133
|
+
query: IPaginateProbeDeliveryQuery = {},
|
|
134
|
+
apiKey?: string,
|
|
135
|
+
): Promise<IPaginateProbeDeliveryResponse> =>
|
|
136
|
+
(
|
|
137
|
+
await AbyssProbeCore.axios.get<IPaginateProbeDeliveryResponse>(
|
|
138
|
+
`${SUBSCRIPTIONS_PATH}/delivery`,
|
|
139
|
+
{ params: serializeProbeQuery(query), headers: authHeader(apiKey) },
|
|
140
|
+
)
|
|
141
|
+
).data;
|
|
142
|
+
|
|
143
|
+
/** `GET /delivery-subscription/:deliverySubscriptionId/delivery`. */
|
|
144
|
+
export const paginateProbeDelivery = async (
|
|
145
|
+
deliverySubscriptionId: string,
|
|
146
|
+
query: IPaginateProbeDeliveryQuery = {},
|
|
147
|
+
apiKey?: string,
|
|
148
|
+
): Promise<IPaginateProbeDeliveryResponse> =>
|
|
149
|
+
(
|
|
150
|
+
await AbyssProbeCore.axios.get<IPaginateProbeDeliveryResponse>(
|
|
151
|
+
`${SUBSCRIPTIONS_PATH}/${deliverySubscriptionId}/delivery`,
|
|
152
|
+
{ params: serializeProbeQuery(query), headers: authHeader(apiKey) },
|
|
153
|
+
)
|
|
154
|
+
).data;
|
|
155
|
+
|
|
156
|
+
/** `GET /delivery-subscription/:deliverySubscriptionId/delivery/:deliveryId`. */
|
|
157
|
+
export const getProbeDelivery = async (
|
|
158
|
+
deliverySubscriptionId: string,
|
|
159
|
+
deliveryId: string,
|
|
160
|
+
scope: IProbeDeliverySubscriptionScopeQuery = {},
|
|
161
|
+
apiKey?: string,
|
|
162
|
+
): Promise<IGetProbeDeliveryResponse> =>
|
|
163
|
+
(
|
|
164
|
+
await AbyssProbeCore.axios.get<IGetProbeDeliveryResponse>(
|
|
165
|
+
`${SUBSCRIPTIONS_PATH}/${deliverySubscriptionId}/delivery/${deliveryId}`,
|
|
166
|
+
{ params: serializeProbeQuery(scope), headers: authHeader(apiKey) },
|
|
167
|
+
)
|
|
168
|
+
).data;
|
|
169
|
+
|
|
170
|
+
/** `POST .../delivery/:deliveryId/replay` — only a delivered or failed one (409 otherwise). */
|
|
171
|
+
export const replayProbeDelivery = async (
|
|
172
|
+
deliverySubscriptionId: string,
|
|
173
|
+
deliveryId: string,
|
|
174
|
+
scope: IProbeDeliverySubscriptionScopeQuery = {},
|
|
175
|
+
apiKey?: string,
|
|
176
|
+
): Promise<IReplayProbeDeliveryResponse> =>
|
|
177
|
+
(
|
|
178
|
+
await AbyssProbeCore.axios.post<IReplayProbeDeliveryResponse>(
|
|
179
|
+
`${SUBSCRIPTIONS_PATH}/${deliverySubscriptionId}/delivery/${deliveryId}/replay`,
|
|
180
|
+
undefined,
|
|
181
|
+
{ params: serializeProbeQuery(scope), headers: authHeader(apiKey) },
|
|
182
|
+
)
|
|
183
|
+
).data;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// ──────────────────────────────────────────────
|
|
2
|
+
// AbyssProbe delivery-subscription API for an application caller (project API key, or a project
|
|
3
|
+
// member's session): the endpoints that receive the verdict of the application's scans. The
|
|
4
|
+
// application counterpart of probe-delivery-subscription.api.ts, with `FULL_ACCESS` on the
|
|
5
|
+
// application as the access rule and no scope argument (the scope is the `:applicationId` URL
|
|
6
|
+
// segment). Mirrors
|
|
7
|
+
// apps/api/src/api/controllers/probe-delivery-subscription-application.controller.ts.
|
|
8
|
+
//
|
|
9
|
+
// `authHeaderApplication` sends `API_KEY_APPLICATION_HEADER` instead of the personal header.
|
|
10
|
+
// ──────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
import { AbyssProbeCore, API_KEY_APPLICATION_HEADER } from '..';
|
|
13
|
+
import type {
|
|
14
|
+
ICreateProbeDeliverySubscriptionBody,
|
|
15
|
+
ICreateProbeDeliverySubscriptionResponse,
|
|
16
|
+
IDeleteProbeDeliverySubscriptionResponse,
|
|
17
|
+
IGetProbeDeliveryResponse,
|
|
18
|
+
IGetProbeDeliverySubscriptionResponse,
|
|
19
|
+
IPaginateProbeDeliveryQuery,
|
|
20
|
+
IPaginateProbeDeliveryResponse,
|
|
21
|
+
IPaginateProbeDeliverySubscriptionQuery,
|
|
22
|
+
IPaginateProbeDeliverySubscriptionResponse,
|
|
23
|
+
IReplayProbeDeliveryResponse,
|
|
24
|
+
IResetSecretProbeDeliverySubscriptionResponse,
|
|
25
|
+
IUpdateProbeDeliverySubscriptionBody,
|
|
26
|
+
IUpdateProbeDeliverySubscriptionResponse,
|
|
27
|
+
} from '../types';
|
|
28
|
+
|
|
29
|
+
function authHeaderApplication(applicationApiKey?: string): Record<string, string> {
|
|
30
|
+
return applicationApiKey ? { [API_KEY_APPLICATION_HEADER]: applicationApiKey } : {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Drops undefined/null: no `organizationId` ever travels on an application call. */
|
|
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
|
+
out[key] = value;
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const subscriptionsPath = (applicationId: string): string =>
|
|
44
|
+
`application/${applicationId}/delivery-subscription`;
|
|
45
|
+
|
|
46
|
+
/** `GET /application/:applicationId/delivery-subscription`. */
|
|
47
|
+
export const paginateProbeDeliverySubscriptionApplication = async (
|
|
48
|
+
applicationId: string,
|
|
49
|
+
query: Omit<IPaginateProbeDeliverySubscriptionQuery, 'organizationId'> = {},
|
|
50
|
+
applicationApiKey?: string,
|
|
51
|
+
): Promise<IPaginateProbeDeliverySubscriptionResponse> =>
|
|
52
|
+
(
|
|
53
|
+
await AbyssProbeCore.axios.get<IPaginateProbeDeliverySubscriptionResponse>(
|
|
54
|
+
subscriptionsPath(applicationId),
|
|
55
|
+
{ params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
|
|
56
|
+
)
|
|
57
|
+
).data;
|
|
58
|
+
|
|
59
|
+
/** `GET /application/:applicationId/delivery-subscription/:deliverySubscriptionId` — no secret. */
|
|
60
|
+
export const getProbeDeliverySubscriptionApplication = async (
|
|
61
|
+
applicationId: string,
|
|
62
|
+
deliverySubscriptionId: string,
|
|
63
|
+
applicationApiKey?: string,
|
|
64
|
+
): Promise<IGetProbeDeliverySubscriptionResponse> =>
|
|
65
|
+
(
|
|
66
|
+
await AbyssProbeCore.axios.get<IGetProbeDeliverySubscriptionResponse>(
|
|
67
|
+
`${subscriptionsPath(applicationId)}/${deliverySubscriptionId}`,
|
|
68
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
69
|
+
)
|
|
70
|
+
).data;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* `POST /application/:applicationId/delivery-subscription` — HTTP 201, the `secret` once. With a
|
|
74
|
+
* project member's session the subscription is theirs; with an API key it is recorded under the
|
|
75
|
+
* project's creator.
|
|
76
|
+
*/
|
|
77
|
+
export const createProbeDeliverySubscriptionApplication = async (
|
|
78
|
+
applicationId: string,
|
|
79
|
+
body: ICreateProbeDeliverySubscriptionBody,
|
|
80
|
+
applicationApiKey?: string,
|
|
81
|
+
): Promise<ICreateProbeDeliverySubscriptionResponse> =>
|
|
82
|
+
(
|
|
83
|
+
await AbyssProbeCore.axios.post<ICreateProbeDeliverySubscriptionResponse>(
|
|
84
|
+
subscriptionsPath(applicationId),
|
|
85
|
+
body,
|
|
86
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
87
|
+
)
|
|
88
|
+
).data;
|
|
89
|
+
|
|
90
|
+
/** `PUT /application/:applicationId/delivery-subscription/:deliverySubscriptionId`. */
|
|
91
|
+
export const updateProbeDeliverySubscriptionApplication = async (
|
|
92
|
+
applicationId: string,
|
|
93
|
+
deliverySubscriptionId: string,
|
|
94
|
+
body: IUpdateProbeDeliverySubscriptionBody,
|
|
95
|
+
applicationApiKey?: string,
|
|
96
|
+
): Promise<IUpdateProbeDeliverySubscriptionResponse> =>
|
|
97
|
+
(
|
|
98
|
+
await AbyssProbeCore.axios.put<IUpdateProbeDeliverySubscriptionResponse>(
|
|
99
|
+
`${subscriptionsPath(applicationId)}/${deliverySubscriptionId}`,
|
|
100
|
+
body,
|
|
101
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
102
|
+
)
|
|
103
|
+
).data;
|
|
104
|
+
|
|
105
|
+
/** `DELETE /application/:applicationId/delivery-subscription/:deliverySubscriptionId`. */
|
|
106
|
+
export const deleteProbeDeliverySubscriptionApplication = async (
|
|
107
|
+
applicationId: string,
|
|
108
|
+
deliverySubscriptionId: string,
|
|
109
|
+
applicationApiKey?: string,
|
|
110
|
+
): Promise<IDeleteProbeDeliverySubscriptionResponse> =>
|
|
111
|
+
(
|
|
112
|
+
await AbyssProbeCore.axios.delete<IDeleteProbeDeliverySubscriptionResponse>(
|
|
113
|
+
`${subscriptionsPath(applicationId)}/${deliverySubscriptionId}`,
|
|
114
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
115
|
+
)
|
|
116
|
+
).data;
|
|
117
|
+
|
|
118
|
+
/** `POST .../delivery-subscription/:deliverySubscriptionId/reset-secret` — the new secret, once. */
|
|
119
|
+
export const resetSecretProbeDeliverySubscriptionApplication = async (
|
|
120
|
+
applicationId: string,
|
|
121
|
+
deliverySubscriptionId: string,
|
|
122
|
+
applicationApiKey?: string,
|
|
123
|
+
): Promise<IResetSecretProbeDeliverySubscriptionResponse> =>
|
|
124
|
+
(
|
|
125
|
+
await AbyssProbeCore.axios.post<IResetSecretProbeDeliverySubscriptionResponse>(
|
|
126
|
+
`${subscriptionsPath(applicationId)}/${deliverySubscriptionId}/reset-secret`,
|
|
127
|
+
undefined,
|
|
128
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
129
|
+
)
|
|
130
|
+
).data;
|
|
131
|
+
|
|
132
|
+
/** `GET /application/:applicationId/delivery-subscription/delivery` — every subscription of the application. */
|
|
133
|
+
export const paginateProbeScopeDeliveryApplication = async (
|
|
134
|
+
applicationId: string,
|
|
135
|
+
query: Omit<IPaginateProbeDeliveryQuery, 'organizationId'> = {},
|
|
136
|
+
applicationApiKey?: string,
|
|
137
|
+
): Promise<IPaginateProbeDeliveryResponse> =>
|
|
138
|
+
(
|
|
139
|
+
await AbyssProbeCore.axios.get<IPaginateProbeDeliveryResponse>(
|
|
140
|
+
`${subscriptionsPath(applicationId)}/delivery`,
|
|
141
|
+
{ params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
|
|
142
|
+
)
|
|
143
|
+
).data;
|
|
144
|
+
|
|
145
|
+
/** `GET .../delivery-subscription/:deliverySubscriptionId/delivery`. */
|
|
146
|
+
export const paginateProbeDeliveryApplication = async (
|
|
147
|
+
applicationId: string,
|
|
148
|
+
deliverySubscriptionId: string,
|
|
149
|
+
query: Omit<IPaginateProbeDeliveryQuery, 'organizationId'> = {},
|
|
150
|
+
applicationApiKey?: string,
|
|
151
|
+
): Promise<IPaginateProbeDeliveryResponse> =>
|
|
152
|
+
(
|
|
153
|
+
await AbyssProbeCore.axios.get<IPaginateProbeDeliveryResponse>(
|
|
154
|
+
`${subscriptionsPath(applicationId)}/${deliverySubscriptionId}/delivery`,
|
|
155
|
+
{ params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
|
|
156
|
+
)
|
|
157
|
+
).data;
|
|
158
|
+
|
|
159
|
+
/** `GET .../delivery-subscription/:deliverySubscriptionId/delivery/:deliveryId`. */
|
|
160
|
+
export const getProbeDeliveryApplication = async (
|
|
161
|
+
applicationId: string,
|
|
162
|
+
deliverySubscriptionId: string,
|
|
163
|
+
deliveryId: string,
|
|
164
|
+
applicationApiKey?: string,
|
|
165
|
+
): Promise<IGetProbeDeliveryResponse> =>
|
|
166
|
+
(
|
|
167
|
+
await AbyssProbeCore.axios.get<IGetProbeDeliveryResponse>(
|
|
168
|
+
`${subscriptionsPath(applicationId)}/${deliverySubscriptionId}/delivery/${deliveryId}`,
|
|
169
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
170
|
+
)
|
|
171
|
+
).data;
|
|
172
|
+
|
|
173
|
+
/** `POST .../delivery/:deliveryId/replay` — only a delivered or failed one (409 otherwise). */
|
|
174
|
+
export const replayProbeDeliveryApplication = async (
|
|
175
|
+
applicationId: string,
|
|
176
|
+
deliverySubscriptionId: string,
|
|
177
|
+
deliveryId: string,
|
|
178
|
+
applicationApiKey?: string,
|
|
179
|
+
): Promise<IReplayProbeDeliveryResponse> =>
|
|
180
|
+
(
|
|
181
|
+
await AbyssProbeCore.axios.post<IReplayProbeDeliveryResponse>(
|
|
182
|
+
`${subscriptionsPath(applicationId)}/${deliverySubscriptionId}/delivery/${deliveryId}/replay`,
|
|
183
|
+
undefined,
|
|
184
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
185
|
+
)
|
|
186
|
+
).data;
|
|
@@ -1,141 +1,128 @@
|
|
|
1
|
-
// ──────────────────────────────────────────────
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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 AbyssProbeCore.axios.get<IListProbeWebhookDeliveriesResponse>(
|
|
138
|
-
`application/${applicationId}/webhook/${webhookId}/deliveries`,
|
|
139
|
-
{ params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
|
|
140
|
-
)
|
|
141
|
-
).data;
|
|
1
|
+
// ──────────────────────────────────────────────
|
|
2
|
+
// INTERNAL (P5 #792): AbyssProbe application webhooks, CRUD over the `probe_webhooks` rows owned
|
|
3
|
+
// by a calling application (create / list / delete / update, + paginated delivery history).
|
|
4
|
+
// They serve AbyssStorage's antivirus subscription until its client subscriptions move to Flow
|
|
5
|
+
// (L2). A client's own subscriptions to the verdict of its scans are the Flow delivery
|
|
6
|
+
// subscriptions (probe-delivery-subscription.application.api.ts). Mirrors
|
|
7
|
+
// apps/api/src/api/controllers/probe-webhook-application.controller.ts EXACTLY.
|
|
8
|
+
//
|
|
9
|
+
// The scope is entirely the `:applicationId` URL segment, resolved server-side by
|
|
10
|
+
// ProbeApplicationMiddleware; there is nothing to select between. `authHeaderApplication` sends
|
|
11
|
+
// `API_KEY_APPLICATION_HEADER` (`abyss-api-key-application`, imported from this package's root).
|
|
12
|
+
// ──────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
import { AbyssProbeCore, API_KEY_APPLICATION_HEADER } from '..';
|
|
15
|
+
import type {
|
|
16
|
+
ICreateProbeWebhookBody,
|
|
17
|
+
IUpdateProbeWebhookBody,
|
|
18
|
+
IListProbeWebhookDeliveriesQuery,
|
|
19
|
+
ICreateProbeWebhookResponse,
|
|
20
|
+
IListProbeWebhookResponse,
|
|
21
|
+
IDeleteProbeWebhookResponse,
|
|
22
|
+
IUpdateProbeWebhookResponse,
|
|
23
|
+
IListProbeWebhookDeliveriesResponse,
|
|
24
|
+
} from '../types';
|
|
25
|
+
|
|
26
|
+
function authHeaderApplication(applicationApiKey?: string): Record<string, string> {
|
|
27
|
+
return applicationApiKey ? { [API_KEY_APPLICATION_HEADER]: applicationApiKey } : {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** 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. */
|
|
31
|
+
function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
|
|
32
|
+
const out: Record<string, unknown> = {};
|
|
33
|
+
for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
|
|
34
|
+
if (value === undefined || value === null) continue;
|
|
35
|
+
out[key] = value instanceof Date ? value.toISOString() : value;
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* `POST /application/:applicationId/webhook` — register a callbackUrl owned
|
|
42
|
+
* by the calling application. The response's `secret` field (HMAC signing
|
|
43
|
+
* secret) is returned ONLY here — store it immediately, it cannot be
|
|
44
|
+
* re-revealed later.
|
|
45
|
+
*/
|
|
46
|
+
export const createProbeWebhookApplication = async (
|
|
47
|
+
applicationId: string,
|
|
48
|
+
body: ICreateProbeWebhookBody,
|
|
49
|
+
applicationApiKey?: string,
|
|
50
|
+
): Promise<ICreateProbeWebhookResponse> =>
|
|
51
|
+
(
|
|
52
|
+
await AbyssProbeCore.axios.post<ICreateProbeWebhookResponse>(
|
|
53
|
+
`application/${applicationId}/webhook`,
|
|
54
|
+
body,
|
|
55
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
56
|
+
)
|
|
57
|
+
).data;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* `GET /application/:applicationId/webhook` — flat list of the calling
|
|
61
|
+
* application's own webhooks (not paginated — bounded by
|
|
62
|
+
* WEBHOOK_MAX_PER_SCOPE server-side).
|
|
63
|
+
*/
|
|
64
|
+
export const listProbeWebhookApplication = async (
|
|
65
|
+
applicationId: string,
|
|
66
|
+
applicationApiKey?: string,
|
|
67
|
+
): Promise<IListProbeWebhookResponse> =>
|
|
68
|
+
(
|
|
69
|
+
await AbyssProbeCore.axios.get<IListProbeWebhookResponse>(
|
|
70
|
+
`application/${applicationId}/webhook`,
|
|
71
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
72
|
+
)
|
|
73
|
+
).data;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* `DELETE /application/:applicationId/webhook/:webhookId` — cross-tenant
|
|
77
|
+
* guarded server-side by a direct `applicationId` comparison (404, never
|
|
78
|
+
* 403).
|
|
79
|
+
*/
|
|
80
|
+
export const deleteProbeWebhookApplication = async (
|
|
81
|
+
applicationId: string,
|
|
82
|
+
webhookId: string,
|
|
83
|
+
applicationApiKey?: string,
|
|
84
|
+
): Promise<IDeleteProbeWebhookResponse> =>
|
|
85
|
+
(
|
|
86
|
+
await AbyssProbeCore.axios.delete<IDeleteProbeWebhookResponse>(
|
|
87
|
+
`application/${applicationId}/webhook/${webhookId}`,
|
|
88
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
89
|
+
)
|
|
90
|
+
).data;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* `PATCH /application/:applicationId/webhook/:webhookId` (WS5-5) — edit
|
|
94
|
+
* `callbackUrl` and/or `active` on a webhook owned by the calling
|
|
95
|
+
* application. Cross-tenant guarded server-side (404, never 403). The
|
|
96
|
+
* response includes `secret` — re-displayable now, see {@link IProbeWebhook}.
|
|
97
|
+
*/
|
|
98
|
+
export const updateProbeWebhookApplication = async (
|
|
99
|
+
applicationId: string,
|
|
100
|
+
webhookId: string,
|
|
101
|
+
body: IUpdateProbeWebhookBody,
|
|
102
|
+
applicationApiKey?: string,
|
|
103
|
+
): Promise<IUpdateProbeWebhookResponse> =>
|
|
104
|
+
(
|
|
105
|
+
await AbyssProbeCore.axios.patch<IUpdateProbeWebhookResponse>(
|
|
106
|
+
`application/${applicationId}/webhook/${webhookId}`,
|
|
107
|
+
body,
|
|
108
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
109
|
+
)
|
|
110
|
+
).data;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* `GET /application/:applicationId/webhook/:webhookId/deliveries` (WS5-6) —
|
|
114
|
+
* paginated delivery-attempt history for one webhook owned by the calling
|
|
115
|
+
* application. Cross-tenant guarded server-side (404, never 403).
|
|
116
|
+
*/
|
|
117
|
+
export const listProbeWebhookDeliveriesApplication = async (
|
|
118
|
+
applicationId: string,
|
|
119
|
+
webhookId: string,
|
|
120
|
+
query: IListProbeWebhookDeliveriesQuery = {},
|
|
121
|
+
applicationApiKey?: string,
|
|
122
|
+
): Promise<IListProbeWebhookDeliveriesResponse> =>
|
|
123
|
+
(
|
|
124
|
+
await AbyssProbeCore.axios.get<IListProbeWebhookDeliveriesResponse>(
|
|
125
|
+
`application/${applicationId}/webhook/${webhookId}/deliveries`,
|
|
126
|
+
{ params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
|
|
127
|
+
)
|
|
128
|
+
).data;
|