@foss.global/interfaces
v2.7.0
Published
Shared TypeScript interfaces and TypedRequest contracts for the foss.global Git platform ecosystem.
Maintainers
Readme
@foss.global/interfaces
Shared TypeScript DTOs and TypedRequest contracts for the foss.global Git platform ecosystem.
This package intentionally contains contracts only. Runtime forge adapters belong in @foss.global/codefeed, and the Git storage/protocol engine belongs in @foss.global/gitmanager.
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
Install
pnpm add @foss.global/interfacesUsage
import type { data, requests } from '@foss.global/interfaces';
const repo: data.IPublicRepo = {
id: 1,
org: 'foss.global',
name: 'interfaces',
slug: 'foss.global/interfaces',
orgAvatarUrl: '',
description: 'Shared contracts',
language: 'TypeScript',
htmlUrl: 'https://code.foss.global/foss.global/interfaces',
cloneUrl: 'https://code.foss.global/foss.global/interfaces.git',
sshUrl: 'ssh://[email protected]:29419/foss.global/interfaces.git',
starsCount: 0,
forksCount: 0,
watchersCount: 0,
openIssuesCount: 0,
openPrCount: 0,
releaseCount: 0,
size: 0,
defaultBranch: 'main',
updatedAt: new Date().toISOString(),
createdAt: new Date().toISOString(),
archived: false,
topics: [],
};
type PublicOverviewRequest = requests.IReq_PublicOverview;Runner and CI contracts
Runner protocol v1 is exposed through runnerProtocolVersion. The package root and the data namespace both export the complete runner and CI DTO set:
import {
runnerProtocolVersion,
type IClaimJobResponse,
type ICiEnqueueJobRequest,
type IRegisterRunnerRequest,
} from '@foss.global/interfaces';
const registration: IRegisterRunnerRequest = {
registrationRequestId: 'registration-1',
protocolVersion: runnerProtocolVersion,
runnerVersion: '0.1.0',
name: 'linux-amd64-1',
labels: ['linux', 'amd64'],
capabilities: {
executor: 'oci',
runtime: 'docker',
networks: ['none', 'bridge'],
sourceArchives: ['tar.gz'],
artifacts: false,
caches: false,
serviceContainers: false,
},
};
const enqueue: ICiEnqueueJobRequest = {
idempotencyKey: 'build-main-1',
tenantId: 'foss.global',
repositoryId: 'foss.global/interfaces',
requiredLabels: ['linux', 'amd64'],
job: {
image: 'node:24',
command: ['pnpm', 'test'],
network: 'none',
},
};
type ClaimedJob = IClaimJobResponse;The runner lifecycle contracts cover registration, sessions, runner and job heartbeats, claim/lease identity, fencing tokens, ordered log chunks, completion, abandonment, and recovery. The CI control-plane contracts cover job enqueue and summaries, log pages, cancellation, and runner drain state.
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.
GitManager ref inventory contracts
IGitManagerRefRequest, IGitManagerRef, and TGitManagerRefInventoryResult
describe a complete, paginated ref inventory. Without prefixes, every ref
under refs/ is listed, including notes, pull, keep-around, and
provider-internal namespaces. HEAD is reported separately in head. Annotated
tags carry their fully peeled object. Symbolic refs carry their target ref
name; a symbolic ref whose target does not resolve is still listed, with a null
objectId and objectType.
import type {
IGitManagerRef,
IGitManagerRefRequest,
TGitManagerRefInventoryResult,
} from '@foss.global/interfaces';
declare function listRefs(
request: IGitManagerRefRequest,
): Promise<TGitManagerRefInventoryResult>;
const collectRefs = async (): Promise<IGitManagerRef[]> => {
const refs: IGitManagerRef[] = [];
let cursor: string | undefined;
while (true) {
const result = await listRefs({ org: 'foss.global', repo: 'interfaces', cursor });
if (result.status === 'stale') {
refs.length = 0;
cursor = undefined;
continue;
}
refs.push(...result.refs);
if (result.pagination.status === 'exhausted') {
return refs;
}
cursor = result.pagination.cursor;
}
};
// A complete ref name as the only prefix is an exact lookup.
const main = await listRefs({
org: 'foss.global',
repo: 'interfaces',
prefixes: ['refs/heads/main'],
});Prefixes match whole path components, so refs/heads/ma does not select
refs/heads/main. Overlapping prefixes select their de-duplicated union, and
an empty prefixes array is rejected as invalid. Pages are sorted by ref name
in byte order and each carries inventoryDigest, the SHA-256 of the complete
selection defined on IGitManagerRefInventoryPage. A cursor is opaque and
bound to the repository, the prefix set, and that digest. When the selected
refs or HEAD change between pages, the next call returns status: 'stale'
instead of a page that would mix two states; the caller restarts without a
cursor. A cursor is a transport continuation, not a durable replication
checkpoint.
GitManager remote transfer and size contracts
IGitManagerImportMirrorRequest and IGitManagerRefreshMirrorRequest take
IGitManagerRemoteTransferOptions: an optional credential
(TGitManagerRemoteCredential, HTTP Basic), optional caCertificates (PEM,
used as Git's CA bundle for that transfer) and an optional timeoutMs
(default 120000, at most 21600000). A credential reaches Git only through the
Git process environment as an Authorization header, so it never appears in
the remote URL, on a command line, in the repository's Git config, or in an
error. It requires an https remote without user information, and Git does
not follow redirects while it carries one. A refresh reuses the mirror's stored
remote URL.
IGitManagerRepositorySize measures a repository's object database:
objectCount distinct objects, objectBytes (their uncompressed sizes, which
do not depend on packing) and storageBytes (every file of the object
database, which does).
GitManager atomic push and default branch contracts
IGitManagerAtomicPushRequest pushes IGitManagerAtomicPushRefUpdates from a
managed repository to remoteUrl as one transaction: the remote applies every
update or none, and a remote that does not advertise the atomic capability is
refused rather than pushed to ref by ref. Every update is leased:
expectedOldObjectId is the object the remote ref must point at now (null to
create a ref that must not exist), and newObjectId is the object to set (null
to delete). The URL is used for that push only; it must be https, or http to
a loopback host. The transfer options are those of importMirror, except that
a push credential is also accepted for loopback http.
IGitManagerAtomicPushResult is applied when every ref is ok and
rejected when no ref changed. Each IGitManagerAtomicPushRefResult is ok,
stale (the lease failed) or rejected (a hook, ref protection, or another
ref of the same push failed), with the remote's reason as message. Every ref
that is not ok also carries a classified TGitManagerAtomicPushRefReason:
stale-lease, atomic-collateral (refused only because another ref failed),
transaction-failed (the remote could not commit, typically a concurrent
change; read the remote back), hook-declined, non-fast-forward,
local-rejected or remote-rejected for any other refusal.
IGitManagerSetDefaultBranchRequest points a repository's HEAD at an existing
branch, named as in IGitManagerRepositoryInfo.defaultBranch. With
allowUnborn: true the branch may not exist yet: HEAD then names it unborn
until a push creates it, so that one atomic push can create the new default
branch and delete the old one, which Git refuses while HEAD names the old one.
An IGitManagerProtectedRefViolation names a ref update that the protected ref
rules refuse and the TGitManagerProtectedRefViolationRule it breaks:
create, delete, force-push (the old object is not an ancestor of the new
one) or not-a-commit. GitManager decides it with the same check its
pre-receive hook enforces.
Origin contracts
TOriginState records where a native entity came from: native, imported
with an IOriginRef, or unknown, which never means native. An IOriginRef
names the source by the operator-minted forge connection instanceId, the
entityKind (repository), the source entityId (a Gitea repository's
decimal ID) and parentId (null for repositories, whose Gitea IDs are unique
per instance). It carries no URLs, paths, configuration or run IDs, digests, or
authority.
Forge inventory contracts
IForgeInventoryReport, IForgeInventoryPage<TItem>, IForgeInventoryNamespace,
IForgeInventoryRepository and IForgeInventoryIssue describe operator inventory observations. They
are exported from both the package root and data. This package supplies types;
it does not scan a forge or validate network responses.
Stable provider identifiers are opaque strings qualified by instance and ID namespace. Mutable paths remain separate segment arrays, preserving GitLab subgroups and literal hyphens. A source without a stable identifier reports an unresolved identity. URLs must be credential-free, and inventory responses need operator authorization rather than anonymous public exposure.
Issue observations separate the provider row ID from its repository-local
number (GitLab iid) and retain the repository identity. They preserve empty
body text, unknown metadata, open/closed state, provider issue classification,
confidentiality, reported author identity and provider content timestamps.
The reported author does not prove original attribution for previously imported
issues. Comments, labels, milestones, assignees, attachments and history require
their own inventory and preservation work; this metadata DTO does not claim
that those collections or external writes are implemented.
Every canonical entity class has an explicit capability and collection result,
including classes not inspected or unavailable. Additional provider features
have their own entries. enumerated means the selected collection was exhausted
for its recorded visibility scope; a public or caller-visible live scan does
not establish a complete frozen migration inventory. Page continuation,
exhaustion, and interrupted enumeration have distinct discriminated shapes.
Counts and byte quantities use nonnegative decimal strings to avoid JSON integer precision loss. Unknown size differs from zero, and estimated repository storage size is not the size of a future Git push. Runtime adapters must validate values, scope consistency, capability/result agreement, cursor binding, diagnostics, and authorization. These DTOs do not establish replication authority, historical import fidelity, checksummed manifests, or durable recovery checkpoints.
Forge source inventory contracts
IForgeSourceInventoryReport is the authenticated, read-only measurement of a
source forge before its one-time migration, read with a site administrator's
token. It counts users, organizations, teams, memberships, keys, packages by
type, and per repository the Git refs and objects, LFS objects, issues, pull requests,
comments, reviews, reactions, attachments, releases (drafts included) with
asset bytes, wiki pages, access settings, webhooks, push mirrors, Actions
settings, and the Actions runs and artifacts that are archived rather than
migrated.
Every count is a TForgeSourceMeasure: complete with a decimal-string value,
partial with the value observed before a retryable failure, or notMeasured
when no read was attempted. inventoryComplete is true only when discovery
finished and no measure is partial or not measured; incompleteReasons lists
why not. limitations names source data the provider exposes to no
administrator read and that is reissued rather than migrated, such as Gitea's
user-scoped Actions secrets; everything readable is a measure instead.
Reasons are sanitized text, never raw response bodies or URLs.
Git counts other than the forge-reported size, and LFS counts, are read at the
Git level from a mirror clone of every advertised ref: refs by namespace,
distinct objects and their uncompressed bytes, and the LFS objects that
pointers in any reachable revision reference. LFS objects are checked through
the forge's LFS batch API and split into held objects with their bytes and
missingObjects, which cannot be migrated.
The same mirror records the repository's head, an IForgeSourceRepositoryHead:
the ref HEAD names as target (null when HEAD is detached or not symbolic) and
whether it resolves. An empty repository's HEAD is unborn and does not
resolve; in any other repository a HEAD that does not resolve names a missing
branch, such as a default branch deleted at the source, and an import's HEAD
diverges from the source at apply time until the source names an existing
branch. A target that differs from the API's defaultBranch shows that the
forge's setting and its Git HEAD disagree. head is null when the mirror was
not measured and absent in reports from generators that predate it.
Beside its counts, a repository records each release as an
IForgeSourceRelease in releaseRecords, drafts included: the source ids,
tag, target, name, body, flags, the forge's creation and publication times, an
IForgeSourceReleaseAuthor snapshot (the source account's id and login, never
a native user) and its IForgeSourceReleaseAssets with their storage uuid,
name as stored, size and download count. The forge exposes no asset digest, so
none is recorded; a consumer verifies content itself. The download count moves
with every download and never decides whether a release changed.
protections records, as read, the branch and tag protection rules that
access counts: an IForgeSourceBranchProtection keeps the rule name (an exact
name or a glob), whether anyone may push or force-push, every allowlist with
its switch, and the review, status check, signing and file pattern
restrictions; an IForgeSourceTagProtection keeps its name pattern and
allowlist. Whether a rule can be enforced natively is the consumer's verdict.
Releases, assets and tag rules sort by numeric id, branch rules by name in
code-unit order. Both are null when their counts are not complete and absent
in reports from generators that predate them.
Owners are a TForgeSourceOwnerInventory union: an organization carries its
members, teams, team memberships and repository grants, labels and Actions
secret count; a user carries its account flags and SSH and GPG key counts.
Both carry repositories, webhooks, Actions variables, runners and packages by
type. totals.owners sums the owner-level counts; the repository-shaped totals
sum repositories only.
A run first reads IForgeSourceInventoryDiscovery, then measures independent
TForgeSourceInventoryUnits (the instance, each owner and each repository). A
failed unit, or one holding a partial measure, is measured again on resume.
Discovery records each repository's id as a decimal string and its unit
carries it, so a unit whose name now answers with another id fails instead of
measuring the repository that took the name. id is absent in discoveries
from generators that predate it; a consumer that keys on ids refuses those.
IForgeSourceInventory is deterministic: it carries no run timestamps (the
source's own times, such as release creation, are source state), owners sort
by kind and name, repositories by owner and name. The report adds
collisionCheck, the source owner and repository names that already exist
natively, exactly or case-insensitively, sorted by subject, source and native
name. A report is a complete planning basis only when inventoryComplete is
true and the collision check ran.
A report never contains secret values, credentials, tokens, private keys, Actions secret or variable values, webhook secrets, or mirror remote URLs.
Exports
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.requests: TypedRequest contracts forcodefeed,publicOverview,publicOrg,publicRepo,publicFile, andpublicCommits.- Barrel exports: all public data and request interfaces are also exported from the package root.
Testing
pnpm test
pnpm run buildLicense and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
Company Information
Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at [email protected].
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
