@pipeline-builder/pipeline-data 4.1.22 → 4.1.24
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/lib/api/crud-service.js +2 -71
- package/lib/api/keyset-cursor.d.ts +38 -0
- package/lib/api/keyset-cursor.js +82 -0
- package/lib/api/plugin-advisories.d.ts +30 -0
- package/lib/api/plugin-advisories.js +89 -0
- package/lib/api/plugin-consumption-policy.d.ts +44 -0
- package/lib/api/plugin-consumption-policy.js +133 -0
- package/lib/api/plugin-resolution.d.ts +2 -54
- package/lib/api/plugin-resolution.js +5 -211
- package/lib/api/public-directory.d.ts +3 -7
- package/lib/api/public-directory.js +2 -2
- package/lib/api/reporting/caches.d.ts +5 -0
- package/lib/api/reporting/caches.js +11 -1
- package/lib/api/reporting/dora-scoring.d.ts +1 -1
- package/lib/api/reporting/dora-scoring.js +2 -2
- package/lib/api/reporting/ingest.d.ts +11 -0
- package/lib/api/reporting/ingest.js +210 -0
- package/lib/api/reporting/retention-sweep.d.ts +17 -0
- package/lib/api/reporting/retention-sweep.js +155 -0
- package/lib/api/reporting/retention.d.ts +1 -1
- package/lib/api/reporting/retention.js +2 -2
- package/lib/api/reporting-service.d.ts +5 -18
- package/lib/api/reporting-service.js +17 -333
- package/lib/database/index.d.ts +2 -2
- package/lib/database/index.js +2 -2
- package/lib/database/retry-strategy.d.ts +0 -6
- package/lib/database/retry-strategy.js +4 -12
- package/lib/database/schema/ecosystem.d.ts +9 -7
- package/lib/database/schema/ecosystem.js +1 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.js +4 -2
- package/lib/testing/exports.json +0 -1
- package/package.json +2 -2
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Keyset (cursor) pagination primitives for `CrudService.findPaginated`.
|
|
5
|
+
*
|
|
6
|
+
* Pure functions over a Drizzle column — no table, no tenant context, no I/O —
|
|
7
|
+
* which is why they live outside the CRUD base class: the cursor encoding and
|
|
8
|
+
* its "is this castable / strictly after" rules are the fiddly, test-worthy
|
|
9
|
+
* part of paging and are easier to reason about on their own.
|
|
10
|
+
*/
|
|
11
|
+
import { sql } from 'drizzle-orm';
|
|
12
|
+
/** Projection alias carrying the sort column's exact DB text for the next cursor. */
|
|
13
|
+
export const CURSOR_SORT_KEY = '__cursorSortKey';
|
|
14
|
+
/**
|
|
15
|
+
* Opaque keyset cursor: the last row's sort value as Postgres TEXT (full
|
|
16
|
+
* precision — a JS `Date` would truncate `timestamptz` microseconds to ms, so
|
|
17
|
+
* `created_at > '<ms>'` re-returns or skips rows in the same millisecond) plus
|
|
18
|
+
* its `id` as the tie-breaker.
|
|
19
|
+
*/
|
|
20
|
+
export function encodeCursor(sortText, id) {
|
|
21
|
+
return Buffer.from(JSON.stringify([sortText, id]), 'utf8').toString('base64url');
|
|
22
|
+
}
|
|
23
|
+
/** Decode a cursor produced by {@link encodeCursor}; `null` when malformed. */
|
|
24
|
+
export function decodeCursor(cursor) {
|
|
25
|
+
try {
|
|
26
|
+
const parsed = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'));
|
|
27
|
+
if (Array.isArray(parsed) && parsed.length === 2
|
|
28
|
+
&& (parsed[0] === null || typeof parsed[0] === 'string')
|
|
29
|
+
&& typeof parsed[1] === 'string' && parsed[1].length > 0) {
|
|
30
|
+
return { sortText: parsed[0], id: parsed[1] };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// fall through
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const UUID_TEXT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
39
|
+
/** Postgres `timestamp[tz]::text` / `date::text` (also accepts ISO-8601). */
|
|
40
|
+
const TIMESTAMP_TEXT = /^\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,6})?)?(?:Z|[+-]\d{2}(?::?\d{2})?)?)?$/;
|
|
41
|
+
const NUMERIC_TEXT = /^-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?$/;
|
|
42
|
+
/**
|
|
43
|
+
* Whether `text` can be cast to `column`'s type. A decoded cursor is still
|
|
44
|
+
* client input: a value Postgres can't cast (a non-UUID id, a garbage
|
|
45
|
+
* timestamp) fails the whole query with a 500. Column types this doesn't know
|
|
46
|
+
* (text, varchar, …) accept any string.
|
|
47
|
+
*/
|
|
48
|
+
export function isCastableTo(column, text) {
|
|
49
|
+
const { columnType, dataType } = column;
|
|
50
|
+
const enumValues = column.enumValues;
|
|
51
|
+
if (columnType === 'PgUUID')
|
|
52
|
+
return UUID_TEXT.test(text);
|
|
53
|
+
if ((columnType === 'PgEnumColumn' || columnType === 'PgEnumObjectColumn') && enumValues?.length)
|
|
54
|
+
return enumValues.includes(text);
|
|
55
|
+
if (dataType === 'date' || columnType === 'PgTimestampString' || columnType === 'PgDateString')
|
|
56
|
+
return TIMESTAMP_TEXT.test(text);
|
|
57
|
+
if (dataType === 'boolean')
|
|
58
|
+
return text === 'true' || text === 'false';
|
|
59
|
+
if (dataType === 'number' || dataType === 'bigint')
|
|
60
|
+
return NUMERIC_TEXT.test(text);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Keyset predicate "strictly after (sortText, id)" for `ORDER BY sort <dir>, id <dir>`
|
|
65
|
+
* under Postgres' default null placement (ASC → NULLS LAST, DESC → NULLS FIRST).
|
|
66
|
+
* The text value is bound as a parameter compared against the column, so Postgres
|
|
67
|
+
* casts it back to the column's type at full precision.
|
|
68
|
+
*/
|
|
69
|
+
export function keysetAfter(sortColumn, idColumn, sortOrder, sortText, id) {
|
|
70
|
+
if (sortColumn === idColumn) {
|
|
71
|
+
return sortOrder === 'desc' ? sql `${idColumn} < ${id}` : sql `${idColumn} > ${id}`;
|
|
72
|
+
}
|
|
73
|
+
if (sortOrder === 'asc') {
|
|
74
|
+
return sortText === null
|
|
75
|
+
? sql `(${sortColumn} IS NULL AND ${idColumn} > ${id})`
|
|
76
|
+
: sql `(${sortColumn} > ${sortText} OR (${sortColumn} = ${sortText} AND ${idColumn} > ${id}) OR ${sortColumn} IS NULL)`;
|
|
77
|
+
}
|
|
78
|
+
return sortText === null
|
|
79
|
+
? sql `(${sortColumn} IS NOT NULL OR (${sortColumn} IS NULL AND ${idColumn} < ${id}))`
|
|
80
|
+
: sql `(${sortColumn} < ${sortText} OR (${sortColumn} = ${sortText} AND ${idColumn} < ${id}))`;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5c2V0LWN1cnNvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkva2V5c2V0LWN1cnNvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDOzs7Ozs7O0dBT0c7QUFFSCxPQUFPLEVBQUUsR0FBRyxFQUFZLE1BQU0sYUFBYSxDQUFDO0FBRzVDLHFGQUFxRjtBQUNyRixNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsaUJBQWlCLENBQUM7QUFFakQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUFDLFFBQXVCLEVBQUUsRUFBVTtJQUM5RCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNuRixDQUFDO0FBRUQsK0VBQStFO0FBQy9FLE1BQU0sVUFBVSxZQUFZLENBQUMsTUFBYztJQUN6QyxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBWSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLElBQ0UsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUM7ZUFDekMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsQ0FBQztlQUNyRCxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQ3hELENBQUM7WUFDRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDaEQsQ0FBQztJQUNILENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxlQUFlO0lBQ2pCLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRCxNQUFNLFNBQVMsR0FBRyxpRUFBaUUsQ0FBQztBQUNwRiw2RUFBNkU7QUFDN0UsTUFBTSxjQUFjLEdBQUcsOEZBQThGLENBQUM7QUFDdEgsTUFBTSxZQUFZLEdBQUcsb0NBQW9DLENBQUM7QUFFMUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUFDLE1BQWlCLEVBQUUsSUFBWTtJQUMxRCxNQUFNLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUN4QyxNQUFNLFVBQVUsR0FBSSxNQUE2QyxDQUFDLFVBQVUsQ0FBQztJQUM3RSxJQUFJLFVBQVUsS0FBSyxRQUFRO1FBQUUsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pELElBQUksQ0FBQyxVQUFVLEtBQUssY0FBYyxJQUFJLFVBQVUsS0FBSyxvQkFBb0IsQ0FBQyxJQUFJLFVBQVUsRUFBRSxNQUFNO1FBQUUsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25JLElBQUksUUFBUSxLQUFLLE1BQU0sSUFBSSxVQUFVLEtBQUssbUJBQW1CLElBQUksVUFBVSxLQUFLLGNBQWM7UUFBRSxPQUFPLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDakksSUFBSSxRQUFRLEtBQUssU0FBUztRQUFFLE9BQU8sSUFBSSxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssT0FBTyxDQUFDO0lBQ3ZFLElBQUksUUFBUSxLQUFLLFFBQVEsSUFBSSxRQUFRLEtBQUssUUFBUTtRQUFFLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuRixPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQ3pCLFVBQXFCLEVBQ3JCLFFBQW1CLEVBQ25CLFNBQXlCLEVBQ3pCLFFBQXVCLEVBQ3ZCLEVBQVU7SUFFVixJQUFJLFVBQVUsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM1QixPQUFPLFNBQVMsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQSxHQUFHLFFBQVEsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFBLEdBQUcsUUFBUSxNQUFNLEVBQUUsRUFBRSxDQUFDO0lBQ3BGLENBQUM7SUFDRCxJQUFJLFNBQVMsS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUN4QixPQUFPLFFBQVEsS0FBSyxJQUFJO1lBQ3RCLENBQUMsQ0FBQyxHQUFHLENBQUEsSUFBSSxVQUFVLGdCQUFnQixRQUFRLE1BQU0sRUFBRSxHQUFHO1lBQ3RELENBQUMsQ0FBQyxHQUFHLENBQUEsSUFBSSxVQUFVLE1BQU0sUUFBUSxRQUFRLFVBQVUsTUFBTSxRQUFRLFFBQVEsUUFBUSxNQUFNLEVBQUUsUUFBUSxVQUFVLFdBQVcsQ0FBQztJQUMzSCxDQUFDO0lBQ0QsT0FBTyxRQUFRLEtBQUssSUFBSTtRQUN0QixDQUFDLENBQUMsR0FBRyxDQUFBLElBQUksVUFBVSxvQkFBb0IsVUFBVSxnQkFBZ0IsUUFBUSxNQUFNLEVBQUUsSUFBSTtRQUNyRixDQUFDLENBQUMsR0FBRyxDQUFBLElBQUksVUFBVSxNQUFNLFFBQVEsUUFBUSxVQUFVLE1BQU0sUUFBUSxRQUFRLFFBQVEsTUFBTSxFQUFFLElBQUksQ0FBQztBQUNsRyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogS2V5c2V0IChjdXJzb3IpIHBhZ2luYXRpb24gcHJpbWl0aXZlcyBmb3IgYENydWRTZXJ2aWNlLmZpbmRQYWdpbmF0ZWRgLlxuICpcbiAqIFB1cmUgZnVuY3Rpb25zIG92ZXIgYSBEcml6emxlIGNvbHVtbiDigJQgbm8gdGFibGUsIG5vIHRlbmFudCBjb250ZXh0LCBubyBJL08g4oCUXG4gKiB3aGljaCBpcyB3aHkgdGhleSBsaXZlIG91dHNpZGUgdGhlIENSVUQgYmFzZSBjbGFzczogdGhlIGN1cnNvciBlbmNvZGluZyBhbmRcbiAqIGl0cyBcImlzIHRoaXMgY2FzdGFibGUgLyBzdHJpY3RseSBhZnRlclwiIHJ1bGVzIGFyZSB0aGUgZmlkZGx5LCB0ZXN0LXdvcnRoeVxuICogcGFydCBvZiBwYWdpbmcgYW5kIGFyZSBlYXNpZXIgdG8gcmVhc29uIGFib3V0IG9uIHRoZWlyIG93bi5cbiAqL1xuXG5pbXBvcnQgeyBzcWwsIHR5cGUgU1FMIH0gZnJvbSAnZHJpenpsZS1vcm0nO1xuaW1wb3J0IHR5cGUgeyBBbnlDb2x1bW4gfSBmcm9tICdkcml6emxlLW9ybS9jb2x1bW4nO1xuXG4vKiogUHJvamVjdGlvbiBhbGlhcyBjYXJyeWluZyB0aGUgc29ydCBjb2x1bW4ncyBleGFjdCBEQiB0ZXh0IGZvciB0aGUgbmV4dCBjdXJzb3IuICovXG5leHBvcnQgY29uc3QgQ1VSU09SX1NPUlRfS0VZID0gJ19fY3Vyc29yU29ydEtleSc7XG5cbi8qKlxuICogT3BhcXVlIGtleXNldCBjdXJzb3I6IHRoZSBsYXN0IHJvdydzIHNvcnQgdmFsdWUgYXMgUG9zdGdyZXMgVEVYVCAoZnVsbFxuICogcHJlY2lzaW9uIOKAlCBhIEpTIGBEYXRlYCB3b3VsZCB0cnVuY2F0ZSBgdGltZXN0YW1wdHpgIG1pY3Jvc2Vjb25kcyB0byBtcywgc29cbiAqIGBjcmVhdGVkX2F0ID4gJzxtcz4nYCByZS1yZXR1cm5zIG9yIHNraXBzIHJvd3MgaW4gdGhlIHNhbWUgbWlsbGlzZWNvbmQpIHBsdXNcbiAqIGl0cyBgaWRgIGFzIHRoZSB0aWUtYnJlYWtlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZUN1cnNvcihzb3J0VGV4dDogc3RyaW5nIHwgbnVsbCwgaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShbc29ydFRleHQsIGlkXSksICd1dGY4JykudG9TdHJpbmcoJ2Jhc2U2NHVybCcpO1xufVxuXG4vKiogRGVjb2RlIGEgY3Vyc29yIHByb2R1Y2VkIGJ5IHtAbGluayBlbmNvZGVDdXJzb3J9OyBgbnVsbGAgd2hlbiBtYWxmb3JtZWQuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlQ3Vyc29yKGN1cnNvcjogc3RyaW5nKTogeyBzb3J0VGV4dDogc3RyaW5nIHwgbnVsbDsgaWQ6IHN0cmluZyB9IHwgbnVsbCB7XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkOiB1bmtub3duID0gSlNPTi5wYXJzZShCdWZmZXIuZnJvbShjdXJzb3IsICdiYXNlNjR1cmwnKS50b1N0cmluZygndXRmOCcpKTtcbiAgICBpZiAoXG4gICAgICBBcnJheS5pc0FycmF5KHBhcnNlZCkgJiYgcGFyc2VkLmxlbmd0aCA9PT0gMlxuICAgICAgJiYgKHBhcnNlZFswXSA9PT0gbnVsbCB8fCB0eXBlb2YgcGFyc2VkWzBdID09PSAnc3RyaW5nJylcbiAgICAgICYmIHR5cGVvZiBwYXJzZWRbMV0gPT09ICdzdHJpbmcnICYmIHBhcnNlZFsxXS5sZW5ndGggPiAwXG4gICAgKSB7XG4gICAgICByZXR1cm4geyBzb3J0VGV4dDogcGFyc2VkWzBdLCBpZDogcGFyc2VkWzFdIH07XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBmYWxsIHRocm91Z2hcbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuY29uc3QgVVVJRF9URVhUID0gL15bMC05YS1mXXs4fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXsxMn0kL2k7XG4vKiogUG9zdGdyZXMgYHRpbWVzdGFtcFt0el06OnRleHRgIC8gYGRhdGU6OnRleHRgIChhbHNvIGFjY2VwdHMgSVNPLTg2MDEpLiAqL1xuY29uc3QgVElNRVNUQU1QX1RFWFQgPSAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9KD86WyBUXVxcZHsyfTpcXGR7Mn0oPzo6XFxkezJ9KD86XFwuXFxkezEsNn0pPyk/KD86WnxbKy1dXFxkezJ9KD86Oj9cXGR7Mn0pPyk/KT8kLztcbmNvbnN0IE5VTUVSSUNfVEVYVCA9IC9eLT9cXGQrKD86XFwuXFxkKyk/KD86W2VFXVstK10/XFxkKyk/JC87XG5cbi8qKlxuICogV2hldGhlciBgdGV4dGAgY2FuIGJlIGNhc3QgdG8gYGNvbHVtbmAncyB0eXBlLiBBIGRlY29kZWQgY3Vyc29yIGlzIHN0aWxsXG4gKiBjbGllbnQgaW5wdXQ6IGEgdmFsdWUgUG9zdGdyZXMgY2FuJ3QgY2FzdCAoYSBub24tVVVJRCBpZCwgYSBnYXJiYWdlXG4gKiB0aW1lc3RhbXApIGZhaWxzIHRoZSB3aG9sZSBxdWVyeSB3aXRoIGEgNTAwLiBDb2x1bW4gdHlwZXMgdGhpcyBkb2Vzbid0IGtub3dcbiAqICh0ZXh0LCB2YXJjaGFyLCDigKYpIGFjY2VwdCBhbnkgc3RyaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDYXN0YWJsZVRvKGNvbHVtbjogQW55Q29sdW1uLCB0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgeyBjb2x1bW5UeXBlLCBkYXRhVHlwZSB9ID0gY29sdW1uO1xuICBjb25zdCBlbnVtVmFsdWVzID0gKGNvbHVtbiBhcyB7IGVudW1WYWx1ZXM/OiByZWFkb25seSBzdHJpbmdbXSB9KS5lbnVtVmFsdWVzO1xuICBpZiAoY29sdW1uVHlwZSA9PT0gJ1BnVVVJRCcpIHJldHVybiBVVUlEX1RFWFQudGVzdCh0ZXh0KTtcbiAgaWYgKChjb2x1bW5UeXBlID09PSAnUGdFbnVtQ29sdW1uJyB8fCBjb2x1bW5UeXBlID09PSAnUGdFbnVtT2JqZWN0Q29sdW1uJykgJiYgZW51bVZhbHVlcz8ubGVuZ3RoKSByZXR1cm4gZW51bVZhbHVlcy5pbmNsdWRlcyh0ZXh0KTtcbiAgaWYgKGRhdGFUeXBlID09PSAnZGF0ZScgfHwgY29sdW1uVHlwZSA9PT0gJ1BnVGltZXN0YW1wU3RyaW5nJyB8fCBjb2x1bW5UeXBlID09PSAnUGdEYXRlU3RyaW5nJykgcmV0dXJuIFRJTUVTVEFNUF9URVhULnRlc3QodGV4dCk7XG4gIGlmIChkYXRhVHlwZSA9PT0gJ2Jvb2xlYW4nKSByZXR1cm4gdGV4dCA9PT0gJ3RydWUnIHx8IHRleHQgPT09ICdmYWxzZSc7XG4gIGlmIChkYXRhVHlwZSA9PT0gJ251bWJlcicgfHwgZGF0YVR5cGUgPT09ICdiaWdpbnQnKSByZXR1cm4gTlVNRVJJQ19URVhULnRlc3QodGV4dCk7XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEtleXNldCBwcmVkaWNhdGUgXCJzdHJpY3RseSBhZnRlciAoc29ydFRleHQsIGlkKVwiIGZvciBgT1JERVIgQlkgc29ydCA8ZGlyPiwgaWQgPGRpcj5gXG4gKiB1bmRlciBQb3N0Z3JlcycgZGVmYXVsdCBudWxsIHBsYWNlbWVudCAoQVNDIOKGkiBOVUxMUyBMQVNULCBERVNDIOKGkiBOVUxMUyBGSVJTVCkuXG4gKiBUaGUgdGV4dCB2YWx1ZSBpcyBib3VuZCBhcyBhIHBhcmFtZXRlciBjb21wYXJlZCBhZ2FpbnN0IHRoZSBjb2x1bW4sIHNvIFBvc3RncmVzXG4gKiBjYXN0cyBpdCBiYWNrIHRvIHRoZSBjb2x1bW4ncyB0eXBlIGF0IGZ1bGwgcHJlY2lzaW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24ga2V5c2V0QWZ0ZXIoXG4gIHNvcnRDb2x1bW46IEFueUNvbHVtbixcbiAgaWRDb2x1bW46IEFueUNvbHVtbixcbiAgc29ydE9yZGVyOiAnYXNjJyB8ICdkZXNjJyxcbiAgc29ydFRleHQ6IHN0cmluZyB8IG51bGwsXG4gIGlkOiBzdHJpbmcsXG4pOiBTUUwge1xuICBpZiAoc29ydENvbHVtbiA9PT0gaWRDb2x1bW4pIHtcbiAgICByZXR1cm4gc29ydE9yZGVyID09PSAnZGVzYycgPyBzcWxgJHtpZENvbHVtbn0gPCAke2lkfWAgOiBzcWxgJHtpZENvbHVtbn0gPiAke2lkfWA7XG4gIH1cbiAgaWYgKHNvcnRPcmRlciA9PT0gJ2FzYycpIHtcbiAgICByZXR1cm4gc29ydFRleHQgPT09IG51bGxcbiAgICAgID8gc3FsYCgke3NvcnRDb2x1bW59IElTIE5VTEwgQU5EICR7aWRDb2x1bW59ID4gJHtpZH0pYFxuICAgICAgOiBzcWxgKCR7c29ydENvbHVtbn0gPiAke3NvcnRUZXh0fSBPUiAoJHtzb3J0Q29sdW1ufSA9ICR7c29ydFRleHR9IEFORCAke2lkQ29sdW1ufSA+ICR7aWR9KSBPUiAke3NvcnRDb2x1bW59IElTIE5VTEwpYDtcbiAgfVxuICByZXR1cm4gc29ydFRleHQgPT09IG51bGxcbiAgICA/IHNxbGAoJHtzb3J0Q29sdW1ufSBJUyBOT1QgTlVMTCBPUiAoJHtzb3J0Q29sdW1ufSBJUyBOVUxMIEFORCAke2lkQ29sdW1ufSA8ICR7aWR9KSlgXG4gICAgOiBzcWxgKCR7c29ydENvbHVtbn0gPCAke3NvcnRUZXh0fSBPUiAoJHtzb3J0Q29sdW1ufSA9ICR7c29ydFRleHR9IEFORCAke2lkQ29sdW1ufSA8ICR7aWR9KSlgO1xufVxuIl19
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advisory matching: does a published advisory's `affectedRange` cover a given
|
|
3
|
+
* version, and which advisories block a resolution under the org's policy.
|
|
4
|
+
*
|
|
5
|
+
* The range grammar is npm-style and deliberately re-implemented here rather
|
|
6
|
+
* than pulled from `semver`: advisory ranges are OPERATOR SETS
|
|
7
|
+
* (`>=1.0.0 <1.2.3`, `1.0.0 - 1.2.0`, `^1.2`, `1.x`, `||`), a different shape
|
|
8
|
+
* from the install/reference version SPECS in ./semver-range.ts.
|
|
9
|
+
*/
|
|
10
|
+
import type { ConsumptionPolicy } from './plugin-consumption-policy.js';
|
|
11
|
+
import type { AdvisorySeverity, BlockOnAdvisory, PluginAdvisory } from '../database/drizzle-schema.js';
|
|
12
|
+
/** Severities each `blockOnAdvisory` setting blocks. */
|
|
13
|
+
export declare const ADVISORY_BLOCK_SEVERITIES: Readonly<Record<BlockOnAdvisory, readonly AdvisorySeverity[]>>;
|
|
14
|
+
/**
|
|
15
|
+
* Whether an advisory's `affectedRange` covers `version`: `||`-separated
|
|
16
|
+
* comparator sets, each either the lookup spec forms (`^`, `~`, partial,
|
|
17
|
+
* exact) or space-separated comparators (`>=1.0.0 <1.2.3`) or a hyphen range.
|
|
18
|
+
* `*` covers everything; an unparseable range covers nothing.
|
|
19
|
+
*/
|
|
20
|
+
export declare function advisoryRangeCovers(range: string, version: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Why `range` isn't a usable advisory range (the forms {@link advisoryRangeCovers}
|
|
23
|
+
* understands), or null when it is. An advisory whose range parses as nothing
|
|
24
|
+
* would silently cover nothing, so drafts are refused instead.
|
|
25
|
+
*/
|
|
26
|
+
export declare function advisoryRangeProblem(range: string): string | null;
|
|
27
|
+
/** The PUBLISHED advisories whose range covers `version` (any severity), most severe first. */
|
|
28
|
+
export declare function advisoriesCovering<A extends Pick<PluginAdvisory, 'severity' | 'state' | 'affectedRange'>>(advisories: readonly A[], version: string): A[];
|
|
29
|
+
/** The PUBLISHED advisories the policy blocks `version` for. */
|
|
30
|
+
export declare function blockingAdvisories(advisories: readonly Pick<PluginAdvisory, 'id' | 'severity' | 'state' | 'affectedRange' | 'fixedVersion' | 'summary'>[], version: string, policy: Pick<ConsumptionPolicy, 'blockOnAdvisory'>): Array<Pick<PluginAdvisory, 'id' | 'severity' | 'state' | 'affectedRange' | 'fixedVersion' | 'summary'>>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { compareSemver, parseSemver, parseVersionSpec, satisfiesVersionSpec } from './semver-range.js';
|
|
4
|
+
/** Severities each `blockOnAdvisory` setting blocks. */
|
|
5
|
+
export const ADVISORY_BLOCK_SEVERITIES = {
|
|
6
|
+
critical: ['critical'],
|
|
7
|
+
high: ['critical', 'high'],
|
|
8
|
+
never: [],
|
|
9
|
+
};
|
|
10
|
+
const COMPARATOR = /^(>=|<=|>|<|=)?\s*v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)$/;
|
|
11
|
+
/** One comparator set (`>=1.0.0 <1.2.3`, `^1.2`, `1.x`, `1.0.0 - 1.2.0`) against `version`. */
|
|
12
|
+
function comparatorSetCovers(set, version) {
|
|
13
|
+
const hyphen = /^(\S+)\s+-\s+(\S+)$/.exec(set);
|
|
14
|
+
if (hyphen)
|
|
15
|
+
return compareSemver(version, hyphen[1]) >= 0 && compareSemver(version, hyphen[2]) <= 0;
|
|
16
|
+
const parts = set.split(/\s+/).filter(Boolean);
|
|
17
|
+
if (parts.length === 1 && parseVersionSpec(parts[0]))
|
|
18
|
+
return satisfiesVersionSpec(version, parts[0]);
|
|
19
|
+
return parts.every((p) => {
|
|
20
|
+
const m = COMPARATOR.exec(p);
|
|
21
|
+
if (!m)
|
|
22
|
+
return false;
|
|
23
|
+
const c = compareSemver(version, m[2]);
|
|
24
|
+
switch (m[1] ?? '=') {
|
|
25
|
+
case '>=': return c >= 0;
|
|
26
|
+
case '<=': return c <= 0;
|
|
27
|
+
case '>': return c > 0;
|
|
28
|
+
case '<': return c < 0;
|
|
29
|
+
default: return c === 0;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether an advisory's `affectedRange` covers `version`: `||`-separated
|
|
35
|
+
* comparator sets, each either the lookup spec forms (`^`, `~`, partial,
|
|
36
|
+
* exact) or space-separated comparators (`>=1.0.0 <1.2.3`) or a hyphen range.
|
|
37
|
+
* `*` covers everything; an unparseable range covers nothing.
|
|
38
|
+
*/
|
|
39
|
+
export function advisoryRangeCovers(range, version) {
|
|
40
|
+
if (!parseSemver(version))
|
|
41
|
+
return false;
|
|
42
|
+
return range.split('||').map((s) => s.trim()).some((set) => set === '*' || (set !== '' && comparatorSetCovers(set, version)));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Why `range` isn't a usable advisory range (the forms {@link advisoryRangeCovers}
|
|
46
|
+
* understands), or null when it is. An advisory whose range parses as nothing
|
|
47
|
+
* would silently cover nothing, so drafts are refused instead.
|
|
48
|
+
*/
|
|
49
|
+
export function advisoryRangeProblem(range) {
|
|
50
|
+
const trimmed = range.trim();
|
|
51
|
+
if (trimmed === '')
|
|
52
|
+
return 'the affected range is empty';
|
|
53
|
+
if (trimmed.length > 255)
|
|
54
|
+
return 'the affected range is longer than 255 characters';
|
|
55
|
+
for (const set of trimmed.split('||').map((x) => x.trim())) {
|
|
56
|
+
if (set === '*')
|
|
57
|
+
continue;
|
|
58
|
+
if (set === '')
|
|
59
|
+
return 'the affected range has an empty "||" alternative';
|
|
60
|
+
const hyphen = /^(\S+)\s+-\s+(\S+)$/.exec(set);
|
|
61
|
+
if (hyphen) {
|
|
62
|
+
if (!parseSemver(hyphen[1]) || !parseSemver(hyphen[2]))
|
|
63
|
+
return `"${set}" is not a valid hyphen range`;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const parts = set.split(/\s+/).filter(Boolean);
|
|
67
|
+
if (parts.length === 1 && parts[0] !== 'latest' && parseVersionSpec(parts[0]))
|
|
68
|
+
continue;
|
|
69
|
+
const bad = parts.find((x) => !COMPARATOR.test(x));
|
|
70
|
+
if (bad !== undefined)
|
|
71
|
+
return `"${bad}" is not a version, a ^/~ range or a comparator (>=, <=, >, <, =)`;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
/** The PUBLISHED advisories whose range covers `version` (any severity), most severe first. */
|
|
76
|
+
export function advisoriesCovering(advisories, version) {
|
|
77
|
+
const rank = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
78
|
+
return advisories
|
|
79
|
+
.filter((a) => a.state === 'published' && advisoryRangeCovers(a.affectedRange, version))
|
|
80
|
+
.sort((a, b) => rank[a.severity] - rank[b.severity]);
|
|
81
|
+
}
|
|
82
|
+
/** The PUBLISHED advisories the policy blocks `version` for. */
|
|
83
|
+
export function blockingAdvisories(advisories, version, policy) {
|
|
84
|
+
const severities = ADVISORY_BLOCK_SEVERITIES[policy.blockOnAdvisory];
|
|
85
|
+
if (severities.length === 0)
|
|
86
|
+
return [];
|
|
87
|
+
return advisories.filter((a) => a.state === 'published' && severities.includes(a.severity) && advisoryRangeCovers(a.affectedRange, version));
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWFkdmlzb3JpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3BsdWdpbi1hZHZpc29yaWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFhdEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQVF2Ryx3REFBd0Q7QUFDeEQsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQW1FO0lBQ3ZHLFFBQVEsRUFBRSxDQUFDLFVBQVUsQ0FBQztJQUN0QixJQUFJLEVBQUUsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDO0lBQzFCLEtBQUssRUFBRSxFQUFFO0NBQ1YsQ0FBQztBQUVGLE1BQU0sVUFBVSxHQUFHLCtFQUErRSxDQUFDO0FBRW5HLCtGQUErRjtBQUMvRixTQUFTLG1CQUFtQixDQUFDLEdBQVcsRUFBRSxPQUFlO0lBQ3ZELE1BQU0sTUFBTSxHQUFHLHFCQUFxQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvQyxJQUFJLE1BQU07UUFBRSxPQUFPLGFBQWEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBRSxDQUFDLElBQUksQ0FBQyxJQUFJLGFBQWEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBRSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RHLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9DLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBRSxDQUFDO1FBQUUsT0FBTyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUM7SUFDdkcsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7UUFDdkIsTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsQ0FBQztZQUFFLE9BQU8sS0FBSyxDQUFDO1FBQ3JCLE1BQU0sQ0FBQyxHQUFHLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUM7UUFDeEMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7WUFDcEIsS0FBSyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3pCLEtBQUssSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN6QixLQUFLLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkIsS0FBSyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZCLFNBQVMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxLQUFhLEVBQUUsT0FBZTtJQUNoRSxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3hDLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsS0FBSyxFQUFFLElBQUksbUJBQW1CLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNoSSxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxLQUFhO0lBQ2hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM3QixJQUFJLE9BQU8sS0FBSyxFQUFFO1FBQUUsT0FBTyw2QkFBNkIsQ0FBQztJQUN6RCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsR0FBRztRQUFFLE9BQU8sa0RBQWtELENBQUM7SUFDcEYsS0FBSyxNQUFNLEdBQUcsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUMzRCxJQUFJLEdBQUcsS0FBSyxHQUFHO1lBQUUsU0FBUztRQUMxQixJQUFJLEdBQUcsS0FBSyxFQUFFO1lBQUUsT0FBTyxrREFBa0QsQ0FBQztRQUMxRSxNQUFNLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDL0MsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNYLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBRSxDQUFDO2dCQUFFLE9BQU8sSUFBSSxHQUFHLCtCQUErQixDQUFDO1lBQ3hHLFNBQVM7UUFDWCxDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0MsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUSxJQUFJLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUUsQ0FBQztZQUFFLFNBQVM7UUFDekYsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsSUFBSSxHQUFHLEtBQUssU0FBUztZQUFFLE9BQU8sSUFBSSxHQUFHLG1FQUFtRSxDQUFDO0lBQzNHLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRCwrRkFBK0Y7QUFDL0YsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxVQUF3QixFQUN4QixPQUFlO0lBRWYsTUFBTSxJQUFJLEdBQXFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQzNGLE9BQU8sVUFBVTtTQUNkLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxXQUFXLElBQUksbUJBQW1CLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUN2RixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztBQUN6RCxDQUFDO0FBRUQsZ0VBQWdFO0FBQ2hFLE1BQU0sVUFBVSxrQkFBa0IsQ0FDaEMsVUFBdUgsRUFDdkgsT0FBZSxFQUNmLE1BQWtEO0lBRWxELE1BQU0sVUFBVSxHQUFHLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUNyRSxJQUFJLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3ZDLE9BQU8sVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxXQUFXLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksbUJBQW1CLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQy9JLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBBZHZpc29yeSBtYXRjaGluZzogZG9lcyBhIHB1Ymxpc2hlZCBhZHZpc29yeSdzIGBhZmZlY3RlZFJhbmdlYCBjb3ZlciBhIGdpdmVuXG4gKiB2ZXJzaW9uLCBhbmQgd2hpY2ggYWR2aXNvcmllcyBibG9jayBhIHJlc29sdXRpb24gdW5kZXIgdGhlIG9yZydzIHBvbGljeS5cbiAqXG4gKiBUaGUgcmFuZ2UgZ3JhbW1hciBpcyBucG0tc3R5bGUgYW5kIGRlbGliZXJhdGVseSByZS1pbXBsZW1lbnRlZCBoZXJlIHJhdGhlclxuICogdGhhbiBwdWxsZWQgZnJvbSBgc2VtdmVyYDogYWR2aXNvcnkgcmFuZ2VzIGFyZSBPUEVSQVRPUiBTRVRTXG4gKiAoYD49MS4wLjAgPDEuMi4zYCwgYDEuMC4wIC0gMS4yLjBgLCBgXjEuMmAsIGAxLnhgLCBgfHxgKSwgYSBkaWZmZXJlbnQgc2hhcGVcbiAqIGZyb20gdGhlIGluc3RhbGwvcmVmZXJlbmNlIHZlcnNpb24gU1BFQ1MgaW4gLi9zZW12ZXItcmFuZ2UudHMuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBDb25zdW1wdGlvblBvbGljeSB9IGZyb20gJy4vcGx1Z2luLWNvbnN1bXB0aW9uLXBvbGljeS5qcyc7XG5pbXBvcnQgeyBjb21wYXJlU2VtdmVyLCBwYXJzZVNlbXZlciwgcGFyc2VWZXJzaW9uU3BlYywgc2F0aXNmaWVzVmVyc2lvblNwZWMgfSBmcm9tICcuL3NlbXZlci1yYW5nZS5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIEFkdmlzb3J5U2V2ZXJpdHksXG4gIEJsb2NrT25BZHZpc29yeSxcbiAgUGx1Z2luQWR2aXNvcnksXG59IGZyb20gJy4uL2RhdGFiYXNlL2RyaXp6bGUtc2NoZW1hLmpzJztcblxuXG4vKiogU2V2ZXJpdGllcyBlYWNoIGBibG9ja09uQWR2aXNvcnlgIHNldHRpbmcgYmxvY2tzLiAqL1xuZXhwb3J0IGNvbnN0IEFEVklTT1JZX0JMT0NLX1NFVkVSSVRJRVM6IFJlYWRvbmx5PFJlY29yZDxCbG9ja09uQWR2aXNvcnksIHJlYWRvbmx5IEFkdmlzb3J5U2V2ZXJpdHlbXT4+ID0ge1xuICBjcml0aWNhbDogWydjcml0aWNhbCddLFxuICBoaWdoOiBbJ2NyaXRpY2FsJywgJ2hpZ2gnXSxcbiAgbmV2ZXI6IFtdLFxufTtcblxuY29uc3QgQ09NUEFSQVRPUiA9IC9eKD49fDw9fD58PHw9KT9cXHMqdj8oXFxkK1xcLlxcZCtcXC5cXGQrKD86LVswLTlBLVphLXouLV0rKT8oPzpcXCtbMC05QS1aYS16Li1dKyk/KSQvO1xuXG4vKiogT25lIGNvbXBhcmF0b3Igc2V0IChgPj0xLjAuMCA8MS4yLjNgLCBgXjEuMmAsIGAxLnhgLCBgMS4wLjAgLSAxLjIuMGApIGFnYWluc3QgYHZlcnNpb25gLiAqL1xuZnVuY3Rpb24gY29tcGFyYXRvclNldENvdmVycyhzZXQ6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGh5cGhlbiA9IC9eKFxcUyspXFxzKy1cXHMrKFxcUyspJC8uZXhlYyhzZXQpO1xuICBpZiAoaHlwaGVuKSByZXR1cm4gY29tcGFyZVNlbXZlcih2ZXJzaW9uLCBoeXBoZW5bMV0hKSA+PSAwICYmIGNvbXBhcmVTZW12ZXIodmVyc2lvbiwgaHlwaGVuWzJdISkgPD0gMDtcbiAgY29uc3QgcGFydHMgPSBzZXQuc3BsaXQoL1xccysvKS5maWx0ZXIoQm9vbGVhbik7XG4gIGlmIChwYXJ0cy5sZW5ndGggPT09IDEgJiYgcGFyc2VWZXJzaW9uU3BlYyhwYXJ0c1swXSEpKSByZXR1cm4gc2F0aXNmaWVzVmVyc2lvblNwZWModmVyc2lvbiwgcGFydHNbMF0hKTtcbiAgcmV0dXJuIHBhcnRzLmV2ZXJ5KChwKSA9PiB7XG4gICAgY29uc3QgbSA9IENPTVBBUkFUT1IuZXhlYyhwKTtcbiAgICBpZiAoIW0pIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCBjID0gY29tcGFyZVNlbXZlcih2ZXJzaW9uLCBtWzJdISk7XG4gICAgc3dpdGNoIChtWzFdID8/ICc9Jykge1xuICAgICAgY2FzZSAnPj0nOiByZXR1cm4gYyA+PSAwO1xuICAgICAgY2FzZSAnPD0nOiByZXR1cm4gYyA8PSAwO1xuICAgICAgY2FzZSAnPic6IHJldHVybiBjID4gMDtcbiAgICAgIGNhc2UgJzwnOiByZXR1cm4gYyA8IDA7XG4gICAgICBkZWZhdWx0OiByZXR1cm4gYyA9PT0gMDtcbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gYWR2aXNvcnkncyBgYWZmZWN0ZWRSYW5nZWAgY292ZXJzIGB2ZXJzaW9uYDogYHx8YC1zZXBhcmF0ZWRcbiAqIGNvbXBhcmF0b3Igc2V0cywgZWFjaCBlaXRoZXIgdGhlIGxvb2t1cCBzcGVjIGZvcm1zIChgXmAsIGB+YCwgcGFydGlhbCxcbiAqIGV4YWN0KSBvciBzcGFjZS1zZXBhcmF0ZWQgY29tcGFyYXRvcnMgKGA+PTEuMC4wIDwxLjIuM2ApIG9yIGEgaHlwaGVuIHJhbmdlLlxuICogYCpgIGNvdmVycyBldmVyeXRoaW5nOyBhbiB1bnBhcnNlYWJsZSByYW5nZSBjb3ZlcnMgbm90aGluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkdmlzb3J5UmFuZ2VDb3ZlcnMocmFuZ2U6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGlmICghcGFyc2VTZW12ZXIodmVyc2lvbikpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHJhbmdlLnNwbGl0KCd8fCcpLm1hcCgocykgPT4gcy50cmltKCkpLnNvbWUoKHNldCkgPT4gc2V0ID09PSAnKicgfHwgKHNldCAhPT0gJycgJiYgY29tcGFyYXRvclNldENvdmVycyhzZXQsIHZlcnNpb24pKSk7XG59XG5cbi8qKlxuICogV2h5IGByYW5nZWAgaXNuJ3QgYSB1c2FibGUgYWR2aXNvcnkgcmFuZ2UgKHRoZSBmb3JtcyB7QGxpbmsgYWR2aXNvcnlSYW5nZUNvdmVyc31cbiAqIHVuZGVyc3RhbmRzKSwgb3IgbnVsbCB3aGVuIGl0IGlzLiBBbiBhZHZpc29yeSB3aG9zZSByYW5nZSBwYXJzZXMgYXMgbm90aGluZ1xuICogd291bGQgc2lsZW50bHkgY292ZXIgbm90aGluZywgc28gZHJhZnRzIGFyZSByZWZ1c2VkIGluc3RlYWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZHZpc29yeVJhbmdlUHJvYmxlbShyYW5nZTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IHRyaW1tZWQgPSByYW5nZS50cmltKCk7XG4gIGlmICh0cmltbWVkID09PSAnJykgcmV0dXJuICd0aGUgYWZmZWN0ZWQgcmFuZ2UgaXMgZW1wdHknO1xuICBpZiAodHJpbW1lZC5sZW5ndGggPiAyNTUpIHJldHVybiAndGhlIGFmZmVjdGVkIHJhbmdlIGlzIGxvbmdlciB0aGFuIDI1NSBjaGFyYWN0ZXJzJztcbiAgZm9yIChjb25zdCBzZXQgb2YgdHJpbW1lZC5zcGxpdCgnfHwnKS5tYXAoKHgpID0+IHgudHJpbSgpKSkge1xuICAgIGlmIChzZXQgPT09ICcqJykgY29udGludWU7XG4gICAgaWYgKHNldCA9PT0gJycpIHJldHVybiAndGhlIGFmZmVjdGVkIHJhbmdlIGhhcyBhbiBlbXB0eSBcInx8XCIgYWx0ZXJuYXRpdmUnO1xuICAgIGNvbnN0IGh5cGhlbiA9IC9eKFxcUyspXFxzKy1cXHMrKFxcUyspJC8uZXhlYyhzZXQpO1xuICAgIGlmIChoeXBoZW4pIHtcbiAgICAgIGlmICghcGFyc2VTZW12ZXIoaHlwaGVuWzFdISkgfHwgIXBhcnNlU2VtdmVyKGh5cGhlblsyXSEpKSByZXR1cm4gYFwiJHtzZXR9XCIgaXMgbm90IGEgdmFsaWQgaHlwaGVuIHJhbmdlYDtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBwYXJ0cyA9IHNldC5zcGxpdCgvXFxzKy8pLmZpbHRlcihCb29sZWFuKTtcbiAgICBpZiAocGFydHMubGVuZ3RoID09PSAxICYmIHBhcnRzWzBdICE9PSAnbGF0ZXN0JyAmJiBwYXJzZVZlcnNpb25TcGVjKHBhcnRzWzBdISkpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGJhZCA9IHBhcnRzLmZpbmQoKHgpID0+ICFDT01QQVJBVE9SLnRlc3QoeCkpO1xuICAgIGlmIChiYWQgIT09IHVuZGVmaW5lZCkgcmV0dXJuIGBcIiR7YmFkfVwiIGlzIG5vdCBhIHZlcnNpb24sIGEgXi9+IHJhbmdlIG9yIGEgY29tcGFyYXRvciAoPj0sIDw9LCA+LCA8LCA9KWA7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKiBUaGUgUFVCTElTSEVEIGFkdmlzb3JpZXMgd2hvc2UgcmFuZ2UgY292ZXJzIGB2ZXJzaW9uYCAoYW55IHNldmVyaXR5KSwgbW9zdCBzZXZlcmUgZmlyc3QuICovXG5leHBvcnQgZnVuY3Rpb24gYWR2aXNvcmllc0NvdmVyaW5nPEEgZXh0ZW5kcyBQaWNrPFBsdWdpbkFkdmlzb3J5LCAnc2V2ZXJpdHknIHwgJ3N0YXRlJyB8ICdhZmZlY3RlZFJhbmdlJz4+KFxuICBhZHZpc29yaWVzOiByZWFkb25seSBBW10sXG4gIHZlcnNpb246IHN0cmluZyxcbik6IEFbXSB7XG4gIGNvbnN0IHJhbms6IFJlY29yZDxBZHZpc29yeVNldmVyaXR5LCBudW1iZXI+ID0geyBjcml0aWNhbDogMCwgaGlnaDogMSwgbWVkaXVtOiAyLCBsb3c6IDMgfTtcbiAgcmV0dXJuIGFkdmlzb3JpZXNcbiAgICAuZmlsdGVyKChhKSA9PiBhLnN0YXRlID09PSAncHVibGlzaGVkJyAmJiBhZHZpc29yeVJhbmdlQ292ZXJzKGEuYWZmZWN0ZWRSYW5nZSwgdmVyc2lvbikpXG4gICAgLnNvcnQoKGEsIGIpID0+IHJhbmtbYS5zZXZlcml0eV0gLSByYW5rW2Iuc2V2ZXJpdHldKTtcbn1cblxuLyoqIFRoZSBQVUJMSVNIRUQgYWR2aXNvcmllcyB0aGUgcG9saWN5IGJsb2NrcyBgdmVyc2lvbmAgZm9yLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJsb2NraW5nQWR2aXNvcmllcyhcbiAgYWR2aXNvcmllczogcmVhZG9ubHkgUGljazxQbHVnaW5BZHZpc29yeSwgJ2lkJyB8ICdzZXZlcml0eScgfCAnc3RhdGUnIHwgJ2FmZmVjdGVkUmFuZ2UnIHwgJ2ZpeGVkVmVyc2lvbicgfCAnc3VtbWFyeSc+W10sXG4gIHZlcnNpb246IHN0cmluZyxcbiAgcG9saWN5OiBQaWNrPENvbnN1bXB0aW9uUG9saWN5LCAnYmxvY2tPbkFkdmlzb3J5Jz4sXG4pOiBBcnJheTxQaWNrPFBsdWdpbkFkdmlzb3J5LCAnaWQnIHwgJ3NldmVyaXR5JyB8ICdzdGF0ZScgfCAnYWZmZWN0ZWRSYW5nZScgfCAnZml4ZWRWZXJzaW9uJyB8ICdzdW1tYXJ5Jz4+IHtcbiAgY29uc3Qgc2V2ZXJpdGllcyA9IEFEVklTT1JZX0JMT0NLX1NFVkVSSVRJRVNbcG9saWN5LmJsb2NrT25BZHZpc29yeV07XG4gIGlmIChzZXZlcml0aWVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xuICByZXR1cm4gYWR2aXNvcmllcy5maWx0ZXIoKGEpID0+IGEuc3RhdGUgPT09ICdwdWJsaXNoZWQnICYmIHNldmVyaXRpZXMuaW5jbHVkZXMoYS5zZXZlcml0eSkgJiYgYWR2aXNvcnlSYW5nZUNvdmVycyhhLmFmZmVjdGVkUmFuZ2UsIHZlcnNpb24pKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An org's plugin CONSUMPTION POLICY: which publisher tiers it trusts, which
|
|
3
|
+
* listings it blocks, which advisory severities block a resolution, and which
|
|
4
|
+
* tiers may receive secrets. Applied at every resolution (see
|
|
5
|
+
* ./plugin-resolution.ts) and edited through the org's policy row.
|
|
6
|
+
*
|
|
7
|
+
* Pure functions over the stored row — no I/O — so the same rules run in the
|
|
8
|
+
* resolver, in the policy-update route, and in tests.
|
|
9
|
+
*/
|
|
10
|
+
import { type BlockedListingRef, type BlockOnAdvisory, type OfficialInstalls, type PluginInstallPolicy, type PublisherTier } from '../database/drizzle-schema.js';
|
|
11
|
+
/** An org's consumption policy, as the resolver applies it. */
|
|
12
|
+
export interface ConsumptionPolicy {
|
|
13
|
+
allowedTiers: PublisherTier[];
|
|
14
|
+
requireApprovalTiers: PublisherTier[];
|
|
15
|
+
secretsAllowedTiers: PublisherTier[];
|
|
16
|
+
blockOnAdvisory: BlockOnAdvisory;
|
|
17
|
+
officialInstalls: OfficialInstalls;
|
|
18
|
+
blockedListings: BlockedListingRef[];
|
|
19
|
+
}
|
|
20
|
+
/** The defaults (and the column defaults of `plugin_install_policies`). */
|
|
21
|
+
export declare const DEFAULT_CONSUMPTION_POLICY: Readonly<ConsumptionPolicy>;
|
|
22
|
+
/** At most this many blocked listings per policy. */
|
|
23
|
+
export declare const MAX_BLOCKED_LISTINGS = 500;
|
|
24
|
+
/** A stored policy row (or none) as a {@link ConsumptionPolicy}. */
|
|
25
|
+
export declare function policyOf(row: Partial<PluginInstallPolicy> | null | undefined): ConsumptionPolicy;
|
|
26
|
+
/**
|
|
27
|
+
* A team's policy under its root org's: each field takes the STRICTER of
|
|
28
|
+
* the two, so a team can narrow what its root allows but never widen it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function mergeConsumptionPolicies(root: ConsumptionPolicy, team: ConsumptionPolicy): ConsumptionPolicy;
|
|
31
|
+
/**
|
|
32
|
+
* The policy an org's resolution runs under. A root org: its own row (or the
|
|
33
|
+
* defaults). A team (`rootOrgId` set): its root's policy, merged with the
|
|
34
|
+
* team's own row when it has one.
|
|
35
|
+
*/
|
|
36
|
+
export declare function effectiveConsumptionPolicy(rows: ReadonlyArray<Partial<PluginInstallPolicy> & {
|
|
37
|
+
orgId?: string;
|
|
38
|
+
}>, orgId: string, rootOrgId?: string): ConsumptionPolicy;
|
|
39
|
+
/**
|
|
40
|
+
* Validate a (partial) policy update over `base`. Returns the full new policy,
|
|
41
|
+
* or an error message. `blockedListings` entries are `{ publisher, name }` or
|
|
42
|
+
* `"publisher/name"`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function applyPolicyUpdate(base: ConsumptionPolicy, input: unknown): ConsumptionPolicy | string;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* An org's plugin CONSUMPTION POLICY: which publisher tiers it trusts, which
|
|
5
|
+
* listings it blocks, which advisory severities block a resolution, and which
|
|
6
|
+
* tiers may receive secrets. Applied at every resolution (see
|
|
7
|
+
* ./plugin-resolution.ts) and edited through the org's policy row.
|
|
8
|
+
*
|
|
9
|
+
* Pure functions over the stored row — no I/O — so the same rules run in the
|
|
10
|
+
* resolver, in the policy-update route, and in tests.
|
|
11
|
+
*/
|
|
12
|
+
import { PUBLISHER_TIERS, } from '../database/drizzle-schema.js';
|
|
13
|
+
/** The defaults (and the column defaults of `plugin_install_policies`). */
|
|
14
|
+
export const DEFAULT_CONSUMPTION_POLICY = Object.freeze({
|
|
15
|
+
allowedTiers: ['official', 'verified'],
|
|
16
|
+
requireApprovalTiers: ['community', 'unverified'],
|
|
17
|
+
secretsAllowedTiers: ['official', 'verified'],
|
|
18
|
+
blockOnAdvisory: 'critical',
|
|
19
|
+
officialInstalls: 'implicit',
|
|
20
|
+
blockedListings: [],
|
|
21
|
+
});
|
|
22
|
+
/** At most this many blocked listings per policy. */
|
|
23
|
+
export const MAX_BLOCKED_LISTINGS = 500;
|
|
24
|
+
const BLOCK_ORDER = ['never', 'critical', 'high'];
|
|
25
|
+
const sortTiers = (tiers) => PUBLISHER_TIERS.filter((t) => new Set(tiers).has(t));
|
|
26
|
+
const listingKey = (r) => `${r.publisher}/${r.name}`;
|
|
27
|
+
function uniqueListings(refs) {
|
|
28
|
+
const seen = new Map();
|
|
29
|
+
for (const r of refs)
|
|
30
|
+
seen.set(listingKey(r), { publisher: r.publisher, name: r.name });
|
|
31
|
+
return [...seen.values()].sort((a, b) => listingKey(a).localeCompare(listingKey(b)));
|
|
32
|
+
}
|
|
33
|
+
/** A stored policy row (or none) as a {@link ConsumptionPolicy}. */
|
|
34
|
+
export function policyOf(row) {
|
|
35
|
+
const d = DEFAULT_CONSUMPTION_POLICY;
|
|
36
|
+
return {
|
|
37
|
+
allowedTiers: sortTiers(row?.allowedTiers ?? d.allowedTiers),
|
|
38
|
+
requireApprovalTiers: sortTiers(row?.requireApprovalTiers ?? d.requireApprovalTiers),
|
|
39
|
+
secretsAllowedTiers: sortTiers(row?.secretsAllowedTiers ?? d.secretsAllowedTiers),
|
|
40
|
+
blockOnAdvisory: row?.blockOnAdvisory ?? d.blockOnAdvisory,
|
|
41
|
+
officialInstalls: row?.officialInstalls ?? d.officialInstalls,
|
|
42
|
+
blockedListings: uniqueListings(row?.blockedListings ?? d.blockedListings),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A team's policy under its root org's: each field takes the STRICTER of
|
|
47
|
+
* the two, so a team can narrow what its root allows but never widen it.
|
|
48
|
+
*/
|
|
49
|
+
export function mergeConsumptionPolicies(root, team) {
|
|
50
|
+
const intersect = (a, b) => sortTiers(a.filter((t) => b.includes(t)));
|
|
51
|
+
const union = (a, b) => sortTiers([...a, ...b]);
|
|
52
|
+
const stricterBlock = BLOCK_ORDER.indexOf(root.blockOnAdvisory) >= BLOCK_ORDER.indexOf(team.blockOnAdvisory)
|
|
53
|
+
? root.blockOnAdvisory : team.blockOnAdvisory;
|
|
54
|
+
return {
|
|
55
|
+
allowedTiers: intersect(root.allowedTiers, team.allowedTiers),
|
|
56
|
+
requireApprovalTiers: union(root.requireApprovalTiers, team.requireApprovalTiers),
|
|
57
|
+
secretsAllowedTiers: intersect(root.secretsAllowedTiers, team.secretsAllowedTiers),
|
|
58
|
+
blockOnAdvisory: stricterBlock,
|
|
59
|
+
officialInstalls: root.officialInstalls === 'explicit' || team.officialInstalls === 'explicit' ? 'explicit' : 'implicit',
|
|
60
|
+
blockedListings: uniqueListings([...root.blockedListings, ...team.blockedListings]),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The policy an org's resolution runs under. A root org: its own row (or the
|
|
65
|
+
* defaults). A team (`rootOrgId` set): its root's policy, merged with the
|
|
66
|
+
* team's own row when it has one.
|
|
67
|
+
*/
|
|
68
|
+
export function effectiveConsumptionPolicy(rows, orgId, rootOrgId) {
|
|
69
|
+
const own = rows.find((r) => r.orgId === orgId) ?? null;
|
|
70
|
+
if (!rootOrgId || rootOrgId === orgId)
|
|
71
|
+
return policyOf(own);
|
|
72
|
+
const root = policyOf(rows.find((r) => r.orgId === rootOrgId) ?? null);
|
|
73
|
+
return own ? mergeConsumptionPolicies(root, policyOf(own)) : root;
|
|
74
|
+
}
|
|
75
|
+
const HANDLE_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
76
|
+
const NAME_RE = /^[a-z0-9][a-z0-9._-]*$/;
|
|
77
|
+
function tierList(v, field) {
|
|
78
|
+
if (!Array.isArray(v))
|
|
79
|
+
return `${field} must be an array of tiers`;
|
|
80
|
+
const bad = v.filter((t) => !PUBLISHER_TIERS.includes(t));
|
|
81
|
+
if (bad.length)
|
|
82
|
+
return `${field} has unknown tiers: ${bad.map(String).join(', ')}`;
|
|
83
|
+
return sortTiers(v);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validate a (partial) policy update over `base`. Returns the full new policy,
|
|
87
|
+
* or an error message. `blockedListings` entries are `{ publisher, name }` or
|
|
88
|
+
* `"publisher/name"`.
|
|
89
|
+
*/
|
|
90
|
+
export function applyPolicyUpdate(base, input) {
|
|
91
|
+
if (!input || typeof input !== 'object' || Array.isArray(input))
|
|
92
|
+
return 'body must be an object';
|
|
93
|
+
const b = input;
|
|
94
|
+
const next = { ...base };
|
|
95
|
+
for (const field of ['allowedTiers', 'requireApprovalTiers', 'secretsAllowedTiers']) {
|
|
96
|
+
if (b[field] === undefined)
|
|
97
|
+
continue;
|
|
98
|
+
const tiers = tierList(b[field], field);
|
|
99
|
+
if (typeof tiers === 'string')
|
|
100
|
+
return tiers;
|
|
101
|
+
next[field] = tiers;
|
|
102
|
+
}
|
|
103
|
+
if (b.blockOnAdvisory !== undefined) {
|
|
104
|
+
if (!BLOCK_ORDER.includes(b.blockOnAdvisory))
|
|
105
|
+
return 'blockOnAdvisory must be critical, high or never';
|
|
106
|
+
next.blockOnAdvisory = b.blockOnAdvisory;
|
|
107
|
+
}
|
|
108
|
+
if (b.officialInstalls !== undefined) {
|
|
109
|
+
if (b.officialInstalls !== 'implicit' && b.officialInstalls !== 'explicit')
|
|
110
|
+
return 'officialInstalls must be implicit or explicit';
|
|
111
|
+
next.officialInstalls = b.officialInstalls;
|
|
112
|
+
}
|
|
113
|
+
if (b.blockedListings !== undefined) {
|
|
114
|
+
if (!Array.isArray(b.blockedListings))
|
|
115
|
+
return 'blockedListings must be an array';
|
|
116
|
+
if (b.blockedListings.length > MAX_BLOCKED_LISTINGS)
|
|
117
|
+
return `at most ${MAX_BLOCKED_LISTINGS} blocked listings`;
|
|
118
|
+
const refs = [];
|
|
119
|
+
for (const raw of b.blockedListings) {
|
|
120
|
+
const ref = typeof raw === 'string'
|
|
121
|
+
? (() => { const [publisher, name, extra] = raw.split('/'); return extra === undefined ? { publisher, name } : null; })()
|
|
122
|
+
: raw && typeof raw === 'object' ? { publisher: raw.publisher, name: raw.name } : null;
|
|
123
|
+
if (!ref || typeof ref.publisher !== 'string' || typeof ref.name !== 'string'
|
|
124
|
+
|| !HANDLE_RE.test(ref.publisher) || !NAME_RE.test(ref.name)) {
|
|
125
|
+
return 'each blocked listing must be { publisher, name } (or "publisher/name")';
|
|
126
|
+
}
|
|
127
|
+
refs.push({ publisher: ref.publisher, name: ref.name });
|
|
128
|
+
}
|
|
129
|
+
next.blockedListings = uniqueListings(refs);
|
|
130
|
+
}
|
|
131
|
+
return next;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWNvbnN1bXB0aW9uLXBvbGljeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvcGx1Z2luLWNvbnN1bXB0aW9uLXBvbGljeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDOzs7Ozs7OztHQVFHO0FBRUgsT0FBTyxFQU1MLGVBQWUsR0FDaEIsTUFBTSwrQkFBK0IsQ0FBQztBQWF2QywyRUFBMkU7QUFDM0UsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQWdDLE1BQU0sQ0FBQyxNQUFNLENBQW9CO0lBQ3RHLFlBQVksRUFBRSxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUM7SUFDdEMsb0JBQW9CLEVBQUUsQ0FBQyxXQUFXLEVBQUUsWUFBWSxDQUFDO0lBQ2pELG1CQUFtQixFQUFFLENBQUMsVUFBVSxFQUFFLFVBQVUsQ0FBQztJQUM3QyxlQUFlLEVBQUUsVUFBVTtJQUMzQixnQkFBZ0IsRUFBRSxVQUFVO0lBQzVCLGVBQWUsRUFBRSxFQUFFO0NBQ3BCLENBQUMsQ0FBQztBQUVILHFEQUFxRDtBQUNyRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxHQUFHLENBQUM7QUFFeEMsTUFBTSxXQUFXLEdBQStCLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUU5RSxNQUFNLFNBQVMsR0FBRyxDQUFDLEtBQThCLEVBQW1CLEVBQUUsQ0FDcEUsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFdkQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxDQUFvQixFQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0FBRWhGLFNBQVMsY0FBYyxDQUFDLElB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QUFLLFFBQVE7bUJBQ3hFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUMvRCxPQUFPLHdFQUF3RSxDQUFDO1lBQ2xGLENBQUM7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzFELENBQUM7UUFDRCxJQUFJLENBQUMsZUFBZSxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogQW4gb3JnJ3MgcGx1Z2luIENPTlNVTVBUSU9OIFBPTElDWTogd2hpY2ggcHVibGlzaGVyIHRpZXJzIGl0IHRydXN0cywgd2hpY2hcbiAqIGxpc3RpbmdzIGl0IGJsb2Nrcywgd2hpY2ggYWR2aXNvcnkgc2V2ZXJpdGllcyBibG9jayBhIHJlc29sdXRpb24sIGFuZCB3aGljaFxuICogdGllcnMgbWF5IHJlY2VpdmUgc2VjcmV0cy4gQXBwbGllZCBhdCBldmVyeSByZXNvbHV0aW9uIChzZWVcbiAqIC4vcGx1Z2luLXJlc29sdXRpb24udHMpIGFuZCBlZGl0ZWQgdGhyb3VnaCB0aGUgb3JnJ3MgcG9saWN5IHJvdy5cbiAqXG4gKiBQdXJlIGZ1bmN0aW9ucyBvdmVyIHRoZSBzdG9yZWQgcm93IOKAlCBubyBJL08g4oCUIHNvIHRoZSBzYW1lIHJ1bGVzIHJ1biBpbiB0aGVcbiAqIHJlc29sdmVyLCBpbiB0aGUgcG9saWN5LXVwZGF0ZSByb3V0ZSwgYW5kIGluIHRlc3RzLlxuICovXG5cbmltcG9ydCB7XG4gIHR5cGUgQmxvY2tlZExpc3RpbmdSZWYsXG4gIHR5cGUgQmxvY2tPbkFkdmlzb3J5LFxuICB0eXBlIE9mZmljaWFsSW5zdGFsbHMsXG4gIHR5cGUgUGx1Z2luSW5zdGFsbFBvbGljeSxcbiAgdHlwZSBQdWJsaXNoZXJUaWVyLFxuICBQVUJMSVNIRVJfVElFUlMsXG59IGZyb20gJy4uL2RhdGFiYXNlL2RyaXp6bGUtc2NoZW1hLmpzJztcblxuXG4vKiogQW4gb3JnJ3MgY29uc3VtcHRpb24gcG9saWN5LCBhcyB0aGUgcmVzb2x2ZXIgYXBwbGllcyBpdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29uc3VtcHRpb25Qb2xpY3kge1xuICBhbGxvd2VkVGllcnM6IFB1Ymxpc2hlclRpZXJbXTtcbiAgcmVxdWlyZUFwcHJvdmFsVGllcnM6IFB1Ymxpc2hlclRpZXJbXTtcbiAgc2VjcmV0c0FsbG93ZWRUaWVyczogUHVibGlzaGVyVGllcltdO1xuICBibG9ja09uQWR2aXNvcnk6IEJsb2NrT25BZHZpc29yeTtcbiAgb2ZmaWNpYWxJbnN0YWxsczogT2ZmaWNpYWxJbnN0YWxscztcbiAgYmxvY2tlZExpc3RpbmdzOiBCbG9ja2VkTGlzdGluZ1JlZltdO1xufVxuXG4vKiogVGhlIGRlZmF1bHRzIChhbmQgdGhlIGNvbHVtbiBkZWZhdWx0cyBvZiBgcGx1Z2luX2luc3RhbGxfcG9saWNpZXNgKS4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0NPTlNVTVBUSU9OX1BPTElDWTogUmVhZG9ubHk8Q29uc3VtcHRpb25Qb2xpY3k+ID0gT2JqZWN0LmZyZWV6ZTxDb25zdW1wdGlvblBvbGljeT4oe1xuICBhbGxvd2VkVGllcnM6IFsnb2ZmaWNpYWwnLCAndmVyaWZpZWQnXSxcbiAgcmVxdWlyZUFwcHJvdmFsVGllcnM6IFsnY29tbXVuaXR5JywgJ3VudmVyaWZpZWQnXSxcbiAgc2VjcmV0c0FsbG93ZWRUaWVyczogWydvZmZpY2lhbCcsICd2ZXJpZmllZCddLFxuICBibG9ja09uQWR2aXNvcnk6ICdjcml0aWNhbCcsXG4gIG9mZmljaWFsSW5zdGFsbHM6ICdpbXBsaWNpdCcsXG4gIGJsb2NrZWRMaXN0aW5nczogW10sXG59KTtcblxuLyoqIEF0IG1vc3QgdGhpcyBtYW55IGJsb2NrZWQgbGlzdGluZ3MgcGVyIHBvbGljeS4gKi9cbmV4cG9ydCBjb25zdCBNQVhfQkxPQ0tFRF9MSVNUSU5HUyA9IDUwMDtcblxuY29uc3QgQkxPQ0tfT1JERVI6IHJlYWRvbmx5IEJsb2NrT25BZHZpc29yeVtdID0gWyduZXZlcicsICdjcml0aWNhbCcsICdoaWdoJ107XG5cbmNvbnN0IHNvcnRUaWVycyA9ICh0aWVyczogSXRlcmFibGU8UHVibGlzaGVyVGllcj4pOiBQdWJsaXNoZXJUaWVyW10gPT5cbiAgUFVCTElTSEVSX1RJRVJTLmZpbHRlcigodCkgPT4gbmV3IFNldCh0aWVycykuaGFzKHQpKTtcblxuY29uc3QgbGlzdGluZ0tleSA9IChyOiBCbG9ja2VkTGlzdGluZ1JlZik6IHN0cmluZyA9PiBgJHtyLnB1Ymxpc2hlcn0vJHtyLm5hbWV9YDtcblxuZnVuY3Rpb24gdW5pcXVlTGlzdGluZ3MocmVmczogcmVhZG9ubHkgQmxvY2tlZExpc3RpbmdSZWZbXSk6IEJsb2NrZWRMaXN0aW5nUmVmW10ge1xuICBjb25zdCBzZWVuID0gbmV3IE1hcDxzdHJpbmcsIEJsb2NrZWRMaXN0aW5nUmVmPigpO1xuICBmb3IgKGNvbnN0IHIgb2YgcmVmcykgc2Vlbi5zZXQobGlzdGluZ0tleShyKSwgeyBwdWJsaXNoZXI6IHIucHVibGlzaGVyLCBuYW1lOiByLm5hbWUgfSk7XG4gIHJldHVybiBbLi4uc2Vlbi52YWx1ZXMoKV0uc29ydCgoYSwgYikgPT4gbGlzdGluZ0tleShhKS5sb2NhbGVDb21wYXJlKGxpc3RpbmdLZXkoYikpKTtcbn1cblxuLyoqIEEgc3RvcmVkIHBvbGljeSByb3cgKG9yIG5vbmUpIGFzIGEge0BsaW5rIENvbnN1bXB0aW9uUG9saWN5fS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwb2xpY3lPZihyb3c6IFBhcnRpYWw8UGx1Z2luSW5zdGFsbFBvbGljeT4gfCBudWxsIHwgdW5kZWZpbmVkKTogQ29uc3VtcHRpb25Qb2xpY3kge1xuICBjb25zdCBkID0gREVGQVVMVF9DT05TVU1QVElPTl9QT0xJQ1k7XG4gIHJldHVybiB7XG4gICAgYWxsb3dlZFRpZXJzOiBzb3J0VGllcnMocm93Py5hbGxvd2VkVGllcnMgPz8gZC5hbGxvd2VkVGllcnMpLFxuICAgIHJlcXVpcmVBcHByb3ZhbFRpZXJzOiBzb3J0VGllcnMocm93Py5yZXF1aXJlQXBwcm92YWxUaWVycyA/PyBkLnJlcXVpcmVBcHByb3ZhbFRpZXJzKSxcbiAgICBzZWNyZXRzQWxsb3dlZFRpZXJzOiBzb3J0VGllcnMocm93Py5zZWNyZXRzQWxsb3dlZFRpZXJzID8/IGQuc2VjcmV0c0FsbG93ZWRUaWVycyksXG4gICAgYmxvY2tPbkFkdmlzb3J5OiByb3c/LmJsb2NrT25BZHZpc29yeSA/PyBkLmJsb2NrT25BZHZpc29yeSxcbiAgICBvZmZpY2lhbEluc3RhbGxzOiByb3c/Lm9mZmljaWFsSW5zdGFsbHMgPz8gZC5vZmZpY2lhbEluc3RhbGxzLFxuICAgIGJsb2NrZWRMaXN0aW5nczogdW5pcXVlTGlzdGluZ3Mocm93Py5ibG9ja2VkTGlzdGluZ3MgPz8gZC5ibG9ja2VkTGlzdGluZ3MpLFxuICB9O1xufVxuXG4vKipcbiAqIEEgdGVhbSdzIHBvbGljeSB1bmRlciBpdHMgcm9vdCBvcmcnczogZWFjaCBmaWVsZCB0YWtlcyB0aGUgU1RSSUNURVIgb2ZcbiAqIHRoZSB0d28sIHNvIGEgdGVhbSBjYW4gbmFycm93IHdoYXQgaXRzIHJvb3QgYWxsb3dzIGJ1dCBuZXZlciB3aWRlbiBpdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlQ29uc3VtcHRpb25Qb2xpY2llcyhyb290OiBDb25zdW1wdGlvblBvbGljeSwgdGVhbTogQ29uc3VtcHRpb25Qb2xpY3kpOiBDb25zdW1wdGlvblBvbGljeSB7XG4gIGNvbnN0IGludGVyc2VjdCA9IChhOiBQdWJsaXNoZXJUaWVyW10sIGI6IFB1Ymxpc2hlclRpZXJbXSkgPT4gc29ydFRpZXJzKGEuZmlsdGVyKCh0KSA9PiBiLmluY2x1ZGVzKHQpKSk7XG4gIGNvbnN0IHVuaW9uID0gKGE6IFB1Ymxpc2hlclRpZXJbXSwgYjogUHVibGlzaGVyVGllcltdKSA9PiBzb3J0VGllcnMoWy4uLmEsIC4uLmJdKTtcbiAgY29uc3Qgc3RyaWN0ZXJCbG9jayA9IEJMT0NLX09SREVSLmluZGV4T2Yocm9vdC5ibG9ja09uQWR2aXNvcnkpID49IEJMT0NLX09SREVSLmluZGV4T2YodGVhbS5ibG9ja09uQWR2aXNvcnkpXG4gICAgPyByb290LmJsb2NrT25BZHZpc29yeSA6IHRlYW0uYmxvY2tPbkFkdmlzb3J5O1xuICByZXR1cm4ge1xuICAgIGFsbG93ZWRUaWVyczogaW50ZXJzZWN0KHJvb3QuYWxsb3dlZFRpZXJzLCB0ZWFtLmFsbG93ZWRUaWVycyksXG4gICAgcmVxdWlyZUFwcHJvdmFsVGllcnM6IHVuaW9uKHJvb3QucmVxdWlyZUFwcHJvdmFsVGllcnMsIHRlYW0ucmVxdWlyZUFwcHJvdmFsVGllcnMpLFxuICAgIHNlY3JldHNBbGxvd2VkVGllcnM6IGludGVyc2VjdChyb290LnNlY3JldHNBbGxvd2VkVGllcnMsIHRlYW0uc2VjcmV0c0FsbG93ZWRUaWVycyksXG4gICAgYmxvY2tPbkFkdmlzb3J5OiBzdHJpY3RlckJsb2NrLFxuICAgIG9mZmljaWFsSW5zdGFsbHM6IHJvb3Qub2ZmaWNpYWxJbnN0YWxscyA9PT0gJ2V4cGxpY2l0JyB8fCB0ZWFtLm9mZmljaWFsSW5zdGFsbHMgPT09ICdleHBsaWNpdCcgPyAnZXhwbGljaXQnIDogJ2ltcGxpY2l0JyxcbiAgICBibG9ja2VkTGlzdGluZ3M6IHVuaXF1ZUxpc3RpbmdzKFsuLi5yb290LmJsb2NrZWRMaXN0aW5ncywgLi4udGVhbS5ibG9ja2VkTGlzdGluZ3NdKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBUaGUgcG9saWN5IGFuIG9yZydzIHJlc29sdXRpb24gcnVucyB1bmRlci4gQSByb290IG9yZzogaXRzIG93biByb3cgKG9yIHRoZVxuICogZGVmYXVsdHMpLiBBIHRlYW0gKGByb290T3JnSWRgIHNldCk6IGl0cyByb290J3MgcG9saWN5LCBtZXJnZWQgd2l0aCB0aGVcbiAqIHRlYW0ncyBvd24gcm93IHdoZW4gaXQgaGFzIG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVmZmVjdGl2ZUNvbnN1bXB0aW9uUG9saWN5KFxuICByb3dzOiBSZWFkb25seUFycmF5PFBhcnRpYWw8UGx1Z2luSW5zdGFsbFBvbGljeT4gJiB7IG9yZ0lkPzogc3RyaW5nIH0+LFxuICBvcmdJZDogc3RyaW5nLFxuICByb290T3JnSWQ/OiBzdHJpbmcsXG4pOiBDb25zdW1wdGlvblBvbGljeSB7XG4gIGNvbnN0IG93biA9IHJvd3MuZmluZCgocikgPT4gci5vcmdJZCA9PT0gb3JnSWQpID8/IG51bGw7XG4gIGlmICghcm9vdE9yZ0lkIHx8IHJvb3RPcmdJZCA9PT0gb3JnSWQpIHJldHVybiBwb2xpY3lPZihvd24pO1xuICBjb25zdCByb290ID0gcG9saWN5T2Yocm93cy5maW5kKChyKSA9PiByLm9yZ0lkID09PSByb290T3JnSWQpID8/IG51bGwpO1xuICByZXR1cm4gb3duID8gbWVyZ2VDb25zdW1wdGlvblBvbGljaWVzKHJvb3QsIHBvbGljeU9mKG93bikpIDogcm9vdDtcbn1cblxuY29uc3QgSEFORExFX1JFID0gL15bYS16MC05XSsoPzotW2EtejAtOV0rKSokLztcbmNvbnN0IE5BTUVfUkUgPSAvXlthLXowLTldW2EtejAtOS5fLV0qJC87XG5cbmZ1bmN0aW9uIHRpZXJMaXN0KHY6IHVua25vd24sIGZpZWxkOiBzdHJpbmcpOiBQdWJsaXNoZXJUaWVyW10gfCBzdHJpbmcge1xuICBpZiAoIUFycmF5LmlzQXJyYXkodikpIHJldHVybiBgJHtmaWVsZH0gbXVzdCBiZSBhbiBhcnJheSBvZiB0aWVyc2A7XG4gIGNvbnN0IGJhZCA9IHYuZmlsdGVyKCh0KSA9PiAhKFBVQkxJU0hFUl9USUVSUyBhcyByZWFkb25seSB1bmtub3duW10pLmluY2x1ZGVzKHQpKTtcbiAgaWYgKGJhZC5sZW5ndGgpIHJldHVybiBgJHtmaWVsZH0gaGFzIHVua25vd24gdGllcnM6ICR7YmFkLm1hcChTdHJpbmcpLmpvaW4oJywgJyl9YDtcbiAgcmV0dXJuIHNvcnRUaWVycyh2IGFzIFB1Ymxpc2hlclRpZXJbXSk7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgYSAocGFydGlhbCkgcG9saWN5IHVwZGF0ZSBvdmVyIGBiYXNlYC4gUmV0dXJucyB0aGUgZnVsbCBuZXcgcG9saWN5LFxuICogb3IgYW4gZXJyb3IgbWVzc2FnZS4gYGJsb2NrZWRMaXN0aW5nc2AgZW50cmllcyBhcmUgYHsgcHVibGlzaGVyLCBuYW1lIH1gIG9yXG4gKiBgXCJwdWJsaXNoZXIvbmFtZVwiYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UG9saWN5VXBkYXRlKGJhc2U6IENvbnN1bXB0aW9uUG9saWN5LCBpbnB1dDogdW5rbm93bik6IENvbnN1bXB0aW9uUG9saWN5IHwgc3RyaW5nIHtcbiAgaWYgKCFpbnB1dCB8fCB0eXBlb2YgaW5wdXQgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkoaW5wdXQpKSByZXR1cm4gJ2JvZHkgbXVzdCBiZSBhbiBvYmplY3QnO1xuICBjb25zdCBiID0gaW5wdXQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IG5leHQ6IENvbnN1bXB0aW9uUG9saWN5ID0geyAuLi5iYXNlIH07XG4gIGZvciAoY29uc3QgZmllbGQgb2YgWydhbGxvd2VkVGllcnMnLCAncmVxdWlyZUFwcHJvdmFsVGllcnMnLCAnc2VjcmV0c0FsbG93ZWRUaWVycyddIGFzIGNvbnN0KSB7XG4gICAgaWYgKGJbZmllbGRdID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgIGNvbnN0IHRpZXJzID0gdGllckxpc3QoYltmaWVsZF0sIGZpZWxkKTtcbiAgICBpZiAodHlwZW9mIHRpZXJzID09PSAnc3RyaW5nJykgcmV0dXJuIHRpZXJzO1xuICAgIG5leHRbZmllbGRdID0gdGllcnM7XG4gIH1cbiAgaWYgKGIuYmxvY2tPbkFkdmlzb3J5ICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoIUJMT0NLX09SREVSLmluY2x1ZGVzKGIuYmxvY2tPbkFkdmlzb3J5IGFzIEJsb2NrT25BZHZpc29yeSkpIHJldHVybiAnYmxvY2tPbkFkdmlzb3J5IG11c3QgYmUgY3JpdGljYWwsIGhpZ2ggb3IgbmV2ZXInO1xuICAgIG5leHQuYmxvY2tPbkFkdmlzb3J5ID0gYi5ibG9ja09uQWR2aXNvcnkgYXMgQmxvY2tPbkFkdmlzb3J5O1xuICB9XG4gIGlmIChiLm9mZmljaWFsSW5zdGFsbHMgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChiLm9mZmljaWFsSW5zdGFsbHMgIT09ICdpbXBsaWNpdCcgJiYgYi5vZmZpY2lhbEluc3RhbGxzICE9PSAnZXhwbGljaXQnKSByZXR1cm4gJ29mZmljaWFsSW5zdGFsbHMgbXVzdCBiZSBpbXBsaWNpdCBvciBleHBsaWNpdCc7XG4gICAgbmV4dC5vZmZpY2lhbEluc3RhbGxzID0gYi5vZmZpY2lhbEluc3RhbGxzO1xuICB9XG4gIGlmIChiLmJsb2NrZWRMaXN0aW5ncyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGIuYmxvY2tlZExpc3RpbmdzKSkgcmV0dXJuICdibG9ja2VkTGlzdGluZ3MgbXVzdCBiZSBhbiBhcnJheSc7XG4gICAgaWYgKGIuYmxvY2tlZExpc3RpbmdzLmxlbmd0aCA+IE1BWF9CTE9DS0VEX0xJU1RJTkdTKSByZXR1cm4gYGF0IG1vc3QgJHtNQVhfQkxPQ0tFRF9MSVNUSU5HU30gYmxvY2tlZCBsaXN0aW5nc2A7XG4gICAgY29uc3QgcmVmczogQmxvY2tlZExpc3RpbmdSZWZbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcmF3IG9mIGIuYmxvY2tlZExpc3RpbmdzKSB7XG4gICAgICBjb25zdCByZWYgPSB0eXBlb2YgcmF3ID09PSAnc3RyaW5nJ1xuICAgICAgICA/ICgoKSA9PiB7IGNvbnN0IFtwdWJsaXNoZXIsIG5hbWUsIGV4dHJhXSA9IHJhdy5zcGxpdCgnLycpOyByZXR1cm4gZXh0cmEgPT09IHVuZGVmaW5lZCA/IHsgcHVibGlzaGVyLCBuYW1lIH0gOiBudWxsOyB9KSgpXG4gICAgICAgIDogcmF3ICYmIHR5cGVvZiByYXcgPT09ICdvYmplY3QnID8geyBwdWJsaXNoZXI6IChyYXcgYXMgQmxvY2tlZExpc3RpbmdSZWYpLnB1Ymxpc2hlciwgbmFtZTogKHJhdyBhcyBCbG9ja2VkTGlzdGluZ1JlZikubmFtZSB9IDogbnVsbDtcbiAgICAgIGlmICghcmVmIHx8IHR5cGVvZiByZWYucHVibGlzaGVyICE9PSAnc3RyaW5nJyB8fCB0eXBlb2YgcmVmLm5hbWUgIT09ICdzdHJpbmcnXG4gICAgICAgIHx8ICFIQU5ETEVfUkUudGVzdChyZWYucHVibGlzaGVyKSB8fCAhTkFNRV9SRS50ZXN0KHJlZi5uYW1lKSkge1xuICAgICAgICByZXR1cm4gJ2VhY2ggYmxvY2tlZCBsaXN0aW5nIG11c3QgYmUgeyBwdWJsaXNoZXIsIG5hbWUgfSAob3IgXCJwdWJsaXNoZXIvbmFtZVwiKSc7XG4gICAgICB9XG4gICAgICByZWZzLnB1c2goeyBwdWJsaXNoZXI6IHJlZi5wdWJsaXNoZXIsIG5hbWU6IHJlZi5uYW1lIH0pO1xuICAgIH1cbiAgICBuZXh0LmJsb2NrZWRMaXN0aW5ncyA9IHVuaXF1ZUxpc3RpbmdzKHJlZnMpO1xuICB9XG4gIHJldHVybiBuZXh0O1xufVxuIl19
|
|
@@ -33,41 +33,8 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { type VulnFlaggedWarning } from '@pipeline-builder/api-core';
|
|
35
35
|
import type { CrudTx } from './crud-service.js';
|
|
36
|
-
import { type
|
|
37
|
-
|
|
38
|
-
export interface ConsumptionPolicy {
|
|
39
|
-
allowedTiers: PublisherTier[];
|
|
40
|
-
requireApprovalTiers: PublisherTier[];
|
|
41
|
-
secretsAllowedTiers: PublisherTier[];
|
|
42
|
-
blockOnAdvisory: BlockOnAdvisory;
|
|
43
|
-
officialInstalls: OfficialInstalls;
|
|
44
|
-
blockedListings: BlockedListingRef[];
|
|
45
|
-
}
|
|
46
|
-
/** The defaults (and the column defaults of `plugin_install_policies`). */
|
|
47
|
-
export declare const DEFAULT_CONSUMPTION_POLICY: Readonly<ConsumptionPolicy>;
|
|
48
|
-
/** At most this many blocked listings per policy. */
|
|
49
|
-
export declare const MAX_BLOCKED_LISTINGS = 500;
|
|
50
|
-
/** A stored policy row (or none) as a {@link ConsumptionPolicy}. */
|
|
51
|
-
export declare function policyOf(row: Partial<PluginInstallPolicy> | null | undefined): ConsumptionPolicy;
|
|
52
|
-
/**
|
|
53
|
-
* A team's policy under its root org's: each field takes the STRICTER of
|
|
54
|
-
* the two, so a team can narrow what its root allows but never widen it.
|
|
55
|
-
*/
|
|
56
|
-
export declare function mergeConsumptionPolicies(root: ConsumptionPolicy, team: ConsumptionPolicy): ConsumptionPolicy;
|
|
57
|
-
/**
|
|
58
|
-
* The policy an org's resolution runs under. A root org: its own row (or the
|
|
59
|
-
* defaults). A team (`rootOrgId` set): its root's policy, merged with the
|
|
60
|
-
* team's own row when it has one.
|
|
61
|
-
*/
|
|
62
|
-
export declare function effectiveConsumptionPolicy(rows: ReadonlyArray<Partial<PluginInstallPolicy> & {
|
|
63
|
-
orgId?: string;
|
|
64
|
-
}>, orgId: string, rootOrgId?: string): ConsumptionPolicy;
|
|
65
|
-
/**
|
|
66
|
-
* Validate a (partial) policy update over `base`. Returns the full new policy,
|
|
67
|
-
* or an error message. `blockedListings` entries are `{ publisher, name }` or
|
|
68
|
-
* `"publisher/name"`.
|
|
69
|
-
*/
|
|
70
|
-
export declare function applyPolicyUpdate(base: ConsumptionPolicy, input: unknown): ConsumptionPolicy | string;
|
|
36
|
+
import { type ConsumptionPolicy } from './plugin-consumption-policy.js';
|
|
37
|
+
import { type PluginAdvisory, type PluginInstall, type PluginInstallPolicy, type PluginListing, type PluginListingVersion, type Publisher } from '../database/drizzle-schema.js';
|
|
71
38
|
/** Why a reference can't resolve; `code` is an api-core `ErrorCode` name. */
|
|
72
39
|
export interface ResolutionRefusal {
|
|
73
40
|
code: 'NOT_FOUND' | 'PLUGIN_NOT_INSTALLED' | 'PLUGIN_BLOCKED_BY_POLICY' | 'PLUGIN_UNAVAILABLE' | 'PLUGIN_VERSION_VULN_BLOCKED';
|
|
@@ -89,25 +56,6 @@ export interface ListingBlock {
|
|
|
89
56
|
export declare function listingBlock(policy: ConsumptionPolicy, publisher: Pick<Publisher, 'handle' | 'tier' | 'suspendedAt'>, listing: Pick<PluginListing, 'name' | 'state'>): ListingBlock | null;
|
|
90
57
|
/** The refusal a {@link ListingBlock} becomes. */
|
|
91
58
|
export declare function blockRefusal(block: ListingBlock): ResolutionRefusal;
|
|
92
|
-
/** Severities each `blockOnAdvisory` setting blocks. */
|
|
93
|
-
export declare const ADVISORY_BLOCK_SEVERITIES: Readonly<Record<BlockOnAdvisory, readonly AdvisorySeverity[]>>;
|
|
94
|
-
/**
|
|
95
|
-
* Whether an advisory's `affectedRange` covers `version`: `||`-separated
|
|
96
|
-
* comparator sets, each either the lookup spec forms (`^`, `~`, partial,
|
|
97
|
-
* exact) or space-separated comparators (`>=1.0.0 <1.2.3`) or a hyphen range.
|
|
98
|
-
* `*` covers everything; an unparseable range covers nothing.
|
|
99
|
-
*/
|
|
100
|
-
export declare function advisoryRangeCovers(range: string, version: string): boolean;
|
|
101
|
-
/**
|
|
102
|
-
* Why `range` isn't a usable advisory range (the forms {@link advisoryRangeCovers}
|
|
103
|
-
* understands), or null when it is. An advisory whose range parses as nothing
|
|
104
|
-
* would silently cover nothing, so drafts are refused instead.
|
|
105
|
-
*/
|
|
106
|
-
export declare function advisoryRangeProblem(range: string): string | null;
|
|
107
|
-
/** The PUBLISHED advisories whose range covers `version` (any severity), most severe first. */
|
|
108
|
-
export declare function advisoriesCovering<A extends Pick<PluginAdvisory, 'severity' | 'state' | 'affectedRange'>>(advisories: readonly A[], version: string): A[];
|
|
109
|
-
/** The PUBLISHED advisories the policy blocks `version` for. */
|
|
110
|
-
export declare function blockingAdvisories(advisories: readonly Pick<PluginAdvisory, 'id' | 'severity' | 'state' | 'affectedRange' | 'fixedVersion' | 'summary'>[], version: string, policy: Pick<ConsumptionPolicy, 'blockOnAdvisory'>): Array<Pick<PluginAdvisory, 'id' | 'severity' | 'state' | 'affectedRange' | 'fixedVersion' | 'summary'>>;
|
|
111
59
|
/** How the org reaches a listing: an explicit install row, or the implicit Official one. */
|
|
112
60
|
export type InstallMode = {
|
|
113
61
|
kind: 'explicit';
|