@foss.global/interfaces 2.0.0 → 2.1.1

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-10-13 - 2.1.1
4
+
5
+ ### Fixes
6
+
7
+ - Correct the atomic push contract docs: `http` push remotes must be loopback IP literals (`127.0.0.0/8`, `[::1]`), never `localhost`; a ref already at `newObjectId` reports `ok` without a lease check
8
+
9
+ ## 2026-10-13 - 2.1.0
10
+
11
+ ### Features
12
+
13
+ - add origin and atomic push contracts for the Gitea import (data)
14
+ - `IOriginRef` and `TOriginState`: where a native entity came from (`native`, `imported` with the source forge instance and entity id, or `unknown`); an identity only, never a URL, path or authority.
15
+ - `IGitManagerAtomicPushRequest` with leased `IGitManagerAtomicPushRefUpdate`s and the all-or-nothing `IGitManagerAtomicPushResult` (`ok`, `stale` or `rejected` per ref); https or loopback-http remotes only.
16
+ - `IGitManagerSetDefaultBranchRequest` points a repository's HEAD at an existing branch.
17
+
3
18
  ## 2026-10-13 - 2.0.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: '2.0.0',
6
+ version: '2.1.1',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFHQUFxRztDQUNuSCxDQUFBIn0=
@@ -14,6 +14,14 @@ export interface IGitManagerRepositoryInfo extends IGitManagerRepositorySelector
14
14
  export interface IGitManagerInitBareRepositoryRequest extends IGitManagerRepositorySelector {
15
15
  defaultBranch?: string;
16
16
  }
17
+ /**
18
+ * Points a repository's HEAD at an existing branch, which clones then check
19
+ * out by default.
20
+ */
21
+ export interface IGitManagerSetDefaultBranchRequest extends IGitManagerRepositorySelector {
22
+ /** Branch name without `refs/heads/`, as in `IGitManagerRepositoryInfo.defaultBranch`; the branch must exist. */
23
+ defaultBranch: string;
24
+ }
17
25
  /**
18
26
  * HTTP Basic credentials for a remote Git transfer, such as a forge user name
19
27
  * with an access token as the password. Neither part may contain control
@@ -55,6 +63,66 @@ export interface IGitManagerImportMirrorRequest extends IGitManagerRepositorySel
55
63
  /** Fetches every ref of an imported mirror's remote again, pruning refs the remote no longer has. */
56
64
  export interface IGitManagerRefreshMirrorRequest extends IGitManagerRepositorySelector, IGitManagerRemoteTransferOptions {
57
65
  }
66
+ /**
67
+ * One ref change of an atomic push, guarded by a lease: the remote applies it
68
+ * only while its ref still points at `expectedOldObjectId`. Both object IDs
69
+ * are full hexadecimal object IDs; at least one of them is non-null.
70
+ */
71
+ export interface IGitManagerAtomicPushRefUpdate {
72
+ /** Full ref name on the remote, for example `refs/heads/main`. */
73
+ ref: string;
74
+ /** Object the remote ref must point at now; null creates the ref, which must not exist. */
75
+ expectedOldObjectId: string | null;
76
+ /** Object to set the remote ref to, present in the managed repository; null deletes the ref. */
77
+ newObjectId: string | null;
78
+ }
79
+ /**
80
+ * Pushes ref updates from a managed repository to a remote as one atomic
81
+ * transaction: the remote applies every update or none. The remote must
82
+ * advertise the `atomic` receive-pack capability; without it the push fails
83
+ * before any ref is sent and never falls back to ref-by-ref updates.
84
+ *
85
+ * `remoteUrl` is used for this push only and is never stored in the
86
+ * repository. It must be `https`, or `http` to a loopback IP address
87
+ * (`127.0.0.0/8` or `[::1]`); host names such as `localhost` are refused for
88
+ * `http` because their resolution is not checked. `ssh`, `git`, `file` and
89
+ * scp-like URLs are refused. Transfer options behave as for `importMirror`,
90
+ * except that a push credential is also accepted for `http` to a loopback IP
91
+ * address, which never leaves the machine; the URL must not carry user
92
+ * information.
93
+ */
94
+ export interface IGitManagerAtomicPushRequest extends IGitManagerRepositorySelector, IGitManagerRemoteTransferOptions {
95
+ remoteUrl: string;
96
+ /** Updates of distinct refs; at least one. */
97
+ updates: IGitManagerAtomicPushRefUpdate[];
98
+ }
99
+ /**
100
+ * Outcome of one ref as the remote reported it. `stale` means the lease
101
+ * failed: the remote ref did not point at the expected object. A ref that
102
+ * already points at `newObjectId` is reported `ok` without its lease being
103
+ * checked, because git skips it as up to date before the lease check; such a
104
+ * ref is not changed, so an `ok` result never overwrote an object the caller
105
+ * did not expect. `rejected`
106
+ * covers every other refusal, such as a hook or ref protection, and also the
107
+ * refs the remote refused only because another ref of the same atomic push
108
+ * failed.
109
+ */
110
+ export type TGitManagerAtomicPushRefStatus = 'ok' | 'rejected' | 'stale';
111
+ export interface IGitManagerAtomicPushRefResult {
112
+ ref: string;
113
+ status: TGitManagerAtomicPushRefStatus;
114
+ /** Reason text the remote reported for the ref, when it gave one; credentials are redacted. */
115
+ message?: string;
116
+ }
117
+ /**
118
+ * Result of an atomic push. `applied` means every ref is `ok`; `rejected`
119
+ * means no ref changed on the remote, and `refs` says why.
120
+ */
121
+ export interface IGitManagerAtomicPushResult extends IGitManagerRepositorySelector {
122
+ status: 'applied' | 'rejected';
123
+ /** One result per requested update, in request order. */
124
+ refs: IGitManagerAtomicPushRefResult[];
125
+ }
58
126
  /**
59
127
  * The object database of one repository when it was measured. Objects of
60
128
  * alternate object stores are not counted.
@@ -2,5 +2,6 @@ export * from './codefeed.js';
2
2
  export * from './forgeinventory.js';
3
3
  export * from './forgesourceinventory.js';
4
4
  export * from './gitmanager.js';
5
+ export * from './origin.js';
5
6
  export * from './public.js';
6
7
  export * from './runner.js';
@@ -2,6 +2,7 @@ export * from './codefeed.js';
2
2
  export * from './forgeinventory.js';
3
3
  export * from './forgesourceinventory.js';
4
4
  export * from './gitmanager.js';
5
+ export * from './origin.js';
5
6
  export * from './public.js';
6
7
  export * from './runner.js';
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYywyQkFBMkIsQ0FBQztBQUMxQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDIn0=
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9kYXRhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsZUFBZSxDQUFDO0FBQzlCLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYywyQkFBMkIsQ0FBQztBQUMxQyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDO0FBQzVCLGNBQWMsYUFBYSxDQUFDIn0=
@@ -0,0 +1,35 @@
1
+ /** Kinds of source entity an import records its origin for. */
2
+ export type TOriginEntityKind = 'repository';
3
+ /**
4
+ * Identity of the source entity a native entity was imported from.
5
+ *
6
+ * It names the source by stable identifiers only. It carries no URLs, paths,
7
+ * configuration or run IDs, digests, or authority: it neither locates the
8
+ * source nor grants access to it.
9
+ */
10
+ export interface IOriginRef {
11
+ /** Operator-minted instanceId of the forge connection the entity was imported from. */
12
+ instanceId: string;
13
+ entityKind: TOriginEntityKind;
14
+ /** Source row ID as an opaque string; for a Gitea repository, its decimal repository ID. */
15
+ entityId: string;
16
+ /**
17
+ * Source ID of the parent when entity IDs are parent-scoped; otherwise null.
18
+ * Null for repositories, because Gitea repository IDs are unique within an
19
+ * instance. Later entity kinds define their parent.
20
+ */
21
+ parentId: string | null;
22
+ }
23
+ /**
24
+ * Where a native entity came from: created natively, imported from a
25
+ * recorded source, or not known, for example for an entity that predates
26
+ * origin tracking. `unknown` must never be read as `native`.
27
+ */
28
+ export type TOriginState = {
29
+ kind: 'native';
30
+ } | {
31
+ kind: 'imported';
32
+ origin: IOriginRef;
33
+ } | {
34
+ kind: 'unknown';
35
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JpZ2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGF0YS9vcmlnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foss.global/interfaces",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "private": false,
5
5
  "description": "Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.",
6
6
  "exports": {
package/readme.md CHANGED
@@ -171,6 +171,36 @@ remote URL.
171
171
  do not depend on packing) and `storageBytes` (every file of the object
172
172
  database, which does).
173
173
 
174
+ ### GitManager atomic push and default branch contracts
175
+
176
+ `IGitManagerAtomicPushRequest` pushes `IGitManagerAtomicPushRefUpdate`s from a
177
+ managed repository to `remoteUrl` as one transaction: the remote applies every
178
+ update or none, and a remote that does not advertise the `atomic` capability is
179
+ refused rather than pushed to ref by ref. Every update is leased:
180
+ `expectedOldObjectId` is the object the remote ref must point at now (null to
181
+ create a ref that must not exist), and `newObjectId` is the object to set (null
182
+ to delete). The URL is used for that push only; it must be `https`, or `http` to
183
+ a loopback host. The transfer options are those of `importMirror`, except that
184
+ a push credential is also accepted for loopback `http`.
185
+
186
+ `IGitManagerAtomicPushResult` is `applied` when every ref is `ok` and
187
+ `rejected` when no ref changed. Each `IGitManagerAtomicPushRefResult` is `ok`,
188
+ `stale` (the lease failed) or `rejected` (a hook, ref protection, or another
189
+ ref of the same push failed), with the remote's reason as `message`.
190
+
191
+ `IGitManagerSetDefaultBranchRequest` points a repository's HEAD at an existing
192
+ branch, named as in `IGitManagerRepositoryInfo.defaultBranch`.
193
+
194
+ ### Origin contracts
195
+
196
+ `TOriginState` records where a native entity came from: `native`, `imported`
197
+ with an `IOriginRef`, or `unknown`, which never means native. An `IOriginRef`
198
+ names the source by the operator-minted forge connection `instanceId`, the
199
+ `entityKind` (`repository`), the source `entityId` (a Gitea repository's
200
+ decimal ID) and `parentId` (null for repositories, whose Gitea IDs are unique
201
+ per instance). It carries no URLs, paths, configuration or run IDs, digests, or
202
+ authority.
203
+
174
204
  ### Forge inventory contracts
175
205
 
176
206
  `IForgeInventoryReport`, `IForgeInventoryPage<TItem>`, `IForgeInventoryNamespace`,
@@ -256,7 +286,7 @@ Actions secret or variable values, webhook secrets, or mirror remote URLs.
256
286
 
257
287
  ## Exports
258
288
 
259
- - `data`: public DTOs for users, organizations, repositories, contents, commits, diffs, releases, issues, activity, news, stats, codefeed commit results, GitManager repository/read API results, forge and forge source inventories, and runner/CI contracts.
289
+ - `data`: public DTOs for users, organizations, repositories, contents, commits, diffs, releases, issues, activity, news, stats, codefeed commit results, GitManager repository/read/push API results, origin references, forge and forge source inventories, and runner/CI contracts.
260
290
  - `requests`: TypedRequest contracts for `codefeed`, `publicOverview`, `publicOrg`, `publicRepo`, `publicFile`, and `publicCommits`.
261
291
  - Barrel exports: all public data and request interfaces are also exported from the package root.
262
292
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@foss.global/interfaces',
6
- version: '2.0.0',
6
+ version: '2.1.1',
7
7
  description: 'Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.'
8
8
  }
@@ -29,6 +29,15 @@ export interface IGitManagerInitBareRepositoryRequest extends IGitManagerReposit
29
29
  defaultBranch?: string;
30
30
  }
31
31
 
32
+ /**
33
+ * Points a repository's HEAD at an existing branch, which clones then check
34
+ * out by default.
35
+ */
36
+ export interface IGitManagerSetDefaultBranchRequest extends IGitManagerRepositorySelector {
37
+ /** Branch name without `refs/heads/`, as in `IGitManagerRepositoryInfo.defaultBranch`; the branch must exist. */
38
+ defaultBranch: string;
39
+ }
40
+
32
41
  /**
33
42
  * HTTP Basic credentials for a remote Git transfer, such as a forge user name
34
43
  * with an access token as the password. Neither part may contain control
@@ -74,6 +83,71 @@ export interface IGitManagerImportMirrorRequest extends IGitManagerRepositorySel
74
83
  /** Fetches every ref of an imported mirror's remote again, pruning refs the remote no longer has. */
75
84
  export interface IGitManagerRefreshMirrorRequest extends IGitManagerRepositorySelector, IGitManagerRemoteTransferOptions {}
76
85
 
86
+ /**
87
+ * One ref change of an atomic push, guarded by a lease: the remote applies it
88
+ * only while its ref still points at `expectedOldObjectId`. Both object IDs
89
+ * are full hexadecimal object IDs; at least one of them is non-null.
90
+ */
91
+ export interface IGitManagerAtomicPushRefUpdate {
92
+ /** Full ref name on the remote, for example `refs/heads/main`. */
93
+ ref: string;
94
+ /** Object the remote ref must point at now; null creates the ref, which must not exist. */
95
+ expectedOldObjectId: string | null;
96
+ /** Object to set the remote ref to, present in the managed repository; null deletes the ref. */
97
+ newObjectId: string | null;
98
+ }
99
+
100
+ /**
101
+ * Pushes ref updates from a managed repository to a remote as one atomic
102
+ * transaction: the remote applies every update or none. The remote must
103
+ * advertise the `atomic` receive-pack capability; without it the push fails
104
+ * before any ref is sent and never falls back to ref-by-ref updates.
105
+ *
106
+ * `remoteUrl` is used for this push only and is never stored in the
107
+ * repository. It must be `https`, or `http` to a loopback IP address
108
+ * (`127.0.0.0/8` or `[::1]`); host names such as `localhost` are refused for
109
+ * `http` because their resolution is not checked. `ssh`, `git`, `file` and
110
+ * scp-like URLs are refused. Transfer options behave as for `importMirror`,
111
+ * except that a push credential is also accepted for `http` to a loopback IP
112
+ * address, which never leaves the machine; the URL must not carry user
113
+ * information.
114
+ */
115
+ export interface IGitManagerAtomicPushRequest extends IGitManagerRepositorySelector, IGitManagerRemoteTransferOptions {
116
+ remoteUrl: string;
117
+ /** Updates of distinct refs; at least one. */
118
+ updates: IGitManagerAtomicPushRefUpdate[];
119
+ }
120
+
121
+ /**
122
+ * Outcome of one ref as the remote reported it. `stale` means the lease
123
+ * failed: the remote ref did not point at the expected object. A ref that
124
+ * already points at `newObjectId` is reported `ok` without its lease being
125
+ * checked, because git skips it as up to date before the lease check; such a
126
+ * ref is not changed, so an `ok` result never overwrote an object the caller
127
+ * did not expect. `rejected`
128
+ * covers every other refusal, such as a hook or ref protection, and also the
129
+ * refs the remote refused only because another ref of the same atomic push
130
+ * failed.
131
+ */
132
+ export type TGitManagerAtomicPushRefStatus = 'ok' | 'rejected' | 'stale';
133
+
134
+ export interface IGitManagerAtomicPushRefResult {
135
+ ref: string;
136
+ status: TGitManagerAtomicPushRefStatus;
137
+ /** Reason text the remote reported for the ref, when it gave one; credentials are redacted. */
138
+ message?: string;
139
+ }
140
+
141
+ /**
142
+ * Result of an atomic push. `applied` means every ref is `ok`; `rejected`
143
+ * means no ref changed on the remote, and `refs` says why.
144
+ */
145
+ export interface IGitManagerAtomicPushResult extends IGitManagerRepositorySelector {
146
+ status: 'applied' | 'rejected';
147
+ /** One result per requested update, in request order. */
148
+ refs: IGitManagerAtomicPushRefResult[];
149
+ }
150
+
77
151
  /**
78
152
  * The object database of one repository when it was measured. Objects of
79
153
  * alternate object stores are not counted.
package/ts/data/index.ts CHANGED
@@ -2,5 +2,6 @@ export * from './codefeed.js';
2
2
  export * from './forgeinventory.js';
3
3
  export * from './forgesourceinventory.js';
4
4
  export * from './gitmanager.js';
5
+ export * from './origin.js';
5
6
  export * from './public.js';
6
7
  export * from './runner.js';
@@ -0,0 +1,33 @@
1
+ /** Kinds of source entity an import records its origin for. */
2
+ export type TOriginEntityKind = 'repository';
3
+
4
+ /**
5
+ * Identity of the source entity a native entity was imported from.
6
+ *
7
+ * It names the source by stable identifiers only. It carries no URLs, paths,
8
+ * configuration or run IDs, digests, or authority: it neither locates the
9
+ * source nor grants access to it.
10
+ */
11
+ export interface IOriginRef {
12
+ /** Operator-minted instanceId of the forge connection the entity was imported from. */
13
+ instanceId: string;
14
+ entityKind: TOriginEntityKind;
15
+ /** Source row ID as an opaque string; for a Gitea repository, its decimal repository ID. */
16
+ entityId: string;
17
+ /**
18
+ * Source ID of the parent when entity IDs are parent-scoped; otherwise null.
19
+ * Null for repositories, because Gitea repository IDs are unique within an
20
+ * instance. Later entity kinds define their parent.
21
+ */
22
+ parentId: string | null;
23
+ }
24
+
25
+ /**
26
+ * Where a native entity came from: created natively, imported from a
27
+ * recorded source, or not known, for example for an entity that predates
28
+ * origin tracking. `unknown` must never be read as `native`.
29
+ */
30
+ export type TOriginState =
31
+ | { kind: 'native' }
32
+ | { kind: 'imported'; origin: IOriginRef }
33
+ | { kind: 'unknown' };