@ship.zone/ci-spec
@ship.zone/ci-spec defines the ship.zone CI standard: the language-neutral workflow and runner contracts between a coordinator and its runners. The normative artifacts are OpenAPI, JSON Schema, protocol prose, and conformance cases. TypeScript exports provide only the specification version, draft metadata, identifier lists, failure codes, reserved names, and asset locations.
The current specification is a draft. It is intentionally incompatible with the legacy internal runner protocol it replaces and must not be treated as stable until independent implementations pass the conformance suite.
Versioning
The package version is the specification version, and it is the only version in the specification. A ci_actions.yml references it once, as its top-level spec:
spec: 2.0.0
Compiled jobs and runner protocol messages carry the same spec field. An implementation built against version I accepts a declared version D when both have the same major version and D is not newer than I; the rule is defined in spec/runner-protocol.md and fixed by conformance/version-cases.json. Every incompatible change is a new major version, and additions arrive as new minor versions: a workflow that uses a construct introduced in a later minor version declares that version or a later one. Version 2.0.0 renames the package and its normative identifiers (see Migrating from @foss.global/ci-spec), removes the 1.x cross-version rules, and completes the compilation rules: one stable failure code per compilation failure with a fixed precedence, a stricter YAML subset, the derivation of every compiled job member, and the identities of expanded nodes. Version 2.1.0 adds job failure codes: every coherence rule of a compiled job has exactly one code, and a job that is not coherent carries the code of the first rule it violates (see Job Coherence in spec/runner-protocol.md); it also exports the reserved names as constants. Version 2.1.1 clarifies compilation: it states the YAML 1.2 character, byte order mark, escape, and document counting rules, bounds collection nesting to 64, and counts the 16 KiB command argument limit in UTF-8 bytes. Documents written against 2.0.0 stay valid. The history of the 1.x rules is in the changelog.
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 @ship.zone/ci-spec
Migrating from @foss.global/ci-spec
Version 2.0.0 moves the standard from @foss.global/ci-spec to @ship.zone/ci-spec. Renaming normative identifiers is an incompatible change, so a 1.x implementation does not accept a 2.0.0 document, and a 2.0.0 implementation does not accept a 1.x document: both sides move to the same major version together.
- Replace the dependency:
pnpm remove @foss.global/ci-spec && pnpm add @ship.zone/ci-spec, and change every import and asset subpath from@foss.global/ci-specto@ship.zone/ci-spec. The exported names and subpaths are unchanged. - Declare
spec: 2.0.0in everyci_actions.yml, and send and expectspec2.0.0 in compiled jobs and runner protocol messages. - Rename the normative identifiers:
| 1.x | 2.0.0 |
|---|---|
npm package @foss.global/ci-spec |
@ship.zone/ci-spec |
step environment FOSS_CI_MATRIX_JSON |
SHIPZONE_CI_MATRIX_JSON |
step environment FOSS_CI_INPUTS_JSON |
SHIPZONE_CI_INPUTS_JSON |
reserved environment prefix FOSS_CI_* |
SHIPZONE_CI_* |
reserved image label prefix global.foss.ci. |
zone.ship.ci. |
schema $id https://foss.global/spec/ci/ci_actions.schema.json |
https://ship.zone/spec/ci/schemas/ci_actions.schema.json |
schema $id https://foss.global/spec/ci/runner-job.schema.json |
https://ship.zone/spec/ci/schemas/runner-job.schema.json |
- Adopt the 2.0.0 compilation rules (see
spec/ci-actions.md): the YAML subset now rejects keys that do not resolve to strings (quote a key such as1) and every explicit tag, including!!str; a job that declares artifacts or caches beyond its resolved permissions fails compilation instead of compiling; and every compilation failure carries one of the codes of Compilation Failures. - Register schemas under their
$idonly. Every normative JSON document is identified byhttps://ship.zone/spec/ci/followed by its package path, so the OpenAPI reference../schemas/runner-job.schema.jsonresolves to the runner job schema's$idwhen the OpenAPI components are registered underhttps://ship.zone/spec/ci/spec/runner.openapi.json:
const ajv = new Ajv2020({ strict: true });
ajv.addSchema(runnerJobSchema); // registered under its $id
ajv.addSchema({
$schema: 'https://json-schema.org/draft/2020-12/schema',
$id: 'https://ship.zone/spec/ci/spec/runner.openapi.json',
$defs: openApi.components.schemas, // with #/components/schemas/ rewritten to #/$defs/
});
Normative Artifacts
spec/runner-protocol.md: runner protocol semantics, security, lifecycle, and limits.spec/runner.openapi.json: runner-facing HTTP and streaming API.spec/ci-actions.md: repository workflow parsing and compilation rules.schemas/runner-job.schema.json: compiled job wire schema.schemas/ci_actions.schema.json: repository-rootci_actions.ymlschema.conformance/runner-cases.json: implementation-independent behavior cases.conformance/runner-messages.json: schema-bound runner wire-message fixtures.conformance/digest-cases.json: canonical JSON and digest fixtures.conformance/archive-cases.json: byte-identical gzip/tar acceptance and rejection vectors.conformance/version-cases.json: specification version compatibility outcomes.conformance/compile-cases.jsonand its schemaconformance/compile-cases.schema.json: the compilation failure codes in precedence order, trigger pattern and tag version vectors, the expected code of every invalid workflow fixture, and compile vectors that bind a workflow, run context, and deployment policy to a failure code, to not-triggered, or to the compiled nodes and plan digests. The package runs no compiler; its tests check that every vector is schema-valid and internally coherent, and compilers run the vectors.conformance/runner-job-cases.jsonand its schemaconformance/runner-job-cases.schema.json: the job failure codes in precedence order and the expected outcome of every runner job fixture and of inline version cases.conformance/ci-actions/andconformance/runner-jobs/: valid and invalid data fixtures.conformance/ci-actions/compile-invalid/holds schema-valid workflows that a compiler must reject; each is bound to a case inrunner-cases.json.conformance/runner-jobs/incoherent/holds schema-valid compiled jobs that fail a later rule of Job Coherence; each is bound to a case inrunner-job-cases.json.
The package exports these raw asset subpaths:
@ship.zone/ci-spec/runner.openapi.json@ship.zone/ci-spec/runner-protocol.md@ship.zone/ci-spec/ci-actions.md@ship.zone/ci-spec/runner-job.schema.json@ship.zone/ci-spec/ci_actions.schema.json@ship.zone/ci-spec/runner-cases.json@ship.zone/ci-spec/runner-messages.json@ship.zone/ci-spec/digest-cases.json@ship.zone/ci-spec/archive-cases.json@ship.zone/ci-spec/version-cases.json@ship.zone/ci-spec/compile-cases.json@ship.zone/ci-spec/compile-cases.schema.json@ship.zone/ci-spec/runner-job-cases.json@ship.zone/ci-spec/runner-job-cases.schema.json@ship.zone/ci-spec/conformance/ci-actions/*@ship.zone/ci-spec/conformance/runner-jobs/*
TypeScript metadata exposes package-root-relative asset locations, failure codes, and reserved names separately:
import {
ciSpecAssetPaths,
ciSpecVersion,
compilationFailureCodes,
executionProfileIdentifiers,
maximumArchivePathMetadataBytes,
reservedEnvironmentPrefix,
reservedImageLabelPrefix,
runnerJobFailureCodes,
runnerProtocolBasePath,
} from '@ship.zone/ci-spec';
console.log(ciSpecVersion); // the installed package version, e.g. 2.0.0
console.log(runnerProtocolBasePath); // /api/runner
console.log(executionProfileIdentifiers.imageBuild); // oci-image
console.log(maximumArchivePathMetadataBytes); // 134217728
console.log(ciSpecAssetPaths.runnerOpenApi);
console.log(compilationFailureCodes[0]); // { code: 'workflow_too_large', layer: 'source' }
console.log(runnerJobFailureCodes[1]); // job_schema_invalid
console.log(reservedEnvironmentPrefix); // SHIPZONE_CI_
console.log(reservedImageLabelPrefix); // zone.ship.ci.
Generated language bindings are deliberately not normative. Implementations must follow the published OpenAPI, JSON Schemas, prose rules, and conformance cases.
Design Boundary
Coordinators read ci_actions.yml from the exact repository commit, validate and compile it, resolve policy and trust, and issue immutable jobs. Runners never parse repository workflow files and never receive Git repository credentials.
Three execution profiles exist. oci runs argument-array steps in a digest-pinned or candidate image. vm runs the same kind of steps as root inside one microVM guest per attempt, for jobs that need a container engine or kernel facilities, on linux platforms and darwin/arm64. oci-image builds one single-platform OCI image in a fresh microVM per attempt on a dedicated builder runner and pushes it by digest with an attempt-scoped grant; the coordinator assembles the multi-platform candidate index. A job can be restricted to runs of chosen trigger kinds, for example to tag runs only. Secrets a repository marks protected reach only jobs of protected tag runs, and private npm scopes are read with attempt-scoped read-only grants that only trusted runs receive. Jobs have no network unless they declare an egress allowlist; loopback inside an attempt's own network namespaces is always available and never shared with another attempt. Jobs may declare memory, CPU, PID, shared-memory, and workspace ceilings, and runners may advertise the maxima they enforce. Releases run in CI: the coordinator qualifies candidates and artifacts and performs every publication with credentials that never reach a job, in the default or declared order; release assets are the files of job artifacts and are verified by reading them back from the release. Further execution profiles are added as new profile identifiers in a later specification version.
Verification
pnpm run lint:openapi
pnpm run test:types
pnpm test
pnpm run build
License 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 hello@task.vc.
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.