@foss.global/interfaces 0.13.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026-09-25 - 1.0.0
4
+
5
+ ### Breaking Changes
6
+
7
+ - replace the GitManager ref listing contract with a complete paginated ref inventory (gitmanager)
8
+ - `IGitManagerRefRequest` gains `prefixes`, `cursor`, and `limit`; without prefixes every ref under `refs/` is selected, overlapping prefixes select their de-duplicated union, an empty array is invalid, and a complete ref name as the only prefix is an exact lookup.
9
+ - `IGitManagerRef` now carries `name`, `objectId`, `objectType`, `peeledObjectId`, `peeledObjectType`, and `symbolicTarget`; `objectId` and `objectType` are null only for a symbolic ref whose target does not resolve. The per-ref `org`, `repo`, `shortName`, `refType`, `updatedAt`, and `subject` fields and `TGitManagerRefType` are removed.
10
+ - Add `TGitManagerRefInventoryResult`: an `IGitManagerRefInventoryPage` with HEAD, total count, inventory digest, and cursor pagination, or `IGitManagerRefInventoryStale` when the selected refs or HEAD changed between pages.
11
+
12
+ ### Maintenance
13
+
14
+ - Update release tooling to pnpm 12.4.2, `@git.zone/tsbuild` 5.0.0, `@git.zone/tsrun` 3.0.0, `@git.zone/tstest` 6.2.0, `@git.zone/tsdoc` 2.2.2 and `@types/node` 26.6.1 (tooling)
15
+ - pnpm 12.5.x and `@types/node` 26.6.2 are inside the seven-day release-age window, so pnpm stays on 12.4.2 and `@types/node` on 26.6.1.
16
+ - No source migration is needed: no `ts*` folder carries its own `tsconfig.json` (tsbuild 5), no script reads `process.argv` (tsrun 3), and both test files end in `tap.start()` without `TapNodeTools` (tstest 5 and 6).
17
+
3
18
  ## 2026-09-05 - 0.13.0
4
19
 
5
20
  ### Features
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@foss.global/interfaces',
6
- version: '0.13.0',
6
+ version: '1.0.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.'
8
8
  };
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHFHQUFxRztDQUNuSCxDQUFBIn0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFHQUFxRztDQUNuSCxDQUFBIn0=
@@ -1,4 +1,3 @@
1
- export type TGitManagerRefType = 'branch' | 'tag' | 'other';
2
1
  export type TGitManagerObjectType = 'blob' | 'tree' | 'commit' | 'tag' | 'other';
3
2
  export type TGitManagerTreeEntryType = 'file' | 'dir' | 'symlink' | 'submodule' | 'other';
4
3
  export type TGitManagerDiffFileStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'typechange' | 'unmerged' | 'unknown';
@@ -18,17 +17,92 @@ export interface IGitManagerInitBareRepositoryRequest extends IGitManagerReposit
18
17
  export interface IGitManagerImportMirrorRequest extends IGitManagerRepositorySelector {
19
18
  remoteUrl: string;
20
19
  }
21
- export interface IGitManagerRef extends IGitManagerRepositorySelector {
22
- name: string;
23
- shortName: string;
24
- objectId: string;
25
- objectType: TGitManagerObjectType;
26
- refType: TGitManagerRefType;
27
- updatedAt: string;
28
- subject: string;
29
- }
20
+ /**
21
+ * One page request of a repository's complete ref inventory.
22
+ *
23
+ * Without `prefixes`, every ref under `refs/` is listed: branches, tags, and
24
+ * all other namespaces such as `refs/notes/*`, `refs/pull/*`,
25
+ * `refs/keep-around/*`, and provider-internal refs. A prefix selects refs on
26
+ * full path components: `refs/heads/` selects every branch, and a complete
27
+ * ref name such as `refs/heads/main` selects exactly that ref.
28
+ */
30
29
  export interface IGitManagerRefRequest extends IGitManagerRepositorySelector {
30
+ /**
31
+ * `refs/`-rooted prefixes; omit to list every ref. An empty array is
32
+ * rejected as invalid. Overlapping prefixes select the de-duplicated union,
33
+ * so each ref appears once.
34
+ */
35
+ prefixes?: string[];
36
+ /** Opaque cursor from the preceding page; omit to start a new inventory. */
37
+ cursor?: string;
38
+ /** Maximum refs in this page. The engine owns the default and maximum. */
39
+ limit?: number;
31
40
  }
41
+ export interface IGitManagerRef {
42
+ /** Full ref name, for example `refs/heads/main`. */
43
+ name: string;
44
+ /**
45
+ * Object the ref points at; for a symbolic ref, the object its target
46
+ * resolves to. Null only for a symbolic ref whose target does not resolve,
47
+ * such as `refs/remotes/origin/HEAD` pointing at a deleted branch; such refs
48
+ * are listed, never dropped.
49
+ */
50
+ objectId: string | null;
51
+ /** Type of `objectId`; null exactly when `objectId` is null. */
52
+ objectType: TGitManagerObjectType | null;
53
+ /** Fully peeled object for annotated tags, including nested tags; otherwise null. */
54
+ peeledObjectId: string | null;
55
+ peeledObjectType: TGitManagerObjectType | null;
56
+ /** Target ref name when this ref is symbolic; otherwise null. */
57
+ symbolicTarget: string | null;
58
+ }
59
+ /** Repository HEAD, which is reported separately and never listed in `refs`. */
60
+ export interface IGitManagerRefHead {
61
+ /** Target ref name when HEAD is symbolic; null when detached. */
62
+ symbolicTarget: string | null;
63
+ /** Resolved object; null when HEAD points at an unborn branch. */
64
+ objectId: string | null;
65
+ }
66
+ export type TGitManagerRefInventoryPagination = {
67
+ status: 'more';
68
+ cursor: string;
69
+ } | {
70
+ status: 'exhausted';
71
+ };
72
+ /**
73
+ * A coherent page of the selected ref inventory, sorted by ref name in byte
74
+ * order. Every page carries the digest of the complete selection it was cut
75
+ * from; a cursor is honoured only while that digest is unchanged, so pages of
76
+ * one inventory never mix two ref states.
77
+ *
78
+ * `inventoryDigest` is the lowercase hex SHA-256 over the UTF-8 bytes of
79
+ * `HEAD\0<head.symbolicTarget or empty>\0<head.objectId or empty>\n` followed
80
+ * by `<name>\0<objectId or empty>\0<symbolicTarget or empty>\n` for each
81
+ * selected ref in ref-name byte order over the complete selection. Peeled
82
+ * values and object types follow from the object IDs and are not part of the
83
+ * digest.
84
+ */
85
+ export interface IGitManagerRefInventoryPage extends IGitManagerRepositorySelector {
86
+ status: 'page';
87
+ inventoryDigest: string;
88
+ /** Number of refs in the complete selection, not in this page. */
89
+ refCount: number;
90
+ head: IGitManagerRefHead;
91
+ refs: IGitManagerRef[];
92
+ pagination: TGitManagerRefInventoryPagination;
93
+ }
94
+ /**
95
+ * The selected refs or HEAD changed since the cursor was issued. The caller
96
+ * restarts the inventory without a cursor; no partial page is returned.
97
+ */
98
+ export interface IGitManagerRefInventoryStale extends IGitManagerRepositorySelector {
99
+ status: 'stale';
100
+ /** Digest bound to the rejected cursor. */
101
+ expectedInventoryDigest: string;
102
+ /** Digest of the current selection. */
103
+ inventoryDigest: string;
104
+ }
105
+ export type TGitManagerRefInventoryResult = IGitManagerRefInventoryPage | IGitManagerRefInventoryStale;
32
106
  export type TGitManagerMergeMethod = 'merge' | 'squash' | 'rebase';
33
107
  export type TGitManagerMergeStatus = 'merged' | 'already_merged' | 'conflicting' | 'stale';
34
108
  export interface IGitManagerMergeRequest extends IGitManagerRepositorySelector {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foss.global/interfaces",
3
- "version": "0.13.0",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.",
6
6
  "exports": {
@@ -13,11 +13,11 @@
13
13
  "@api.global/typedrequest-interfaces": "^7.1.0"
14
14
  },
15
15
  "devDependencies": {
16
- "@git.zone/tsbuild": "^4.4.2",
17
- "@git.zone/tsdoc": "^2.1.1",
18
- "@git.zone/tsrun": "^2.0.6",
19
- "@git.zone/tstest": "^4.0.0",
20
- "@types/node": "^26.4.1"
16
+ "@git.zone/tsbuild": "^5.0.0",
17
+ "@git.zone/tsdoc": "^2.2.2",
18
+ "@git.zone/tsrun": "^3.0.0",
19
+ "@git.zone/tstest": "^6.2.0",
20
+ "@types/node": "^26.6.1"
21
21
  },
22
22
  "files": [
23
23
  "ts/**/*",
package/readme.md CHANGED
@@ -95,6 +95,64 @@ The runner lifecycle contracts cover registration, sessions, runner and job hear
95
95
 
96
96
  Protocol v1 describes OCI execution with Docker or Podman and `tar.gz` source archives. Artifacts, caches, and service containers are explicitly unsupported in the v1 capability shape. Supported job network modes are `none` and `bridge`; the execution service remains responsible for enforcing the advertised capability.
97
97
 
98
+ ### GitManager ref inventory contracts
99
+
100
+ `IGitManagerRefRequest`, `IGitManagerRef`, and `TGitManagerRefInventoryResult`
101
+ describe a complete, paginated ref inventory. Without `prefixes`, every ref
102
+ under `refs/` is listed, including notes, pull, keep-around, and
103
+ provider-internal namespaces. HEAD is reported separately in `head`. Annotated
104
+ tags carry their fully peeled object. Symbolic refs carry their target ref
105
+ name; a symbolic ref whose target does not resolve is still listed, with a null
106
+ `objectId` and `objectType`.
107
+
108
+ ```ts
109
+ import type {
110
+ IGitManagerRef,
111
+ IGitManagerRefRequest,
112
+ TGitManagerRefInventoryResult,
113
+ } from '@foss.global/interfaces';
114
+
115
+ declare function listRefs(
116
+ request: IGitManagerRefRequest,
117
+ ): Promise<TGitManagerRefInventoryResult>;
118
+
119
+ const collectRefs = async (): Promise<IGitManagerRef[]> => {
120
+ const refs: IGitManagerRef[] = [];
121
+ let cursor: string | undefined;
122
+ while (true) {
123
+ const result = await listRefs({ org: 'foss.global', repo: 'interfaces', cursor });
124
+ if (result.status === 'stale') {
125
+ refs.length = 0;
126
+ cursor = undefined;
127
+ continue;
128
+ }
129
+ refs.push(...result.refs);
130
+ if (result.pagination.status === 'exhausted') {
131
+ return refs;
132
+ }
133
+ cursor = result.pagination.cursor;
134
+ }
135
+ };
136
+
137
+ // A complete ref name as the only prefix is an exact lookup.
138
+ const main = await listRefs({
139
+ org: 'foss.global',
140
+ repo: 'interfaces',
141
+ prefixes: ['refs/heads/main'],
142
+ });
143
+ ```
144
+
145
+ Prefixes match whole path components, so `refs/heads/ma` does not select
146
+ `refs/heads/main`. Overlapping prefixes select their de-duplicated union, and
147
+ an empty `prefixes` array is rejected as invalid. Pages are sorted by ref name
148
+ in byte order and each carries `inventoryDigest`, the SHA-256 of the complete
149
+ selection defined on `IGitManagerRefInventoryPage`. A cursor is opaque and
150
+ bound to the repository, the prefix set, and that digest. When the selected
151
+ refs or HEAD change between pages, the next call returns `status: 'stale'`
152
+ instead of a page that would mix two states; the caller restarts without a
153
+ cursor. A cursor is a transport continuation, not a durable replication
154
+ checkpoint.
155
+
98
156
  ### Forge inventory contracts
99
157
 
100
158
  `IForgeInventoryReport`, `IForgeInventoryPage<TItem>`, `IForgeInventoryNamespace`,
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@foss.global/interfaces',
6
- version: '0.13.0',
6
+ version: '1.0.0',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.'
8
8
  }
@@ -1,5 +1,3 @@
1
- export type TGitManagerRefType = 'branch' | 'tag' | 'other';
2
-
3
1
  export type TGitManagerObjectType = 'blob' | 'tree' | 'commit' | 'tag' | 'other';
4
2
 
5
3
  export type TGitManagerTreeEntryType = 'file' | 'dir' | 'symlink' | 'submodule' | 'other';
@@ -35,17 +33,95 @@ export interface IGitManagerImportMirrorRequest extends IGitManagerRepositorySel
35
33
  remoteUrl: string;
36
34
  }
37
35
 
38
- export interface IGitManagerRef extends IGitManagerRepositorySelector {
36
+ /**
37
+ * One page request of a repository's complete ref inventory.
38
+ *
39
+ * Without `prefixes`, every ref under `refs/` is listed: branches, tags, and
40
+ * all other namespaces such as `refs/notes/*`, `refs/pull/*`,
41
+ * `refs/keep-around/*`, and provider-internal refs. A prefix selects refs on
42
+ * full path components: `refs/heads/` selects every branch, and a complete
43
+ * ref name such as `refs/heads/main` selects exactly that ref.
44
+ */
45
+ export interface IGitManagerRefRequest extends IGitManagerRepositorySelector {
46
+ /**
47
+ * `refs/`-rooted prefixes; omit to list every ref. An empty array is
48
+ * rejected as invalid. Overlapping prefixes select the de-duplicated union,
49
+ * so each ref appears once.
50
+ */
51
+ prefixes?: string[];
52
+ /** Opaque cursor from the preceding page; omit to start a new inventory. */
53
+ cursor?: string;
54
+ /** Maximum refs in this page. The engine owns the default and maximum. */
55
+ limit?: number;
56
+ }
57
+
58
+ export interface IGitManagerRef {
59
+ /** Full ref name, for example `refs/heads/main`. */
39
60
  name: string;
40
- shortName: string;
41
- objectId: string;
42
- objectType: TGitManagerObjectType;
43
- refType: TGitManagerRefType;
44
- updatedAt: string;
45
- subject: string;
61
+ /**
62
+ * Object the ref points at; for a symbolic ref, the object its target
63
+ * resolves to. Null only for a symbolic ref whose target does not resolve,
64
+ * such as `refs/remotes/origin/HEAD` pointing at a deleted branch; such refs
65
+ * are listed, never dropped.
66
+ */
67
+ objectId: string | null;
68
+ /** Type of `objectId`; null exactly when `objectId` is null. */
69
+ objectType: TGitManagerObjectType | null;
70
+ /** Fully peeled object for annotated tags, including nested tags; otherwise null. */
71
+ peeledObjectId: string | null;
72
+ peeledObjectType: TGitManagerObjectType | null;
73
+ /** Target ref name when this ref is symbolic; otherwise null. */
74
+ symbolicTarget: string | null;
75
+ }
76
+
77
+ /** Repository HEAD, which is reported separately and never listed in `refs`. */
78
+ export interface IGitManagerRefHead {
79
+ /** Target ref name when HEAD is symbolic; null when detached. */
80
+ symbolicTarget: string | null;
81
+ /** Resolved object; null when HEAD points at an unborn branch. */
82
+ objectId: string | null;
83
+ }
84
+
85
+ export type TGitManagerRefInventoryPagination =
86
+ | { status: 'more'; cursor: string }
87
+ | { status: 'exhausted' };
88
+
89
+ /**
90
+ * A coherent page of the selected ref inventory, sorted by ref name in byte
91
+ * order. Every page carries the digest of the complete selection it was cut
92
+ * from; a cursor is honoured only while that digest is unchanged, so pages of
93
+ * one inventory never mix two ref states.
94
+ *
95
+ * `inventoryDigest` is the lowercase hex SHA-256 over the UTF-8 bytes of
96
+ * `HEAD\0<head.symbolicTarget or empty>\0<head.objectId or empty>\n` followed
97
+ * by `<name>\0<objectId or empty>\0<symbolicTarget or empty>\n` for each
98
+ * selected ref in ref-name byte order over the complete selection. Peeled
99
+ * values and object types follow from the object IDs and are not part of the
100
+ * digest.
101
+ */
102
+ export interface IGitManagerRefInventoryPage extends IGitManagerRepositorySelector {
103
+ status: 'page';
104
+ inventoryDigest: string;
105
+ /** Number of refs in the complete selection, not in this page. */
106
+ refCount: number;
107
+ head: IGitManagerRefHead;
108
+ refs: IGitManagerRef[];
109
+ pagination: TGitManagerRefInventoryPagination;
110
+ }
111
+
112
+ /**
113
+ * The selected refs or HEAD changed since the cursor was issued. The caller
114
+ * restarts the inventory without a cursor; no partial page is returned.
115
+ */
116
+ export interface IGitManagerRefInventoryStale extends IGitManagerRepositorySelector {
117
+ status: 'stale';
118
+ /** Digest bound to the rejected cursor. */
119
+ expectedInventoryDigest: string;
120
+ /** Digest of the current selection. */
121
+ inventoryDigest: string;
46
122
  }
47
123
 
48
- export interface IGitManagerRefRequest extends IGitManagerRepositorySelector {}
124
+ export type TGitManagerRefInventoryResult = IGitManagerRefInventoryPage | IGitManagerRefInventoryStale;
49
125
 
50
126
  export type TGitManagerMergeMethod = 'merge' | 'squash' | 'rebase';
51
127