@foss.global/codefeed 1.11.1 → 1.12.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/changelog.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-09-05 - 1.12.0
4
+
5
+ ### Features
6
+
7
+ - add read-only forge inventory scanner for Gitea and GitLab (forge-inventory)
8
+ - Add ForgeInventoryAdapter and ForgeInventoryScanner exports for bounded repository and namespace observations.
9
+ - Validate provider payloads, cursors, URLs, response budgets, aborts, and rate-limit metrics without leaking tokens or response bodies.
10
+ - Document scanner usage and add protocol fixture tests for Gitea and GitLab inventory behavior.
11
+ - Update @foss.global/interfaces to ^0.12.0 for inventory DTO support.
12
+
13
+ ### Fixes
14
+
15
+ - update package manager and development tooling dependencies (deps)
16
+ - Updated @git.zone/tsbundle to ^2.13.0
17
+ - Updated @git.zone/tsrun to ^2.0.6
18
+ - Updated @git.zone/tstest to ^4.0.0
19
+ - Updated @types/node to ^26.4.1
20
+ - Updated pnpm to 11.25.0
21
+ - correct default tag workflow repository URL and remove release job (ci)
22
+ - Set the computed repository URL to include the code.foss.global host.
23
+ - Remove the tag-triggered npm publish release job from the default tags workflow.
24
+
3
25
  ## 2026-07-21 - 1.11.1
4
26
 
5
27
  ### Fixes
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@foss.global/codefeed',
6
- version: '1.11.1',
6
+ version: '1.12.0',
7
7
  description: 'The @foss.global/codefeed module generates commit/activity feeds from forge providers including Gitea and GitManager.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHVIQUF1SDtDQUNySSxDQUFBIn0=
@@ -0,0 +1,45 @@
1
+ import * as plugins from './plugins.js';
2
+ export { ForgeInventoryError } from './forgeinventory.validation.js';
3
+ export interface IForgeInventoryOptions {
4
+ kind: 'gitea' | 'gitlab';
5
+ instanceId: string;
6
+ /** Instance root, including an optional deployment subpath. HTTPS is required. */
7
+ baseUrl: string;
8
+ /** Personal access token, retained only in this adapter's memory. */
9
+ token?: string;
10
+ pageSize?: number;
11
+ maxPages?: number;
12
+ requestTimeoutMs?: number;
13
+ maxResponseBytes?: number;
14
+ }
15
+ export interface IForgeInventoryRequest {
16
+ cursor?: string;
17
+ signal?: AbortSignal;
18
+ /** Optional lower response-body budget for this request. */
19
+ maxResponseBytes?: number;
20
+ }
21
+ export interface IForgeInventoryMetrics {
22
+ requests: number;
23
+ responseBytes: number;
24
+ rateLimitedRequests: number;
25
+ }
26
+ /** Read-only, caller-visible API observations. This adapter never claims admin completeness. */
27
+ export declare class ForgeInventoryAdapter {
28
+ #private;
29
+ constructor(optionsArg: IForgeInventoryOptions);
30
+ get instance(): plugins.fossInterfaces.data.IForgeInventoryInstance;
31
+ get metrics(): IForgeInventoryMetrics;
32
+ observation(startedAt: string): plugins.fossInterfaces.data.IForgeInventoryObservation;
33
+ listRepositories(requestArg?: IForgeInventoryRequest): Promise<plugins.fossInterfaces.data.IForgeInventoryPage<plugins.fossInterfaces.data.IForgeInventoryRepository>>;
34
+ /** Organizations/groups only. User namespaces are not enumerated by these endpoints. */
35
+ listNamespaces(requestArg?: IForgeInventoryRequest): Promise<plugins.fossInterfaces.data.IForgeInventoryPage<plugins.fossInterfaces.data.IForgeInventoryNamespace>>;
36
+ private identity;
37
+ private namespace;
38
+ private repository;
39
+ private url;
40
+ private cursor;
41
+ private continuation;
42
+ private page;
43
+ private next;
44
+ private request;
45
+ }
@@ -0,0 +1,318 @@
1
+ import * as plugins from './plugins.js';
2
+ import * as validation from './forgeinventory.validation.js';
3
+ export { ForgeInventoryError } from './forgeinventory.validation.js';
4
+ /** Read-only, caller-visible API observations. This adapter never claims admin completeness. */
5
+ export class ForgeInventoryAdapter {
6
+ #options;
7
+ #cursorKey = plugins.crypto.randomBytes(32);
8
+ #metrics = { requests: 0, responseBytes: 0, rateLimitedRequests: 0 };
9
+ constructor(optionsArg) {
10
+ const baseUrl = validation.httpUrl(optionsArg.baseUrl);
11
+ if (!baseUrl || !baseUrl.startsWith('https:') || !optionsArg.instanceId.trim() ||
12
+ !['gitea', 'gitlab'].includes(optionsArg.kind) ||
13
+ (optionsArg.token !== undefined && (!optionsArg.token || /[\s\u0000-\u001f\u007f]/.test(optionsArg.token)))) {
14
+ throw new validation.ForgeInventoryError('invalid-options');
15
+ }
16
+ this.#options = {
17
+ ...optionsArg,
18
+ baseUrl: baseUrl.replace(/\/$/, ''),
19
+ pageSize: optionsArg.pageSize ?? 50,
20
+ maxPages: optionsArg.maxPages ?? 1000,
21
+ requestTimeoutMs: optionsArg.requestTimeoutMs ?? 30_000,
22
+ maxResponseBytes: optionsArg.maxResponseBytes ?? 8 * 1024 * 1024,
23
+ };
24
+ for (const [name, maximum] of [
25
+ ['pageSize', 100], ['maxPages', 100_000], ['requestTimeoutMs', 300_000], ['maxResponseBytes', 64 * 1024 * 1024],
26
+ ]) {
27
+ const value = this.#options[name];
28
+ if (!Number.isSafeInteger(value) || value < 1 || value > maximum)
29
+ throw new validation.ForgeInventoryError('invalid-limits');
30
+ }
31
+ }
32
+ get instance() {
33
+ return { instanceId: this.#options.instanceId, kind: this.#options.kind, version: null };
34
+ }
35
+ get metrics() { return { ...this.#metrics }; }
36
+ observation(startedAt) {
37
+ return {
38
+ startedAt, finishedAt: new Date().toISOString(),
39
+ access: this.#options.token ? 'callerVisible' : 'publicOnly', consistency: { status: 'live' },
40
+ };
41
+ }
42
+ listRepositories(requestArg = {}) {
43
+ return this.page('repositories', (item) => this.repository(item), requestArg);
44
+ }
45
+ /** Organizations/groups only. User namespaces are not enumerated by these endpoints. */
46
+ listNamespaces(requestArg = {}) {
47
+ return this.page('namespaces', (item) => this.namespace(item), requestArg);
48
+ }
49
+ identity(idNamespace, value) {
50
+ const objectId = validation.decimal(value);
51
+ if (objectId === '0')
52
+ throw new validation.ForgeInventoryError('invalid-identity');
53
+ return { status: 'identified', ref: { instanceId: this.#options.instanceId, idNamespace, objectId, parentObjectId: null } };
54
+ }
55
+ namespace(itemArg) {
56
+ const item = validation.record(itemArg);
57
+ if (this.#options.kind === 'gitea') {
58
+ const pathSegments = validation.segments(item.name);
59
+ if (pathSegments.length !== 1)
60
+ throw new validation.ForgeInventoryError('invalid-organization-path');
61
+ return {
62
+ identity: this.identity('gitea.user.id', item.id), kind: 'organization', parent: null,
63
+ location: { pathSegments, webUrl: null },
64
+ visibility: validation.visibility(item.visibility === 'limited' ? 'internal' : item.visibility),
65
+ };
66
+ }
67
+ return {
68
+ identity: this.identity('gitlab.group.id', item.id), kind: 'group',
69
+ parent: item.parent_id === null ? null : item.parent_id === undefined
70
+ ? { status: 'unresolved', reason: 'Parent group was not exposed.' }
71
+ : this.identity('gitlab.group.id', item.parent_id),
72
+ location: { pathSegments: validation.segments(item.full_path), webUrl: validation.httpUrl(item.web_url) },
73
+ visibility: validation.visibility(item.visibility),
74
+ };
75
+ }
76
+ repository(itemArg) {
77
+ const item = validation.record(itemArg);
78
+ if (this.#options.kind === 'gitea') {
79
+ const owner = validation.record(item.owner);
80
+ const pathSegments = [...validation.segments(owner.login), ...validation.segments(item.name)];
81
+ if (pathSegments.length !== 2)
82
+ throw new validation.ForgeInventoryError('invalid-repository-path');
83
+ const privateRepo = validation.optionalBoolean(item.private);
84
+ const internalRepo = validation.optionalBoolean(item.internal);
85
+ return {
86
+ identity: this.identity('gitea.repository.id', item.id), namespace: this.identity('gitea.user.id', owner.id),
87
+ location: { pathSegments, webUrl: validation.httpUrl(item.html_url) },
88
+ description: validation.optionalString(item.description),
89
+ visibility: privateRepo === true ? 'private' : internalRepo === true ? 'internal' : privateRepo === false && internalRepo === false ? 'public' : null,
90
+ archived: validation.optionalBoolean(item.archived), defaultBranch: validation.optionalString(item.default_branch),
91
+ httpCloneUrl: validation.httpUrl(item.clone_url), sshCloneUrl: validation.sshUrl(item.ssh_url),
92
+ gitSizeBytes: validation.unknownSize('Gitea size is not a separate Git byte measurement.'),
93
+ };
94
+ }
95
+ const namespace = validation.record(item.namespace);
96
+ if (namespace.kind !== 'group' && namespace.kind !== 'user')
97
+ throw new validation.ForgeInventoryError('invalid-namespace-kind');
98
+ return {
99
+ identity: this.identity('gitlab.project.id', item.id),
100
+ namespace: this.identity(namespace.kind === 'group' ? 'gitlab.group.id' : 'gitlab.namespace.id', namespace.id),
101
+ location: { pathSegments: validation.segments(item.path_with_namespace), webUrl: validation.httpUrl(item.web_url) },
102
+ description: validation.optionalString(item.description), visibility: validation.visibility(item.visibility),
103
+ archived: validation.optionalBoolean(item.archived), defaultBranch: validation.optionalString(item.default_branch),
104
+ httpCloneUrl: validation.httpUrl(item.http_url_to_repo), sshCloneUrl: validation.sshUrl(item.ssh_url_to_repo),
105
+ gitSizeBytes: validation.gitlabSize(item.statistics),
106
+ };
107
+ }
108
+ url(state) {
109
+ const gitea = this.#options.kind === 'gitea';
110
+ const endpoint = state.collection === 'repositories' ? (gitea ? 'repos/search' : 'projects') : (gitea ? 'orgs' : 'groups');
111
+ const url = new URL(`${this.#options.baseUrl}/api/${gitea ? 'v1' : 'v4'}/${endpoint}`);
112
+ url.searchParams.set(gitea ? 'limit' : 'per_page', String(this.#options.pageSize));
113
+ if (gitea) {
114
+ url.searchParams.set('page', String(state.page));
115
+ if (state.collection === 'repositories') {
116
+ url.searchParams.set('sort', 'id');
117
+ url.searchParams.set('order', 'asc');
118
+ url.searchParams.set('private', 'true');
119
+ }
120
+ }
121
+ else {
122
+ url.searchParams.set('order_by', 'id');
123
+ url.searchParams.set('sort', 'asc');
124
+ if (state.collection === 'repositories') {
125
+ url.searchParams.set('pagination', 'keyset');
126
+ url.searchParams.set('statistics', 'true');
127
+ if (state.after)
128
+ url.searchParams.set('id_after', state.after);
129
+ }
130
+ else {
131
+ url.searchParams.set('all_available', 'true');
132
+ url.searchParams.set('page', String(state.page));
133
+ }
134
+ }
135
+ return url;
136
+ }
137
+ cursor(state) {
138
+ const payload = Buffer.from(JSON.stringify(state)).toString('base64url');
139
+ return `${payload}.${plugins.crypto.createHmac('sha256', this.#cursorKey).update(payload).digest('base64url')}`;
140
+ }
141
+ continuation(collection, cursor) {
142
+ if (cursor === undefined)
143
+ return { version: 1, collection, page: 1, after: null };
144
+ try {
145
+ if (cursor.length > 2048)
146
+ throw new Error();
147
+ const [payload, signature, extra] = cursor.split('.');
148
+ const expected = plugins.crypto.createHmac('sha256', this.#cursorKey).update(payload).digest('base64url');
149
+ if (extra !== undefined || !signature || signature.length !== expected.length ||
150
+ !plugins.crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)))
151
+ throw new Error();
152
+ const state = JSON.parse(Buffer.from(payload, 'base64url').toString());
153
+ if (state.version !== 1 || state.collection !== collection || !Number.isSafeInteger(state.page) ||
154
+ state.page < 2 || state.page > this.#options.maxPages ||
155
+ (state.after !== null && validation.decimal(state.after) !== state.after))
156
+ throw new Error();
157
+ return state;
158
+ }
159
+ catch {
160
+ throw new validation.ForgeInventoryError('invalid-cursor');
161
+ }
162
+ }
163
+ async page(collection, map, requestArg) {
164
+ const state = this.continuation(collection, requestArg.cursor);
165
+ const startedAt = new Date().toISOString();
166
+ const url = this.url(state);
167
+ const { body, headers } = await this.request(url, requestArg);
168
+ let rows = body;
169
+ if (this.#options.kind === 'gitea' && collection === 'repositories') {
170
+ const envelope = validation.record(body);
171
+ if (envelope.ok !== true)
172
+ throw new validation.ForgeInventoryError('search-not-successful');
173
+ rows = envelope.data;
174
+ }
175
+ if (!Array.isArray(rows) || rows.length > this.#options.pageSize)
176
+ throw new validation.ForgeInventoryError('invalid-page');
177
+ const items = rows.map(map);
178
+ let pagination;
179
+ try {
180
+ const next = this.next(state, url, headers, rows);
181
+ pagination = next === null ? { status: 'exhausted' } : state.page >= this.#options.maxPages
182
+ ? { status: 'incomplete', reason: 'Configured page limit reached.' }
183
+ : { status: 'more', cursor: this.cursor(next) };
184
+ }
185
+ catch {
186
+ pagination = { status: 'incomplete', reason: 'Invalid or inconsistent pagination metadata.' };
187
+ }
188
+ return { schemaVersion: 1, instance: this.instance, scope: { kind: 'instance' }, observation: this.observation(startedAt), items, pagination };
189
+ }
190
+ next(state, current, headers, rows) {
191
+ const keyset = this.#options.kind === 'gitlab' && state.collection === 'repositories';
192
+ let previousId = BigInt(state.after ?? '0');
193
+ if (keyset)
194
+ for (const row of rows) {
195
+ const id = BigInt(validation.decimal(validation.record(row).id));
196
+ if (id <= previousId)
197
+ throw new Error();
198
+ previousId = id;
199
+ }
200
+ const link = headers.get('link');
201
+ let nextUrl = null;
202
+ if (link !== null) {
203
+ if (link.length > 16_384)
204
+ throw new Error();
205
+ for (const entry of link.split(',')) {
206
+ const match = entry.trim().match(/^<([^<>]+)>;\s*rel="(next|prev|first|last)"$/);
207
+ if (!match)
208
+ throw new Error();
209
+ if (match[2] !== 'next')
210
+ continue;
211
+ if (nextUrl !== null)
212
+ throw new Error();
213
+ nextUrl = new URL(match[1], current);
214
+ if (nextUrl.origin !== current.origin || nextUrl.pathname !== current.pathname || nextUrl.username || nextUrl.password || nextUrl.hash)
215
+ throw new Error();
216
+ const expected = new URL(current);
217
+ const changing = keyset ? 'id_after' : 'page';
218
+ expected.searchParams.delete(changing);
219
+ const actual = new URL(nextUrl);
220
+ if (actual.searchParams.getAll(changing).length !== 1)
221
+ throw new Error();
222
+ actual.searchParams.delete(changing);
223
+ expected.searchParams.sort();
224
+ actual.searchParams.sort();
225
+ if (expected.search !== actual.search)
226
+ throw new Error();
227
+ }
228
+ }
229
+ const xNext = headers.get('x-next-page');
230
+ if (!keyset && xNext !== null && xNext !== '' && validation.decimal(xNext) !== String(state.page + 1))
231
+ throw new Error();
232
+ if (rows.length === 0) {
233
+ if (nextUrl || xNext)
234
+ throw new Error();
235
+ return null;
236
+ }
237
+ if (keyset) {
238
+ if (!nextUrl)
239
+ return null; // GitLab keyset exhaustion is signalled by no next Link.
240
+ const after = validation.decimal(nextUrl.searchParams.get('id_after'));
241
+ if (after !== previousId.toString())
242
+ throw new Error();
243
+ return { ...state, page: state.page + 1, after };
244
+ }
245
+ if (nextUrl && validation.decimal(nextUrl.searchParams.get('page')) !== String(state.page + 1))
246
+ throw new Error();
247
+ if (nextUrl && xNext === '')
248
+ throw new Error();
249
+ // A short page can reflect a server page-size cap. Probe the following page
250
+ // even without Link rather than silently truncating at that cap.
251
+ return { ...state, page: state.page + 1 };
252
+ }
253
+ async request(url, requestArg) {
254
+ const { signal } = requestArg;
255
+ const maxBytes = requestArg.maxResponseBytes ?? this.#options.maxResponseBytes;
256
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 1)
257
+ throw new validation.ForgeInventoryError('invalid-response-budget');
258
+ const controller = new AbortController();
259
+ const abort = () => controller.abort();
260
+ if (signal?.aborted)
261
+ throw new validation.ForgeInventoryError('request-aborted');
262
+ signal?.addEventListener('abort', abort, { once: true });
263
+ const timeout = setTimeout(abort, this.#options.requestTimeoutMs);
264
+ const deadline = Date.now() + this.#options.requestTimeoutMs;
265
+ let reader;
266
+ try {
267
+ const headers = new Headers({ accept: 'application/json' });
268
+ if (this.#options.token)
269
+ headers.set(this.#options.kind === 'gitea' ? 'authorization' : 'private-token', this.#options.kind === 'gitea' ? `token ${this.#options.token}` : this.#options.token);
270
+ this.#metrics.requests++;
271
+ const response = await fetch(url, { method: 'GET', headers, redirect: 'error', credentials: 'omit', signal: controller.signal });
272
+ reader = response.body?.getReader();
273
+ if (response.status === 429)
274
+ this.#metrics.rateLimitedRequests++;
275
+ if (response.status !== 200)
276
+ throw new validation.ForgeInventoryError(`http-${response.status}`);
277
+ if (response.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json' || !reader)
278
+ throw new validation.ForgeInventoryError('invalid-content-type');
279
+ const chunks = [];
280
+ let bytes = 0;
281
+ while (true) {
282
+ const result = await reader.read();
283
+ if (result.done)
284
+ break;
285
+ bytes += result.value.byteLength;
286
+ this.#metrics.responseBytes += result.value.byteLength;
287
+ if (bytes > Math.min(maxBytes, this.#options.maxResponseBytes))
288
+ throw new validation.ForgeInventoryError('response-size-limit');
289
+ if (controller.signal.aborted || Date.now() >= deadline)
290
+ throw new validation.ForgeInventoryError('request-aborted-or-timed-out');
291
+ chunks.push(result.value);
292
+ }
293
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(Buffer.concat(chunks));
294
+ const body = JSON.parse(text);
295
+ if (controller.signal.aborted || Date.now() >= deadline)
296
+ throw new validation.ForgeInventoryError('request-aborted-or-timed-out');
297
+ return { body, headers: response.headers };
298
+ }
299
+ catch (error) {
300
+ if (error instanceof validation.ForgeInventoryError)
301
+ throw error;
302
+ throw new validation.ForgeInventoryError(controller.signal.aborted ? 'request-aborted-or-timed-out' : 'request-or-json-failed');
303
+ }
304
+ finally {
305
+ controller.abort();
306
+ clearTimeout(timeout);
307
+ signal?.removeEventListener('abort', abort);
308
+ if (reader) {
309
+ try {
310
+ await reader.cancel();
311
+ }
312
+ catch { /* The request has already been aborted. */ }
313
+ reader.releaseLock();
314
+ }
315
+ }
316
+ }
317
+ }
318
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5mb3JnZWludmVudG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuZm9yZ2VpbnZlbnRvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLFVBQVUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUU3RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQW9DckUsZ0dBQWdHO0FBQ2hHLE1BQU0sT0FBTyxxQkFBcUI7SUFDdkIsUUFBUSxDQUF1RTtJQUMvRSxVQUFVLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUMsUUFBUSxHQUEyQixFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsYUFBYSxFQUFFLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUV0RyxZQUFZLFVBQWtDO1FBQzVDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUU7WUFDNUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztZQUM5QyxDQUFDLFVBQVUsQ0FBQyxLQUFLLEtBQUssU0FBUyxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsS0FBSyxJQUFJLHlCQUF5QixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDOUcsTUFBTSxJQUFJLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FB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
@@ -0,0 +1,25 @@
1
+ import type * as plugins from './plugins.js';
2
+ import type { IForgeInventoryMetrics, IForgeInventoryOptions } from './classes.forgeinventory.js';
3
+ export interface IForgeInventoryScanOptions {
4
+ signal?: AbortSignal;
5
+ /** Maximum distinct items retained per collection. */
6
+ maxItems?: number;
7
+ /** Deadline for the complete scan, including body reads. */
8
+ timeoutMs?: number;
9
+ /** Maximum response bytes consumed across both collections. */
10
+ maxScanResponseBytes?: number;
11
+ }
12
+ export interface IForgeInventoryScan {
13
+ report: plugins.fossInterfaces.data.IForgeInventoryReport;
14
+ repositories: plugins.fossInterfaces.data.IForgeInventoryRepository[];
15
+ namespaces: plugins.fossInterfaces.data.IForgeInventoryNamespace[];
16
+ metrics: IForgeInventoryMetrics;
17
+ }
18
+ /** A bounded, disposable observation; callers own any durable storage and migration decisions. */
19
+ export declare class ForgeInventoryScanner {
20
+ #private;
21
+ constructor(optionsArg: IForgeInventoryOptions);
22
+ scan(optionsArg?: IForgeInventoryScanOptions): Promise<IForgeInventoryScan>;
23
+ private capability;
24
+ private collect;
25
+ }
@@ -0,0 +1,139 @@
1
+ import { ForgeInventoryAdapter, ForgeInventoryError } from './classes.forgeinventory.js';
2
+ import { unknownSize } from './forgeinventory.validation.js';
3
+ const entityClasses = {
4
+ namespaces: true, users: true, teams: true, memberships: true, repositories: true,
5
+ gitRefs: true, gitObjects: true, protectedRefs: true, publicSshKeys: true, deployKeys: true,
6
+ issues: true, issueComments: true, pullRequests: true, reviews: true, reviewComments: true,
7
+ labels: true, milestones: true, assignees: true, reactions: true, releases: true,
8
+ releaseAssets: true, lfsObjects: true, packages: true, packageVersions: true, packageBlobs: true,
9
+ webhooks: true, webhookDeliveries: true, ciWorkflows: true, ciRuns: true, ciArtifacts: true,
10
+ wikis: true, projects: true,
11
+ };
12
+ /** A bounded, disposable observation; callers own any durable storage and migration decisions. */
13
+ export class ForgeInventoryScanner {
14
+ #adapter;
15
+ #running = false;
16
+ constructor(optionsArg) {
17
+ this.#adapter = new ForgeInventoryAdapter(optionsArg);
18
+ }
19
+ async scan(optionsArg = {}) {
20
+ const maxItems = optionsArg.maxItems ?? 100_000;
21
+ const timeoutMs = optionsArg.timeoutMs ?? 60_000;
22
+ const maxScanResponseBytes = optionsArg.maxScanResponseBytes ?? 64 * 1024 * 1024;
23
+ if (!Number.isSafeInteger(maxItems) || maxItems < 1 || maxItems > 1_000_000 ||
24
+ !Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 3_600_000 ||
25
+ !Number.isSafeInteger(maxScanResponseBytes) || maxScanResponseBytes < 1 || maxScanResponseBytes > 1024 * 1024 * 1024) {
26
+ throw new ForgeInventoryError('invalid-scan-limits');
27
+ }
28
+ if (this.#running)
29
+ throw new ForgeInventoryError('scan-already-running');
30
+ this.#running = true;
31
+ const controller = new AbortController();
32
+ const abort = () => controller.abort();
33
+ if (optionsArg.signal?.aborted)
34
+ controller.abort();
35
+ optionsArg.signal?.addEventListener('abort', abort, { once: true });
36
+ const timeout = setTimeout(abort, timeoutMs);
37
+ const before = this.#adapter.metrics;
38
+ const deadline = Date.now() + timeoutMs;
39
+ const remainingBytes = () => maxScanResponseBytes - (this.#adapter.metrics.responseBytes - before.responseBytes);
40
+ const collections = Object.fromEntries(Object.keys(entityClasses).map((key) => [key, {
41
+ capability: { status: 'unverified', reason: 'No inventory reader has inspected this entity class.' },
42
+ result: { status: 'notInspected', reason: 'Outside this repository and organization/group scan.' },
43
+ }]));
44
+ try {
45
+ const namespaces = await this.collect((request) => this.#adapter.listNamespaces(request), maxItems, controller.signal, deadline, remainingBytes);
46
+ const repositories = await this.collect((request) => this.#adapter.listRepositories(request), maxItems, controller.signal, deadline, remainingBytes);
47
+ const namespaceLimitation = 'Only organization/group namespaces were inspected; personal namespaces and full private namespace coverage remain uninspected.';
48
+ collections.namespaces = {
49
+ capability: this.capability(namespaces, [namespaceLimitation, 'Live API visibility does not prove administrator completeness.']),
50
+ result: namespaces.result.status === 'enumerated' ? {
51
+ status: 'incomplete', observation: namespaces.result.observation,
52
+ observedCount: namespaces.result.count, reason: namespaceLimitation,
53
+ } : namespaces.result,
54
+ };
55
+ const repositoryResult = repositories.result;
56
+ if (repositoryResult.status === 'enumerated') {
57
+ const measurements = repositories.items.map((item) => item.gitSizeBytes);
58
+ repositoryResult.sizeBytes = measurements.length > 0 && measurements.every((size) => size.status === 'measured')
59
+ ? { status: 'measured', value: measurements.reduce((sum, size) => sum + (size.status === 'measured' ? BigInt(size.value) : 0n), 0n).toString(), accuracy: 'estimate' }
60
+ : unknownSize('Separate Git byte measurements were not available for every repository.');
61
+ }
62
+ collections.repositories = {
63
+ capability: this.capability(repositories, ['Only API-visible repositories are enumerated.', 'Live pagination is not a frozen export.', 'Git size statistics do not measure outgoing push bytes.']),
64
+ result: repositoryResult,
65
+ };
66
+ const after = this.#adapter.metrics;
67
+ return {
68
+ report: {
69
+ schemaVersion: 1, instance: this.#adapter.instance, scope: { kind: 'instance' }, collections,
70
+ additionalCollections: [{
71
+ name: this.#adapter.instance.kind === 'gitea' ? 'gitea.organizations' : 'gitlab.groups',
72
+ capability: this.capability(namespaces, ['Endpoint visibility and live pagination limits apply.']),
73
+ result: namespaces.result,
74
+ }],
75
+ },
76
+ repositories: repositories.items, namespaces: namespaces.items,
77
+ metrics: {
78
+ requests: after.requests - before.requests,
79
+ responseBytes: after.responseBytes - before.responseBytes,
80
+ rateLimitedRequests: after.rateLimitedRequests - before.rateLimitedRequests,
81
+ },
82
+ };
83
+ }
84
+ finally {
85
+ controller.abort();
86
+ clearTimeout(timeout);
87
+ optionsArg.signal?.removeEventListener('abort', abort);
88
+ this.#running = false;
89
+ }
90
+ }
91
+ capability(collection, limitations) {
92
+ return collection.result.status === 'enumerated' || collection.items.length > 0
93
+ ? { status: 'available', limitations }
94
+ : { status: 'unverified', reason: 'No successful enumeration or entity observation established this reader capability.' };
95
+ }
96
+ async collect(read, maxItems, signal, deadline, remainingBytes) {
97
+ const startedAt = new Date().toISOString();
98
+ const items = [];
99
+ const identities = new Set();
100
+ let cursor;
101
+ const incomplete = (reason) => ({ items, result: {
102
+ status: 'incomplete', observation: this.#adapter.observation(startedAt), observedCount: String(items.length), reason,
103
+ } });
104
+ while (true) {
105
+ if (signal.aborted || Date.now() >= deadline)
106
+ return incomplete('Scan aborted or deadline reached.');
107
+ if (remainingBytes() <= 0)
108
+ return incomplete('Configured scan response-byte limit reached.');
109
+ let page;
110
+ try {
111
+ page = await read({ cursor, signal, maxResponseBytes: remainingBytes() });
112
+ }
113
+ catch (error) {
114
+ return incomplete(error instanceof ForgeInventoryError ? error.message : 'Inventory request failed.');
115
+ }
116
+ for (const item of page.items) {
117
+ if (item.identity.status !== 'identified')
118
+ return incomplete('Stable provider identity was not available.');
119
+ const key = JSON.stringify(item.identity.ref);
120
+ if (identities.has(key))
121
+ return incomplete('Repeated provider identity during live pagination.');
122
+ if (items.length >= maxItems)
123
+ return incomplete('Configured item limit reached.');
124
+ identities.add(key);
125
+ items.push(item);
126
+ }
127
+ if (signal.aborted || Date.now() >= deadline)
128
+ return incomplete('Scan aborted or deadline reached.');
129
+ if (page.pagination.status === 'incomplete')
130
+ return incomplete(page.pagination.reason);
131
+ if (page.pagination.status === 'exhausted')
132
+ return {
133
+ items, result: { status: 'enumerated', observation: this.#adapter.observation(startedAt), count: String(items.length), sizeBytes: unknownSize('No byte measurement for this collection.') },
134
+ };
135
+ cursor = page.pagination.cursor;
136
+ }
137
+ }
138
+ }
139
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5mb3JnZWludmVudG9yeXNjYW5uZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLmZvcmdlaW52ZW50b3J5c2Nhbm5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUV6RixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFtQjdELE1BQU0sYUFBYSxHQUFHO0lBQ3BCLFVBQVUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLElBQUk7SUFDakYsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSTtJQUMzRixNQUFNLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxJQUFJO0lBQzFGLE1BQU0sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUk7SUFDaEYsYUFBYSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSTtJQUNoRyxRQUFRLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUk7SUFDM0YsS0FBSyxFQUFFLElBQUksRUFB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
@@ -0,0 +1,15 @@
1
+ import type * as plugins from './plugins.js';
2
+ export declare class ForgeInventoryError extends Error {
3
+ readonly code: string;
4
+ constructor(code: string);
5
+ }
6
+ export declare const record: (value: unknown) => Record<string, unknown>;
7
+ export declare const decimal: (value: unknown) => string;
8
+ export declare const optionalString: (value: unknown) => string | null;
9
+ export declare const optionalBoolean: (value: unknown) => boolean | null;
10
+ export declare const segments: (value: unknown) => string[];
11
+ export declare const visibility: (value: unknown) => plugins.fossInterfaces.data.TForgeInventoryVisibility | null;
12
+ export declare const httpUrl: (value: unknown) => string | null;
13
+ export declare const sshUrl: (value: unknown) => string | null;
14
+ export declare const unknownSize: (reason: string) => plugins.fossInterfaces.data.TForgeInventoryQuantity;
15
+ export declare const gitlabSize: (statistics: unknown) => plugins.fossInterfaces.data.TForgeInventoryQuantity;