# Project Delivery Specification Project delivery reconciles Forgejo source into published artifacts. A `ProjectDelivery` declares the desired result, a controller resolves continuous refs and accepts declared point revisions, and a cluster-owned Argo `WorkflowTemplate` defines all execution. ## Delivery declaration ```mermaid flowchart LR D[ProjectDelivery] C[Delivery controller] T[Cluster-owned WorkflowTemplate] W[Workflow] V[Vault and VSO] A[Build cache] P[Declared publication targets] D --> C C -->|template reference and immutable input| W T --> W V -->|stage-scoped Secrets| W W <-->|cache pull, export, and cleanup| A W --> P ``` ```yaml apiVersion: delivery.quorate.dev/v1alpha1 kind: ProjectDelivery metadata: name: example spec: source: repository: https://git.quorate.dev/example/project continuous: ref: refs/heads/main paths: [packages/example] targets: - kind: QuayOCI repository: quorate/project - kind: ExternalOCI registry: docker.io repository: example/project - kind: ForgejoRelease repository: https://git.quorate.dev/example/project workflowTemplateRef: name: example-delivery ``` `source` contains exactly one delivery mode: | Mode | Selector | Trigger identity | | ------------ | --------------------------------------------------------------------- | ------------------------------- | | `continuous` | One complete ref; optional exact paths and positive-duration debounce | Commit SHA or selected Git tree | | `point` | A non-empty set of full commit SHAs | Full commit SHA | `continuous.paths` contains exact repository-relative file or directory paths. When present, the trigger identity is the selected Git tree state rather than the commit SHA. Point delivery declares immutable revisions: ```yaml source: repository: https://git.quorate.dev/example/project point: revisions: - 0123456789abcdef0123456789abcdef01234567 - 89abcdef0123456789abcdef0123456789abcdef ``` `status.points` records point revisions, Workflow identities and phases, and delivery results. Point revisions are consumed directly without ref enumeration or resolution. `source.repository` identifies the Forgejo repository containing the selected source. Its authority is declaration data rather than an admission boundary. `targets` is a non-empty set of workflow-defined publication declarations. The controller treats each declaration as opaque JSON and passes it unchanged. The referenced `WorkflowTemplate` defines and validates the target kinds and fields it supports. `workflowTemplateRef` names a `WorkflowTemplate` in the `ProjectDelivery` namespace. Admission rejects cross-namespace references and malformed source selectors. `delivery.quorate.dev/retry` names an owned terminal Workflow. ## Qualification interface | Field | Type | Default | Model binding | | ----------------------------------------- | ------------------------------------ | ------------ | -------------------------------------- | | `spec.qualification` | Optional object | Absent | Configured resources form `Deliveries` | | `workflowTemplateRef.name` | Same-namespace WorkflowTemplate name | Required | Workflow template | | `mode` | `Qualification!Policies` | `ManualOnly` | `policy[delivery]` | | `interval` | Duration | `0s` | `Interval[delivery]` | | `delivery.quorate.dev/qualify` annotation | `/` | Absent | `request[delivery]` | | Workflow interface | Value | | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | Input: `source-repository`, `source-ref`, `source-revision`, `targets` | Selected successful build's parameters | | Input: `delivery-result` | Selected build's opaque publication result | | Model `Input(delivery, build)` | Tuple of those parameters and publication result | | Output: `qualification-result` | Workflow-defined result identifying tested source, artifacts, and retained reports | | Result interpretation | Qualification WorkflowTemplate | ## Reconciliation and execution ### Authority | Artifact | Authority | | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | Project Delivery specification | Declaration and status schema, Workflow interface, objectives, and security | | [Project Delivery state model](project-delivery/ProjectDelivery.tla) | Attempt eligibility and history, controller submission, Argo execution synchronization, persistence, lifecycle, and build concurrency | | [Qualification state model](project-delivery/Qualification.tla) | Qualification eligibility, annotation consumption, input capture, interval, and global execution slot | ### Build workflow interface The diagram is the standard `ProjectDelivery` build workflow DAG shape; deviation from it requires evidence that substantiates the deviation. ```mermaid flowchart LR T[Toolchain pull] --> B[Build] C[Cache pull] --> B S[Source pull] --> B B --> E[Cache export and cleanup] B --> P[Publish to declared targets] ``` | Parameter | Value | | ------------------- | ------------------------------------------------------------- | | `source-repository` | Declared repository URL | | `source-ref` | Complete selected continuous ref, or empty for point delivery | | `source-revision` | Resolved full commit SHA | | `targets` | Declaration-provided JSON target set | ### Delivery objectives Measure delivery elapsed time from Workflow `startedAt` to terminal `finishedAt`, excluding intervals when waiting on WAN is the sole active work. | Cache state | Requirement | | ----------- | -------------------------------------------- | | Cold | No reusable build state; within 900 seconds. | | Warm | Reusable build state; within 300 seconds. | The `WorkflowTemplate` owns the DAG: | Concern | Owner | | ----------------------------------------------------- | -------------------------- | | Stages, actions, dependencies, retries | Argo `WorkflowTemplate` | | Build and assembly image selection | Argo `WorkflowTemplate` | | Action and builder image preparation | Cluster | | Stage Secret references | Argo `WorkflowTemplate` | | Secret material and projection | Vault and VSO | | Stage egress | Kubernetes `NetworkPolicy` | | Continuous source selection and duplicate suppression | Delivery controller | | Cache creation, invalidation, cleanup, and layout | Argo `WorkflowTemplate` | | Cache contract | Value | | -------------- | ------------------------------------------------ | | Prefix | `projects///cache//` | | Manifest | `_latest.json` | | Pull | `cacheVersion` and `inputHashes` match | | Export | Replace `_latest.json` | | Cleanup | Remove unreferenced payloads during cache export | | Controller | No cache inspection or enforcement | | `_latest.json` field | Type | Value | | -------------------- | ------- | --------------------------------------- | | `schemaVersion` | Integer | `1` | | `cacheVersion` | String | Workflow cache version | | `inputHashes` | Object | Repository-relative path to SHA-256 map | | `payloadKey` | String | `objects/.tar.zst` | ### Workflow security requirements Every delivery `WorkflowTemplate` and its supporting namespace resources meet these requirements: | Boundary | Requirement | | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Ownership | Commands, images, target interpretation, Secret references, and pod security are cluster-owned | | Supply chain | Action and executor images use immutable digests of latest stable releases; deprecated APIs and components are forbidden; source uses the selected full SHA | | Runtime | `gvisor` where non-cluster-owned code executes; restricted Pod Security; non-root; `RuntimeDefault`; no privilege escalation or capabilities; read-only root filesystem | | Host | No privileged container, host namespace, `hostPath`, device, or runtime socket | | Kubernetes | Action containers receive no Kubernetes credential; executor tokens are bound, short-lived, and limited to Workflow task results and artifact GC | | Delivery stages | A stage is a Pod boundary only when its network, credential, input, or output access differs. Actions with identical access execute in the same Pod. | | Network | Default deny; each stage permits only executor traffic, artifact handoff, and its declared endpoints | | Credentials | Vault to VSO to one read-only stage mount; never parameters, environment, commands, logs, or artifacts | | Handoff | Stages exchange state through the Workflow PVC; publishers transfer immutable output | | Cache | Cache reads and writes use stage-scoped credentials | | Ephemeral state | One ephemeral PVC is the sole working data plane for the build Workflow lifetime | | Build interface | Repository supplies source only; OCI delivery uses cluster-owned apko configuration | | Resources | CPU requests, memory requests, and memory limits on every pod | Publication credentials are destination-native, restricted to the declared destination, and mounted only in the publication stage. Project-delivery credentials are never shared with Smeltery. ## Scope Delivery succeeds when every declared target reports successful publication of the Workflow's immutable output. | Included | Excluded | | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | Source-ref observation and immutable revision selection | Repository visibility | | Duplicate suppression and Workflow creation | Vulnerability policy and scan gating | | Project-specific build, test, assembly, and publication DAGs | Candidate repositories and promotion | | Manual and interval-controlled qualification of published artifacts | Deployment approval and rollout gating | | Publication digests, checksums, URLs, and Workflow status | Deployment and Flux manifest changes | | Stage isolation, credentials, and network policy | Per-repository publisher identities and grants; published artifact retention and registry garbage collection |