|
1 |
+ |
# OxygenFlow (flow) — Deterministic Execution & Provenance Pipeline Specification |
|
2 |
+ |
|
|
3 |
+ |
| | | |
|
4 |
+ |
|---|---| |
|
5 |
+ |
| **Format version** | 1 | |
|
6 |
+ |
| **Date** | 2026-09-28 | |
|
7 |
+ |
| **Status** | Draft 0.1 | |
|
8 |
+ |
| **Target VCS** | Oxygen (oxy) Draft 0.8i | |
|
9 |
+ |
| **Audience** | Implementers, Security Architects, and Systems Engineers | |
|
10 |
+ |
|
|
11 |
+ |
|
|
12 |
+ |
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be |
|
13 |
+ |
interpreted as described in RFC 2119. |
|
14 |
+ |
|
|
15 |
+ |
## 1. Overview and Core Invariants |
|
16 |
+ |
|
|
17 |
+ |
OxygenFlow (flow) is a content-addressed, hermetic execution engine, runner system, |
|
18 |
+ |
and pipeline language designed natively for the Oxygen (oxy) version control |
|
19 |
+ |
system. |
|
20 |
+ |
|
|
21 |
+ |
Existing runner engines (GitHub Actions, GitLab CI, Forgejo Runner) suffer from |
|
22 |
+ |
structural flaws: |
|
23 |
+ |
1. Workspace Bloat: Full clones, index unpacks, and checkout scans dominate I/O. |
|
24 |
+ |
2. String Injection: Shell interpolation within untyped YAML files produces |
|
25 |
+ |
expression injection and command execution exploits. |
|
26 |
+ |
3. Decoupled Supply Chain: Attestations (SLSA, in-toto, Cosign) exist outside |
|
27 |
+ |
the VCS, relying on external registries rather than native repository trust. |
|
28 |
+ |
4. Coarse Caching: Opaque tarballs keyed by arbitrary string hashes fail to |
|
29 |
+ |
leverage commutative history or granular dependency graphs. |
|
30 |
+ |
|
|
31 |
+ |
OxygenFlow solves these liabilities through direct integration with Oxygen: |
|
32 |
+ |
- Zero-Copy Workspaces: Jobs mount workspaces directly from Oxygen's FastCDC- |
|
33 |
+ |
chunked, BLAKE3-addressed Content-Addressable Store (CAS) using Copy-on-Write |
|
34 |
+ |
(COW) overlays. |
|
35 |
+ |
- Commutative History & Impact Trees: Pipelines evaluate over change closures |
|
36 |
+ |
rather than linear snapshot sequences. Commuting changes automatically reuse |
|
37 |
+ |
cached execution receipts without redundant re-execution. |
|
38 |
+ |
- Micro-Engine Sandboxing: Jobs run inside isolated environments (WASM, gVisor, |
|
39 |
+ |
or MicroVMs) with strict, deny-by-default capabilities and no ambient |
|
40 |
+ |
network egress. |
|
41 |
+ |
- Native Cryptographic Provenance: Provenance and execution receipts are |
|
42 |
+ |
generated outside the untrusted guest, encoded as deterministic CBOR, and |
|
43 |
+ |
signed using composite Ed25519 + ML-DSA-65 keys as native Oxygen Attest |
|
44 |
+ |
objects governed by in-repository Policy rules. |
|
45 |
+ |
|
|
46 |
+ |
## 2. Threat Model and Security Architecture |
|
47 |
+ |
|
|
48 |
+ |
### 2.1 Adversaries |
|
49 |
+ |
- Untrusted Proposal Author: Submits code to an open repository containing |
|
50 |
+ |
malicious build configurations intended to escape the runner, exfiltrate |
|
51 |
+ |
secrets, or corrupt shared worker caches. |
|
52 |
+ |
- Malicious Dependency / Upstream: Third-party dependencies invoked during |
|
53 |
+ |
build time attempting out-of-band network calls or host file modification. |
|
54 |
+ |
- Compromised Runner / Malicious Worker: An execution node attempting to |
|
55 |
+ |
forge successful build receipts or inject backdoors into published artifacts. |
|
56 |
+ |
|
|
57 |
+ |
### 2.2 Security Invariants |
|
58 |
+ |
- I1 Deny-by-Default Execution: Sandboxes possess no network interfaces |
|
59 |
+ |
(excluding loopback when requested) and no host filesystem access unless |
|
60 |
+ |
explicitly granted in policy-signed configuration. |
|
61 |
+ |
- I2 Injection-Free Invocation: Configuration parsing directly yields an argv |
|
62 |
+ |
string vector executed via execve(). Shell interpretation (/bin/sh -c) does |
|
63 |
+ |
not exist. |
|
64 |
+ |
- I3 Host-Enforced Provenance: The running payload cannot author, inspect, or |
|
65 |
+ |
alter its own provenance statement. Provenance is emitted solely by the |
|
66 |
+ |
isolation hypervisor boundary. |
|
67 |
+ |
- I4 Cryptographic Identity & Authorization: Runners execute using an Oxygen |
|
68 |
+ |
Identity whose KeyId is enrolled as a delegate in the repository's Policy. |
|
69 |
+ |
Unenrolled runners cannot publish recognized attestations or advance gates. |
|
70 |
+ |
|
|
71 |
+ |
## 3. The OxygenFlow Configuration Language (.flow) |
|
72 |
+ |
|
|
73 |
+ |
Pipelines are declared in KDL syntax within .flow/pipeline.kdl at the |
|
74 |
+ |
repository root. KDL provides strict typing, structured nesting, and rejects |
|
75 |
+ |
arbitrary text macro expansion. |
|
76 |
+ |
|
|
77 |
+ |
### 3.1 Pipeline Specification Schema |
|
78 |
+ |
|
|
79 |
+ |
```kdl |
|
80 |
+ |
schema-version 1 |
|
81 |
+ |
|
|
82 |
+ |
// Define the hermetic execution boundary |
|
83 |
+ |
sandbox "rust-builder" { |
|
84 |
+ |
runtime "microvm" // Options: "wasm" | "gvisor" | "microvm" |
|
85 |
+ |
rootfs "cas://blob/9b5c2a1e8f3d4e7a6b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a" |
|
86 |
+ |
memory-limit "4GiB" |
|
87 |
+ |
cpu-limit 4 |
|
88 |
+ |
network "isolated" // Options: "isolated" | "loopback" | "egress" |
|
89 |
+ |
} |
|
90 |
+ |
|
|
91 |
+ |
// Job evaluated based on Oxygen change closure |
|
92 |
+ |
job "compile-core" { |
|
93 |
+ |
sandbox "rust-builder" |
|
94 |
+ |
|
|
95 |
+ |
// Commutation boundary: runs only if change closure touches these paths |
|
96 |
+ |
scope "crates/oxy-core/**" "crates/oxy-server/**" "Cargo.*" |
|
97 |
+ |
|
|
98 |
+ |
// Zero-copy workspace mount backed by Oxygen CAS |
|
99 |
+ |
mount { |
|
100 |
+ |
source "oxy://workspace" |
|
101 |
+ |
target "/src" |
|
102 |
+ |
include "crates/oxy-core" "crates/oxy-server" "Cargo.toml" "Cargo.lock" |
|
103 |
+ |
readonly #true |
|
104 |
+ |
} |
|
105 |
+ |
|
|
106 |
+ |
// Ephemeral scratch space |
|
107 |
+ |
mount { |
|
108 |
+ |
source "ephemeral://tmpfs" |
|
109 |
+ |
target "/src/target" |
|
110 |
+ |
size "8GiB" |
|
111 |
+ |
} |
|
112 |
+ |
|
|
113 |
+ |
env { |
|
114 |
+ |
RUSTFLAGS "-Dwarnings" |
|
115 |
+ |
CARGO_INCREMENTAL "0" |
|
116 |
+ |
} |
|
117 |
+ |
|
|
118 |
+ |
// Direct argv execution vector (no subshell) |
|
119 |
+ |
exec "cargo" "build" "--release" "--package" "oxy-core" |
|
120 |
+ |
|
|
121 |
+ |
output { |
|
122 |
+ |
artifact "oxy-core-lib" { |
|
123 |
+ |
path "/src/target/release/liboxy_core.rlib" |
|
124 |
+ |
format "blob" |
|
125 |
+ |
} |
|
126 |
+ |
} |
|
127 |
+ |
} |
|
128 |
+ |
|
|
129 |
+ |
job "unit-tests" { |
|
130 |
+ |
sandbox "rust-builder" |
|
131 |
+ |
depends-on "compile-core" |
|
132 |
+ |
|
|
133 |
+ |
mount { |
|
134 |
+ |
source "oxy://workspace" |
|
135 |
+ |
target "/src" |
|
136 |
+ |
readonly #true |
|
137 |
+ |
} |
|
138 |
+ |
|
|
139 |
+ |
mount { |
|
140 |
+ |
source "artifact://compile-core/oxy-core-lib" |
|
141 |
+ |
target "/src/target/release/liboxy_core.rlib" |
|
142 |
+ |
} |
|
143 |
+ |
|
|
144 |
+ |
exec "cargo" "test" "--release" "--package" "oxy-core" |
|
145 |
+ |
} |
|
146 |
+ |
|
|
147 |
+ |
publish "release-provenance" { |
|
148 |
+ |
depends-on "unit-tests" |
|
149 |
+ |
|
|
150 |
+ |
attest { |
|
151 |
+ |
kind "provenance" |
|
152 |
+ |
bind-ref "bookmarks/main" |
|
153 |
+ |
include-artifacts "compile-core/oxy-core-lib" |
|
154 |
+ |
} |
|
155 |
+ |
} |
|
156 |
+ |
|
|
157 |
+ |
|
|
158 |
+ |
### 3.2 Canonical Compilation |
|
159 |
+ |
Upon commit, .flow/pipeline.kdl is validated and compiled into a deterministic |
|
160 |
+ |
CBOR job-graph blob. Runners evaluate the canonical CBOR to prevent syntax or |
|
161 |
+ |
parser ambiguities across varying client platforms. |
|
162 |
+ |
|
|
163 |
+ |
## 4. Sandbox Execution Engine |
|
164 |
+ |
|
|
165 |
+ |
OxygenFlow implements three distinct isolation tiers depending on the workload: |
|
166 |
+ |
|
|
167 |
+ |
### 4.1 Level 0: WASM Component Sandbox |
|
168 |
+ |
- Intended for static linters, formatters, doc generators, and policy checks. |
|
169 |
+ |
- Runs on a standard WebAssembly System Interface (WASI) runtime. |
|
170 |
+ |
- Startup latency: < 5 ms. |
|
171 |
+ |
- Zero host I/O; virtualized file system presented in-memory. |
|
172 |
+ |
|
|
173 |
+ |
### 4.2 Level 1: Intercepted Syscall Isolation (gVisor / Landlock + seccomp-bpf) |
|
174 |
+ |
- Intended for standard compilation and hermetic test suites. |
|
175 |
+ |
- Emulates or filters Linux system call interfaces in user space. |
|
176 |
+ |
- Blocks access to raw network sockets, real-time hardware clocks, and device |
|
177 |
+ |
nodes. |
|
178 |
+ |
- Memory and execution CPU quotas are strictly bounded via cgroups v2. |
|
179 |
+ |
|
|
180 |
+ |
### 4.3 Level 2: MicroVM Isolation (Firecracker / Cloud-Hypervisor) |
|
181 |
+ |
- Intended for kernel tests, multi-container integration, and untrusted code. |
|
182 |
+ |
- Ephemeral Linux microVM booting in < 80 ms. |
|
183 |
+ |
- The root filesystem is presented as a read-only virtio-block device mapped |
|
184 |
+ |
directly to FastCDC chunks stored in Oxygen's CAS. |
|
185 |
+ |
- Guest VM memory is cleared upon termination. |
|
186 |
+ |
|
|
187 |
+ |
## 5. Content-Addressable Storage (CAS) & Zero-Copy Mounting |
|
188 |
+ |
|
|
189 |
+ |
OxygenFlow runners bypass traditional clone operations. Repositories are accessed |
|
190 |
+ |
directly via the local object store (.oxy/objects/) or streamed on demand |
|
191 |
+ |
using Oxygen's wire protocol. |
|
192 |
+ |
|
|
193 |
+ |
### 5.1 FUSE Overlay Mounting (flow-casfs) |
|
194 |
+ |
1. The runner receives a task targeting an Oxygen State ObjectRef (a sorted |
|
195 |
+ |
list of maximal heads). |
|
196 |
+ |
2. The nearest Checkpoint is resolved. Uncommitted changes between the |
|
197 |
+ |
checkpoint and heads are replayed into a virtual tree in-memory. |
|
198 |
+ |
3. The virtual tree is exposed to the sandbox via flow-casfs: |
|
199 |
+ |
- File reads resolve chunks using the FastCDC gear table (32 KiB to 256 KiB, |
|
200 |
+ |
mean 64 KiB) pinned in Oxygen Spec Section 13.2. |
|
201 |
+ |
- Missing chunks are fetched lazily using the POST /objects protocol. |
|
202 |
+ |
- To prevent FUSE context-switch bottlenecks on many small reads, flow-casfs aggressively mmaps chunk data and utilizes host page caching. |
|
203 |
+ |
- All guest mutations are diverted to a scratch tmpfs layer; base objects |
|
204 |
+ |
remain immutable. |
|
205 |
+ |
|
|
206 |
+ |
### 5.2 Artifact Capture |
|
207 |
+ |
1. At task completion, flow-casfs scans the paths declared in the output block. |
|
208 |
+ |
2. Modified outputs are chunked with FastCDC, hashed via BLAKE3-256, and |
|
209 |
+ |
written as canonical Blob and Chunk objects. |
|
210 |
+ |
3. Output ObjectRefs are stored directly in the Oxygen repository. |
|
211 |
+ |
|
|
212 |
+ |
## 6. Commutative Execution & Change Caching |
|
213 |
+ |
|
|
214 |
+ |
In Oxygen, changes that do not share scopes (referenced atoms, placements, or |
|
215 |
+ |
nodes) commute. OxygenFlow exploits this invariant to provide granular caching. |
|
216 |
+ |
|
|
217 |
+ |
### 6.1 Execution Receipt Object |
|
218 |
+ |
Every successful or failed job run emits an immutable Receipt: |
|
219 |
+ |
|
|
220 |
+ |
```cbor |
|
221 |
+ |
Receipt { |
|
222 |
+ |
version [0]: 1 |
|
223 |
+ |
job_name [1]: text |
|
224 |
+ |
pipeline_hash [2]: ObjectRef |
|
225 |
+ |
scope_tree_hash [3]: ObjectRef // BLAKE3 tree hash of the materialized scope |
|
226 |
+ |
inputs [4]: [ObjectRef] // Artifacts and input files consumed |
|
227 |
+ |
environment [5]: ObjectRef // Hash of rootfs, compiler flags, and argv |
|
228 |
+ |
outputs [6]: [ObjectRef] // Produced artifact blobs |
|
229 |
+ |
exit_code [7]: u32 |
|
230 |
+ |
duration_ms [8]: u64 |
|
231 |
+ |
} |
|
232 |
+ |
``` |
|
233 |
+ |
|
|
234 |
+ |
A Receipt is hashed as an Oxygen object with type name "receipt": |
|
235 |
+ |
ObjectRef = BLAKE3-256("oxy1 receipt " || decimal(len) || 0x00 || body) |
|
236 |
+ |
|
|
237 |
+ |
### 6.2 Cache Re-use Invariant |
|
238 |
+ |
Let Scope(J) be the file paths and tree nodes declared by job J. |
|
239 |
+ |
Because changes that do not share scopes commute, we do not need to track lists of ChangeHashes. Instead, we hash the materialized tree of Scope(J). |
|
240 |
+ |
|
|
241 |
+ |
If an existing Receipt R exists such that: |
|
242 |
+ |
R.job_name == J.name && |
|
243 |
+ |
R.pipeline_hash == Hash(J) && |
|
244 |
+ |
R.scope_tree_hash == TreeHash(Scope(J)) && |
|
245 |
+ |
R.environment == CurrentEnvironmentHash |
|
246 |
+ |
|
|
247 |
+ |
Then the job execution is bypassed. R.outputs are mapped into downstream |
|
248 |
+ |
dependents immediately as a cached-commuted hit. |
|
249 |
+ |
|
|
250 |
+ |
## 7. Native Provenance Specification |
|
251 |
+ |
|
|
252 |
+ |
OxygenFlow formalizes build provenance as a native, tamper-evident Oxygen Attest |
|
253 |
+ |
object (kind: "attest"). Provenance is generated exclusively by the runner |
|
254 |
+ |
hypervisor, not the guest payload. |
|
255 |
+ |
|
|
256 |
+ |
### 7.1 Provenance Object Schema |
|
257 |
+ |
|
|
258 |
+ |
```json |
|
259 |
+ |
Attest { |
|
260 |
+ |
version [0]: 1 |
|
261 |
+ |
kind [1]: "attest" |
|
262 |
+ |
repo [2]: bytes(16) // Oxygen Repository ID |
|
263 |
+ |
hlc [3]: HLC // Hybrid Logical Clock |
|
264 |
+ |
body [4]: { |
|
265 |
+ |
"type": "flow/provenance/v1", |
|
266 |
+ |
|
|
267 |
+ |
// Subject artifacts produced by the build |
|
268 |
+ |
"subjects": [ |
|
269 |
+ |
{ |
|
270 |
+ |
"name": text, |
|
271 |
+ |
"ref": ObjectRef, // BLAKE3 hash of output blob |
|
272 |
+ |
"media_type": text |
|
273 |
+ |
} |
|
274 |
+ |
], |
|
275 |
+ |
|
|
276 |
+ |
// Builder platform and execution identity |
|
277 |
+ |
"builder": { |
|
278 |
+ |
"runner_id": KeyId, // ObjectRef of runner's Oxygen Identity |
|
279 |
+ |
"isolation_level": text, // "wasm" | "gvisor" | "microvm" |
|
280 |
+ |
"hypervisor_image": ObjectRef // Rootfs blob digest |
|
281 |
+ |
}, |
|
282 |
+ |
|
|
283 |
+ |
// Exact input materials |
|
284 |
+ |
"materials": { |
|
285 |
+ |
"state_heads": [ChangeHash], // Oxygen heads of the state built |
|
286 |
+ |
"scope_tree_hash": ObjectRef, // Captures exact state without O(N) array bloat |
|
287 |
+ |
"inputs": [ |
|
288 |
+ |
{ |
|
289 |
+ |
"name": text, |
|
290 |
+ |
"ref": ObjectRef // Content hash of locked dependencies |
|
291 |
+ |
} |
|
292 |
+ |
] |
|
293 |
+ |
}, |
|
294 |
+ |
|
|
295 |
+ |
// Structured execution arguments |
|
296 |
+ |
"invocation": { |
|
297 |
+ |
"job": text, |
|
298 |
+ |
"pipeline_spec": ObjectRef, // ObjectRef of .flow/pipeline.kdl |
|
299 |
+ |
"argv": [text], // Unmodified execution vector |
|
300 |
+ |
"env": map<text, text> // Explicitly whitelisted environment |
|
301 |
+ |
}, |
|
302 |
+ |
|
|
303 |
+ |
// Environment observations |
|
304 |
+ |
"metadata": { |
|
305 |
+ |
"started_on": u64, // Wallclock milliseconds |
|
306 |
+ |
"finished_on": u64, |
|
307 |
+ |
"hermetic": bool, // Verified zero outbound network access |
|
308 |
+ |
"reproducible": bool |
|
309 |
+ |
} |
|
310 |
+ |
} |
|
311 |
+ |
} |
|
312 |
+ |
``` |
|
313 |
+ |
|
|
314 |
+ |
### 7.2 Composite Signatures |
|
315 |
+ |
All provenance attestations are signed using Oxygen's composite signature |
|
316 |
+ |
construction (Ed25519 and ML-DSA-65): |
|
317 |
+ |
|
|
318 |
+ |
```cbor |
|
319 |
+ |
Signature { |
|
320 |
+ |
key [0]: KeyId |
|
321 |
+ |
alg [1]: 1 // 1 = Ed25519 + ML-DSA-65 |
|
322 |
+ |
ed [2]: bytes(64) // Classical signature |
|
323 |
+ |
ml [3]: bytes(3309) // Post-quantum signature |
|
324 |
+ |
} |
|
325 |
+ |
``` |
|
326 |
+ |
|
|
327 |
+ |
Both signatures are computed over: |
|
328 |
+ |
"oxy1 sig attest\0" || KeyId || ObjectRef |
|
329 |
+ |
|
|
330 |
+ |
## 8. Policy Integration & Bookmark Gates |
|
331 |
+ |
|
|
332 |
+ |
Oxygen repositories enforce branch and bookmark protections via signed Policy |
|
333 |
+ |
objects (Oxygen Spec Section 14.5). OxygenFlow integrates provenance directly into |
|
334 |
+ |
policy evaluation during push validation. |
|
335 |
+ |
|
|
336 |
+ |
### 8.1 Policy Gate Definition |
|
337 |
+ |
A Policy rule governing a bookmark MAY demand valid OxygenFlow attestations. To mitigate a compromised authorized worker, high-security repositories can require **Consensus Builds** by setting the threshold > 1. This requires multiple independent runner identities to arrive at the exact same output hashes and both sign it. |
|
338 |
+ |
|
|
339 |
+ |
```json |
|
340 |
+ |
PolicyRule { |
|
341 |
+ |
pattern: "bookmarks/production" |
|
342 |
+ |
keys: [ KeyId ] |
|
343 |
+ |
threshold: 1 |
|
344 |
+ |
require: "signed" |
|
345 |
+ |
allow_conflicts: false |
|
346 |
+ |
require_attestations: [ |
|
347 |
+ |
{ |
|
348 |
+ |
type: "flow/provenance/v1", |
|
349 |
+ |
job: "release-provenance", |
|
350 |
+ |
require_hermetic: true, |
|
351 |
+ |
signer_roles: [ "official-worker" ] |
|
352 |
+ |
} |
|
353 |
+ |
] |
|
354 |
+ |
} |
|
355 |
+ |
|
|
356 |
+ |
### 8.2 Push Verification Sequence (VCS Engine Enforcement) |
|
357 |
+ |
When a push request arrives at an Oxygen server attempting to update a |
|
358 |
+ |
protected bookmark: |
|
359 |
+ |
1. Object Integrity: Validate that all changes, chunks, and blobs exist and match |
|
360 |
+ |
their BLAKE3 hashes. |
|
361 |
+ |
2. Attestation Resolution: Verify that an Attest object of type |
|
362 |
+ |
"flow/provenance/v1" is present, referencing the exact heads of the new |
|
363 |
+ |
State. |
|
364 |
+ |
3. Identity Verification: Validate that the attestation's composite signature |
|
365 |
+ |
resolves to a KeyId listed as an authorized delegate of the repository |
|
366 |
+ |
policy roots. |
|
367 |
+ |
4. Invariant Checking: Confirm that the provenance statement records |
|
368 |
+ |
"hermetic: true" and exit code 0. |
|
369 |
+ |
5. Atomic Update: If validation fails at any point, the entire push is refused |
|
370 |
+ |
with ok = false. |
|
371 |
+ |
|
|
372 |
+ |
## 9. Zero-Environment Secret Brokering |
|
373 |
+ |
|
|
374 |
+ |
OxygenFlow forbids the injection of raw secret strings into process environment |
|
375 |
+ |
tables to eliminate accidental leaking via child process dumping, procfs |
|
376 |
+ |
reads, and verbose compiler logging. |
|
377 |
+ |
|
|
378 |
+ |
### 9.1 Ephemeral Secret Broker |
|
379 |
+ |
1. If a job requires a credential (e.g., signing key, cloud deployment token), |
|
380 |
+ |
it declares a secret mount: |
|
381 |
+ |
secret "deploy-token" { |
|
382 |
+ |
vault-ref "infra/tokens/prod" |
|
383 |
+ |
mount-path "/run/secrets/token" |
|
384 |
+ |
} |
|
385 |
+ |
2. The runner negotiates a short-lived token lease from the configured vault. |
|
386 |
+ |
3. The secret is mounted onto an ephemeral, in-memory ramfs location inside |
|
387 |
+ |
the sandbox with access mode 0400, owned exclusively by the worker process. |
|
388 |
+ |
4. Upon process termination, the memory pages are zeroized and the token is |
|
389 |
+ |
marked for immediate revocation at the vault. |
|
390 |
+ |
|
|
391 |
+ |
## 10. Conformance and Verification Requirements |
|
392 |
+ |
|
|
393 |
+ |
A conforming OxygenFlow implementation MUST pass the following tests: |
|
394 |
+ |
|
|
395 |
+ |
1. Injection Immunity: Attempting to supply unescaped shell metacharacters |
|
396 |
+ |
(; && | ` $() \n) in any job field MUST pass those characters as literal |
|
397 |
+ |
bytes to argv; subshells MUST NOT be spawned. |
|
398 |
+ |
2. FastCDC Determinism: Chunks produced by artifact extraction MUST match |
|
399 |
+ |
the gear table cuts and BLAKE3 hashes generated by Oxygen's core chunker. |
|
400 |
+ |
3. Commutation Hit Invariance: For any two commuting changes A and B, running |
|
401 |
+ |
a pipeline on State(A, B) MUST reuse cached receipts generated on State(A) |
|
402 |
+ |
for any job whose scope does not intersect the touched paths of B. |
|
403 |
+ |
4. Non-Downgrade Attestation: An attestation missing the ML-DSA-65 component |
|
404 |
+ |
MUST be rejected by policy verification. |
|
405 |
+ |
5. Hermetic Network Isolation: Jobs configured with network "isolated" MUST |
|
406 |
+ |
have outgoing TCP SYN and UDP packets dropped at the hypervisor boundary. |