@secureport/sdk 0.5.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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/client.d.ts +135 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +191 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/errors.d.ts +80 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +118 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/index.d.ts +31 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +10 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/pagination.d.ts +27 -0
  16. package/dist/pagination.d.ts.map +1 -0
  17. package/dist/pagination.js +19 -0
  18. package/dist/pagination.js.map +1 -0
  19. package/dist/resources/branding.d.ts +49 -0
  20. package/dist/resources/branding.d.ts.map +1 -0
  21. package/dist/resources/branding.js +38 -0
  22. package/dist/resources/branding.js.map +1 -0
  23. package/dist/resources/issues.d.ts +248 -0
  24. package/dist/resources/issues.d.ts.map +1 -0
  25. package/dist/resources/issues.js +100 -0
  26. package/dist/resources/issues.js.map +1 -0
  27. package/dist/resources/reports.d.ts +83 -0
  28. package/dist/resources/reports.d.ts.map +1 -0
  29. package/dist/resources/reports.js +50 -0
  30. package/dist/resources/reports.js.map +1 -0
  31. package/dist/resources/runs.d.ts +474 -0
  32. package/dist/resources/runs.d.ts.map +1 -0
  33. package/dist/resources/runs.js +281 -0
  34. package/dist/resources/runs.js.map +1 -0
  35. package/dist/resources/suppression-rules.d.ts +43 -0
  36. package/dist/resources/suppression-rules.d.ts.map +1 -0
  37. package/dist/resources/suppression-rules.js +33 -0
  38. package/dist/resources/suppression-rules.js.map +1 -0
  39. package/dist/resources/targets.d.ts +126 -0
  40. package/dist/resources/targets.d.ts.map +1 -0
  41. package/dist/resources/targets.js +83 -0
  42. package/dist/resources/targets.js.map +1 -0
  43. package/package.json +55 -0
  44. package/src/client.ts +328 -0
  45. package/src/errors.ts +120 -0
  46. package/src/index.ts +100 -0
  47. package/src/pagination.ts +41 -0
  48. package/src/resources/branding.ts +59 -0
  49. package/src/resources/issues.ts +344 -0
  50. package/src/resources/reports.ts +104 -0
  51. package/src/resources/runs.ts +635 -0
  52. package/src/resources/suppression-rules.ts +69 -0
  53. package/src/resources/targets.ts +179 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../src/resources/reports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEtE;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAEjE;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAEnC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC;IAElC;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAEnC,8BAA8B;IAC9B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CAChD;AAID;;;;;;;GAOG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,YAAY;IAErD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;CAahE"}
@@ -0,0 +1,50 @@
1
+ const MACHINE_FORMATS = new Set(['json', 'markdown', 'csv', 'sarif']);
2
+ /**
3
+ * Reports — the one resource whose response is never JSON. Every format
4
+ * `request` accepts is a raw, streamed body (`text/csv`,
5
+ * `application/sarif+json`, plain `application/json` text, …), so this
6
+ * resource is built on {@link SecureportClient.requestRaw} rather than the
7
+ * usual `request<T>()`, and hands the `Response` itself back to the caller
8
+ * to read as text, parse, or stream to a file.
9
+ */
10
+ export class ReportsResource {
11
+ requestRaw;
12
+ constructor(requestRaw) {
13
+ this.requestRaw = requestRaw;
14
+ }
15
+ /**
16
+ * Renders a run into a report and streams it back. **Nothing is stored on
17
+ * the API side** — the bytes are produced from the run's snapshot on
18
+ * demand and exist only in this response; call this again for the same
19
+ * run and it renders again from whatever the run's snapshot is by then.
20
+ *
21
+ * **A failure partway through the stream cannot become an HTTP status.**
22
+ * The status and headers this method's `Response` carries are whatever was
23
+ * sent before the first byte of the body; nothing that goes wrong later in
24
+ * the stream can change them, so a truncated document looks identical to a
25
+ * complete one at this layer. Verify the body's own shape — that a JSON or
26
+ * SARIF document parses, that a CSV has the trailer row it expects — if a
27
+ * caller needs to be sure nothing was cut short.
28
+ *
29
+ * @throws {Error} synchronously, before any request is made, if
30
+ * `input.format` is `'pdf'` or `'html'` — this method exists only for
31
+ * `'json' | 'csv' | 'sarif' | 'markdown'`; a caller bypassing the type
32
+ * (plain JS, no type checker) is told so without spending a round trip.
33
+ * @throws {SecureportError} `conflict` if the run has not been reconciled
34
+ * — still running, or ended `failed`; `forbidden` should be unreachable
35
+ * given the format check above, but is still what the API itself would
36
+ * answer for `pdf`/`html`.
37
+ */
38
+ request(runId, input) {
39
+ if (!MACHINE_FORMATS.has(input.format)) {
40
+ throw new Error(`'${input.format}' reports are requested from the dashboard by a signed-in user — an ` +
41
+ 'API key can export json, csv, sarif or markdown.');
42
+ }
43
+ return this.requestRaw({
44
+ method: 'POST',
45
+ path: `/runs/${encodeURIComponent(runId)}/reports`,
46
+ body: input,
47
+ });
48
+ }
49
+ }
50
+ //# sourceMappingURL=reports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reports.js","sourceRoot":"","sources":["../../src/resources/reports.ts"],"names":[],"mappings":"AAsDA,MAAM,eAAe,GAAG,IAAI,GAAG,CAAe,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAEpF;;;;;;;GAOG;AACH,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,UAAwB;QAAxB,eAAU,GAAV,UAAU,CAAc;IAAG,CAAC;IAEzD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,KAAa,EAAE,KAAoB;QACzC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CACb,IAAI,KAAK,CAAC,MAAM,sEAAsE;gBACpF,kDAAkD,CACrD,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;YACrB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,SAAS,kBAAkB,CAAC,KAAK,CAAC,UAAU;YAClD,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,474 @@
1
+ import type { Snapshot } from '@secureport/core';
2
+ import type { FetchBody, Requester } from '../client.js';
3
+ import type { Severity } from './issues.js';
4
+ import type { Page, PageQuery } from '../pagination.js';
5
+ /**
6
+ * What kind of run this was — `scan` (Secureport originated the traffic,
7
+ * subject to `POST /runs`'s terms/verification gate), `upload` (results
8
+ * brought from elsewhere) or `manual` (a human recorded a finding directly).
9
+ * Mirrors `@secureport/core`'s `RunKind`; SDK-local for the same reason as
10
+ * `Issue`/`Finding` — see the module doc in `issues.ts`.
11
+ */
12
+ export type RunKind = 'scan' | 'upload' | 'manual';
13
+ /** What set the run going. Never defaulted — see {@link NewRun.trigger}. */
14
+ export type RunTrigger = 'github_action' | 'cli' | 'api' | 'scheduled' | 'web';
15
+ /**
16
+ * Where a run is in its lifecycle. `failed` and `cancelled` are both terminal
17
+ * and neither reconciles — see {@link RunsResource.cancel} for the difference.
18
+ */
19
+ export type RunStatus = 'running' | 'finished' | 'failed' | 'cancelled';
20
+ /**
21
+ * How much a scan does — the S/M/L/XL catalogue, smallest to largest, each
22
+ * size a strict superset of the one below. Mirrors `@secureport/core`.
23
+ */
24
+ export type ScanSize = 's' | 'm' | 'l' | 'xl';
25
+ /** What a run actually exercised. */
26
+ export interface Coverage {
27
+ /** Location patterns the run covered, as globs, e.g. `https://app.example.com/**`. */
28
+ readonly paths: readonly string[];
29
+ /** Ports exercised, where the run was port-aware. */
30
+ readonly ports?: readonly number[];
31
+ /**
32
+ * Severity classes whose checks the run exercised; absent means not
33
+ * severity-scoped. A scoped run cannot resolve issues outside its classes.
34
+ */
35
+ readonly severities?: readonly Severity[];
36
+ /** Engines that took part. */
37
+ readonly engines: readonly string[];
38
+ }
39
+ /**
40
+ * One execution against a target.
41
+ *
42
+ * Date fields are ISO 8601 strings, as the API sends them — see
43
+ * {@link RunsResource.snapshot} for the one method in this resource that
44
+ * returns real `Date`s instead.
45
+ */
46
+ export interface Run {
47
+ readonly id: string;
48
+ readonly orgId: string;
49
+ readonly targetId: string;
50
+ readonly kind: RunKind;
51
+ readonly trigger: RunTrigger;
52
+ readonly status: RunStatus;
53
+ /** How much this run does. Present exactly when `kind` is `'scan'`. */
54
+ readonly size?: ScanSize;
55
+ readonly coverage: Coverage;
56
+ /** The verification evidence a `kind: 'scan'` run was authorised against. */
57
+ readonly verificationId?: string;
58
+ readonly startedAt: string;
59
+ readonly finishedAt?: string;
60
+ }
61
+ export type RunPage = Page<Run>;
62
+ /** The filters `list`/`listAll` take, beside the page. Both optional and combinable. */
63
+ export interface RunFilters {
64
+ readonly targetId?: string;
65
+ readonly status?: RunStatus;
66
+ }
67
+ export interface NewRun {
68
+ readonly targetId: string;
69
+ readonly kind: RunKind;
70
+ /**
71
+ * Required, never defaulted — `00-DOMAIN.md` says trigger is set on every
72
+ * run from the first line of code, and a default would be a way of not
73
+ * saying.
74
+ */
75
+ readonly trigger: RunTrigger;
76
+ /**
77
+ * Scans only, defaulting to `'m'`; refused on kinds that originate no
78
+ * traffic. Sizes the service cannot run yet are refused, never downgraded.
79
+ */
80
+ readonly size?: ScanSize;
81
+ /**
82
+ * Absent means the whole target. Engines arrive with the results. Uploads
83
+ * only: a scan's coverage is derived server-side, and a claim is refused.
84
+ */
85
+ readonly coverage?: Coverage;
86
+ }
87
+ export interface FinishRunInput {
88
+ /**
89
+ * **`'failed'` reconciles nothing** — a failed run is not a complete
90
+ * observation, so {@link RunsResource.summary} and
91
+ * {@link RunsResource.snapshot} will 409 forever after. Only `'finished'`
92
+ * triggers reconciliation.
93
+ */
94
+ readonly status: 'finished' | 'failed';
95
+ }
96
+ /** A scan's phase, as {@link ScanProgress.phase} reports it. */
97
+ export type ScanPhase = 'queued' | 'launching' | 'scanning' | 'ended';
98
+ /**
99
+ * Where a scan is — {@link RunsResource.progress}'s answer.
100
+ *
101
+ * @remarks Deliberately no percentage: the engine reports nothing until it finishes, so the honest estimate is the time bound, not an invented fraction.
102
+ */
103
+ export interface ScanProgress {
104
+ readonly runId: string;
105
+ readonly status: RunStatus;
106
+ /**
107
+ * How far the scan has got: `'queued'` (accepted, not yet launched),
108
+ * `'launching'`, `'scanning'`, or `'ended'` — `status` says how.
109
+ */
110
+ readonly phase: ScanPhase;
111
+ /** Seconds since the run started — up to now, or to when it ended. */
112
+ readonly elapsedSeconds: number;
113
+ /** The size's time budget. The engine is stopped when it runs out. */
114
+ readonly budgetSeconds: number;
115
+ /**
116
+ * When the run will have ended by, one way or the other: the budget plus
117
+ * launch and upload grace. An ISO 8601 string, like every date here.
118
+ */
119
+ readonly expectedBy: string;
120
+ }
121
+ /** Every field in a {@link RunSummary} that counts issues by severity. */
122
+ export interface SeverityCounts {
123
+ readonly critical: number;
124
+ readonly high: number;
125
+ readonly medium: number;
126
+ readonly low: number;
127
+ readonly advisory: number;
128
+ }
129
+ /**
130
+ * What a run did, in the terms a report opens with. Written by
131
+ * reconciliation — see {@link RunsResource.summary}.
132
+ */
133
+ export interface RunSummary {
134
+ readonly runId: string;
135
+ readonly orgId: string;
136
+ readonly targetId: string;
137
+ readonly kind: RunKind;
138
+ readonly trigger: RunTrigger;
139
+ readonly engines: readonly string[];
140
+ readonly coverage: Coverage;
141
+ readonly durationMs: number;
142
+ readonly new: SeverityCounts;
143
+ readonly stillOpen: SeverityCounts;
144
+ readonly resolved: SeverityCounts;
145
+ readonly regressed: SeverityCounts;
146
+ readonly ignored: SeverityCounts;
147
+ readonly exposureScore: number;
148
+ readonly createdAt: string;
149
+ }
150
+ /** Where one upload's parse stands. */
151
+ export type ArtifactProcessingStatus = 'queued' | 'processing' | 'done' | 'failed';
152
+ /**
153
+ * A raw scanner artifact archived against a run — what {@link RunsResource.import}
154
+ * and {@link RunsResource.listArtifacts} both return.
155
+ *
156
+ * `findingCount`/`skippedLines` are present once `processingStatus` is
157
+ * `'done'`; absent while `'queued'` or `'processing'`, since the parse simply
158
+ * has not happened yet.
159
+ */
160
+ export interface RunArtifact {
161
+ readonly id: string;
162
+ readonly orgId: string;
163
+ readonly runId: string;
164
+ readonly objectName: string;
165
+ readonly filename: string;
166
+ readonly contentType: string;
167
+ readonly byteSize: number;
168
+ readonly sha256: string;
169
+ readonly sourceEngine?: string;
170
+ readonly expiresAt: string;
171
+ readonly processingStatus: ArtifactProcessingStatus;
172
+ /** Findings parsed from this upload. Present once `processingStatus` is `'done'`. */
173
+ readonly findingCount?: number;
174
+ /** Unreadable lines dropped from a line-delimited upload. Present with `'done'`. */
175
+ readonly skippedLines?: number;
176
+ readonly createdAt: string;
177
+ }
178
+ /** `GET /runs/{id}/artifacts`'s body — not a {@link Page}, since a run holds only a handful of files. */
179
+ export interface RunArtifactList {
180
+ readonly data: readonly RunArtifact[];
181
+ }
182
+ export interface NewRunImport {
183
+ /**
184
+ * The scanner's raw output, sent exactly as given — never JSON-encoded,
185
+ * whatever type it is. A `Buffer`, `Uint8Array`, `Blob` or `string` all work.
186
+ */
187
+ readonly body: FetchBody;
188
+ /**
189
+ * Sent verbatim as the request's `content-type` — chosen by the caller,
190
+ * never inferred from `body`. Must be one the API accepts (JSON, NDJSON,
191
+ * JSONL, XML or plain text/CSV); anything else is a `415`.
192
+ */
193
+ readonly contentType: string;
194
+ /** Which importer parses this file, e.g. `'nuclei'`, `'zap'`, `'burp'`, `'nessus'` or `'generic'`. */
195
+ readonly engine: string;
196
+ /** Recorded for the report; trusted for nothing. */
197
+ readonly filename?: string;
198
+ }
199
+ /**
200
+ * What {@link RunsResource.createUploadUrl} needs to mint a signed URL — the
201
+ * digest and size the caller already knows, having the whole file in hand to
202
+ * upload it. Computed client-side and not re-verified byte-for-byte by the
203
+ * API (see {@link RunsResource.createUploadUrl}'s own `@throws` and TSDoc):
204
+ * that is the entire point of a signed URL over {@link RunsResource.import} —
205
+ * the bytes never transit the API for it to check.
206
+ */
207
+ export interface NewRunImportUrl {
208
+ /** Lowercase hex SHA-256 of the file about to be uploaded. */
209
+ readonly sha256: string;
210
+ /** The file's exact size. Refused above the API's signed-upload ceiling. */
211
+ readonly byteSize: number;
212
+ /** Sent verbatim as the signed URL's bound content-type — must match the `PUT`'s own header exactly. */
213
+ readonly contentType: string;
214
+ /** Recorded for the report; trusted for nothing. */
215
+ readonly filename?: string;
216
+ }
217
+ /**
218
+ * A signed URL to `PUT` a large scanner artifact to, straight to the
219
+ * artifacts bucket — what {@link RunsResource.createUploadUrl} returns for a
220
+ * file not already archived on this run.
221
+ */
222
+ export interface RunUploadUrl {
223
+ /** `PUT` the file here — nothing else, no query string of your own. */
224
+ readonly uploadUrl: string;
225
+ /** Hand this back to {@link RunsResource.completeUpload} once the `PUT` succeeds. */
226
+ readonly objectName: string;
227
+ /**
228
+ * Every one of these must be sent verbatim as headers on the `PUT`, or the
229
+ * bucket refuses the upload — this is what carries the file's retention
230
+ * period through a path that never calls the API's own archiving code.
231
+ */
232
+ readonly requiredHeaders: Readonly<Record<string, string>>;
233
+ /** The URL itself stops accepting a `PUT` after this — independent of the artifact's own retention. */
234
+ readonly urlExpiresAt: string;
235
+ }
236
+ /**
237
+ * What {@link RunsResource.completeUpload} needs once a signed-URL `PUT`
238
+ * succeeded: the object it wrote to, and what to parse it as.
239
+ */
240
+ export interface CompleteRunImport {
241
+ /** From {@link RunUploadUrl.objectName} — the exact value {@link RunsResource.createUploadUrl} returned. */
242
+ readonly objectName: string;
243
+ /** Which importer parses this file, e.g. `'nuclei'`, `'zap'`, `'burp'`, `'nessus'` or `'generic'`. */
244
+ readonly engine: string;
245
+ /** Recorded for the report; trusted for nothing. */
246
+ readonly filename?: string;
247
+ }
248
+ /** {@link RunsResource.waitUntilFinished}'s options. */
249
+ export interface WaitUntilFinishedOptions {
250
+ /**
251
+ * How often to poll {@link RunsResource.get} while the run is still `running`.
252
+ *
253
+ * @defaultValue 5000
254
+ */
255
+ readonly pollIntervalMs?: number;
256
+ /**
257
+ * How long to poll before giving up and rejecting.
258
+ *
259
+ * Sized for a hosted scan, not an upload: a run behind a busy queue can take
260
+ * minutes, not seconds.
261
+ *
262
+ * @defaultValue 900000 (15 minutes)
263
+ */
264
+ readonly timeoutMs?: number;
265
+ }
266
+ /** {@link RunsResource.waitForArtifact}'s options — same shape as {@link WaitUntilFinishedOptions}. */
267
+ export interface WaitForArtifactOptions {
268
+ /**
269
+ * How often to poll {@link RunsResource.listArtifacts} while the artifact is
270
+ * still `queued` or `processing`.
271
+ *
272
+ * @defaultValue 5000
273
+ */
274
+ readonly pollIntervalMs?: number;
275
+ /**
276
+ * How long to poll before giving up and rejecting.
277
+ *
278
+ * @defaultValue 900000 (15 minutes)
279
+ */
280
+ readonly timeoutMs?: number;
281
+ }
282
+ /**
283
+ * Runs — one execution against a target, and the scan lifecycle around it
284
+ * (`00-DOMAIN.md` §3): started, evidence attached, finished, then
285
+ * reconciled into a summary and a snapshot.
286
+ */
287
+ export declare class RunsResource {
288
+ private readonly request;
289
+ constructor(request: Requester);
290
+ list(query?: PageQuery & RunFilters): Promise<RunPage>;
291
+ /** Every run matching `filters`, across every page, as an async iterator. */
292
+ listAll(filters?: RunFilters): AsyncIterable<Run>;
293
+ /**
294
+ * Starts a run against a target. It is created `running` and stays that way
295
+ * until {@link RunsResource.finish}: upload scanner output in between with
296
+ * {@link RunsResource.import}.
297
+ *
298
+ * @throws {SecureportError} `terms_required` for every kind if the
299
+ * organisation has not accepted the current terms — a human accepts them at
300
+ * `POST /orgs/{orgId}/terms`; an API key cannot. `verification_required` for
301
+ * `kind: 'scan'` if the target has no currently-passing verification,
302
+ * re-checked fresh as part of this same request rather than trusted from a
303
+ * stored flag. Neither is retried by the transport: both are settled
304
+ * refusals, not transient ones.
305
+ */
306
+ create(input: NewRun): Promise<Run>;
307
+ /**
308
+ * One run by id. What it found is {@link RunsResource.summary}, once it has finished —
309
+ * this method never carries a summary or findings itself.
310
+ */
311
+ get(id: string): Promise<Run>;
312
+ /**
313
+ * Ends a run and, for `status: 'finished'`, reconciles it: the findings
314
+ * uploaded against it become new, still-open, resolved or regressed
315
+ * issues, and the run gets a summary. **`status: 'failed'` reconciles
316
+ * nothing** — see {@link FinishRunInput.status}.
317
+ *
318
+ * @remarks Uploads and manual runs only: a `kind: 'scan'` run is refused here — its engine reports its own end, with evidence this route cannot supply. Stop a scan early with {@link RunsResource.cancel} instead.
319
+ * @throws {SecureportError} `conflict` if any upload is still being
320
+ * parsed — poll {@link RunsResource.listArtifacts} and finish once every
321
+ * one is `done` or `failed` — or if the run had already ended;
322
+ * `validation` for a `kind: 'scan'` run.
323
+ */
324
+ finish(id: string, input: FinishRunInput): Promise<Run>;
325
+ /**
326
+ * Stops a running scan: the run ends as `'cancelled'` immediately, and the
327
+ * scan job behind it is cancelled best-effort.
328
+ *
329
+ * @remarks If the job cancel fails, the engine simply runs out its time budget and its late reports are discarded, so `'cancelled'` is final either way. Nothing is reconciled — a cancelled run resolves no issues, and findings already ingested stay recorded as partial evidence. That intent is what distinguishes it from `'failed'`, which means the scan itself went wrong.
330
+ * @throws {SecureportError} `conflict` if the run had already ended;
331
+ * `validation` for a run that is not a `kind: 'scan'` — an upload is ended
332
+ * by its own caller via {@link RunsResource.finish}.
333
+ */
334
+ cancel(id: string): Promise<Run>;
335
+ /**
336
+ * Where a scan is: its phase, how long it has run, its time budget, and
337
+ * when it will have ended by — see {@link ScanProgress} for why no percentage.
338
+ *
339
+ * @remarks Combine with {@link RunsResource.waitUntilFinished} for a poll that also knows when to give up: `expectedBy` is the honest bound.
340
+ * @throws {SecureportError} `validation` for a run that is not a
341
+ * `kind: 'scan'` — an upload's progress is whatever its caller is doing.
342
+ */
343
+ progress(id: string): Promise<ScanProgress>;
344
+ /**
345
+ * Archives a raw scanner artifact against a run. Nothing is parsed on the
346
+ * client side — the whole file is handed to the API as `input.body`, with
347
+ * `input.contentType` sent verbatim, and the API decides how (and when) to
348
+ * parse it.
349
+ *
350
+ * **The response shape depends on size, not just success or failure.** A
351
+ * file under 5 MiB is parsed inline and answers `201` with
352
+ * `processingStatus: 'done'` and `findingCount`/`skippedLines` filled in. At
353
+ * or over 5 MiB the parse is queued and the API answers `202` with
354
+ * `processingStatus: 'queued'` instead — poll {@link RunsResource.listArtifacts}
355
+ * for the outcome. Both are success: check `processingStatus` on the result rather
356
+ * than assuming the synchronous shape. **25 MiB is a hard cap**, refused
357
+ * with `payload_too_large` rather than accepted and truncated.
358
+ *
359
+ * **Idempotent by content, not by request.** Re-uploading the exact same
360
+ * bytes against the same run answers `200` with the original row, verbatim
361
+ * — no re-parse — so a retried upload after a flaky network is never
362
+ * double-counted.
363
+ *
364
+ * @throws {SecureportError} `conflict` if the run has already ended;
365
+ * `payload_too_large` over 25 MiB; `unsupported_media_type` for a
366
+ * `contentType` the API does not accept, or a compressed body.
367
+ */
368
+ import(id: string, input: NewRunImport): Promise<RunArtifact>;
369
+ /**
370
+ * The first half of the signed-URL upload path for a file too large for
371
+ * {@link RunsResource.import} — Cloud Run caps that route's request body at
372
+ * 32 MiB whatever the API wants, so a genuinely large scan (a big Nessus or
373
+ * Burp export) goes here instead: mint a URL, `PUT` the file straight to
374
+ * the bucket yourself, then {@link RunsResource.completeUpload}.
375
+ *
376
+ * **Returns one of two shapes, told apart structurally.** If the same
377
+ * `sha256` is already archived on this run, this resolves with the
378
+ * existing {@link RunArtifact} directly — nothing minted, nothing to
379
+ * upload. Otherwise it resolves with a {@link RunUploadUrl}. Check for
380
+ * `'uploadUrl' in result` (or any field {@link RunUploadUrl} has and
381
+ * {@link RunArtifact} does not) to tell them apart.
382
+ *
383
+ * **You must `PUT` the bytes yourself, with a plain `fetch` — not through
384
+ * this SDK's own transport.** `uploadUrl` is a signed Cloud Storage URL:
385
+ * this client's `request`/`requestRaw` always attach your API key as a
386
+ * bearer token and always resolve paths against the API's own base URL,
387
+ * neither of which belongs on a request to Cloud Storage. Send every
388
+ * header in `result.requiredHeaders` verbatim — the bucket's signature
389
+ * check refuses the upload otherwise, silently from this SDK's point of
390
+ * view (it never sees that request).
391
+ *
392
+ * @throws {SecureportError} `conflict` if the run has already ended;
393
+ * `unsupported_media_type` for a `contentType` the API does not accept.
394
+ */
395
+ createUploadUrl(id: string, input: NewRunImportUrl): Promise<RunArtifact | RunUploadUrl>;
396
+ /**
397
+ * The second half of the signed-URL upload path — call once your own
398
+ * `PUT` to {@link RunUploadUrl.uploadUrl} has succeeded. Archives the
399
+ * object as a run artifact and queues it for parsing; unlike
400
+ * {@link RunsResource.import}, the result is never parsed synchronously
401
+ * here — anything that needed a signed URL is already well past the size
402
+ * the API parses inline. Poll {@link RunsResource.listArtifacts} (or use
403
+ * {@link RunsResource.waitForArtifact}) the same way a `202` from
404
+ * {@link RunsResource.import} is polled.
405
+ *
406
+ * **Idempotent by content, same as {@link RunsResource.import}.** Calling
407
+ * this twice for the same object answers `200` with the original row the
408
+ * second time.
409
+ *
410
+ * @throws {SecureportError} `conflict` if the run has already ended, or if
411
+ * nothing was actually uploaded to the signed URL (it may have expired).
412
+ */
413
+ completeUpload(id: string, input: CompleteRunImport): Promise<RunArtifact>;
414
+ /**
415
+ * The uploads archived against a run, with where each parse stands — what
416
+ * a client polls after a `202` from {@link RunsResource.import}. Not
417
+ * paginated: a run holds the handful of files one scan produced.
418
+ */
419
+ listArtifacts(id: string): Promise<RunArtifactList>;
420
+ /**
421
+ * What the run did, in the terms a report opens with.
422
+ *
423
+ * @throws {SecureportError} `conflict` if the run has not been reconciled
424
+ * — still running, or ended `failed` — rather than a zeroed summary that
425
+ * would read as "nothing found".
426
+ */
427
+ summary(id: string): Promise<RunSummary>;
428
+ /**
429
+ * The snapshot a report is rendered from: the run summary, the target,
430
+ * every issue with what this run changed about it, and the suppressed
431
+ * appendix.
432
+ *
433
+ * **Returns `@secureport/core`'s own `Snapshot` type, with real `Date`s —
434
+ * the one method in this resource that does.** Every other method here
435
+ * returns ISO 8601 strings, mirroring the wire exactly; this one instead
436
+ * runs the response text through core's own `parseSnapshot`, since that
437
+ * is the exact function a `Snapshot` written to disk is read back
438
+ * with, and the API's wire shape is asserted `Exact<>` against core's type
439
+ * server-side. That is what makes `@secureport/core` this package's first
440
+ * real dependency, rather than a structural mirror.
441
+ *
442
+ * @throws {SecureportError} `conflict` if the run has not been reconciled
443
+ * — still running, or ended `failed`.
444
+ */
445
+ snapshot(id: string): Promise<Snapshot>;
446
+ /**
447
+ * Polls {@link RunsResource.get} until the run leaves `'running'`,
448
+ * resolving with whatever it finished as. **Does not itself call
449
+ * {@link RunsResource.summary} or {@link RunsResource.snapshot}** — those
450
+ * still 409 until reconciliation completes, which is why this only
451
+ * watches `status`.
452
+ *
453
+ * Shaped for a long-running hosted scan from the start: today an upload
454
+ * run is finished by the caller directly, so this helper's payoff is
455
+ * mostly forward-looking until scans actually execute.
456
+ *
457
+ * @throws {Error} if `status` is still `'running'` once `timeoutMs` elapses.
458
+ */
459
+ waitUntilFinished(id: string, options?: WaitUntilFinishedOptions): Promise<Run>;
460
+ /**
461
+ * Polls {@link RunsResource.listArtifacts} until one artifact's
462
+ * `processingStatus` leaves `'queued'`/`'processing'`, resolving with it —
463
+ * the artifact-level completion {@link RunsResource.finish} itself waits
464
+ * on (its own TSDoc: "poll listArtifacts and finish once every one is done
465
+ * or failed"). A large upload answers {@link RunsResource.import} with
466
+ * `202 queued` before the parse has even started; this is what a caller
467
+ * that started one polls instead of hand-rolling the same loop.
468
+ *
469
+ * @throws {Error} if the artifact never appears on the run (id mismatch),
470
+ * or if it is still `queued`/`processing` once `timeoutMs` elapses.
471
+ */
472
+ waitForArtifact(runId: string, artifactId: string, options?: WaitForArtifactOptions): Promise<RunArtifact>;
473
+ }
474
+ //# sourceMappingURL=runs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/resources/runs.ts"],"names":[],"mappings":"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"}