Skip to content

Commit 98b0517

Browse files
hyperpolymathclaude
andcommitted
feat: add Stapeln container configuration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 06d90fc commit 98b0517

1 file changed

Lines changed: 389 additions & 0 deletions

File tree

stapeln.toml

Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# stapeln.toml — Layer-based container build for nextgen-languages monorepo
3+
#
4+
# stapeln builds containers as composable layers (German: "to stack").
5+
# Each layer is independently cacheable, verifiable, and signable.
6+
#
7+
# nextgen-languages is a monorepo containing 14 experimental language
8+
# implementations. Each language has its own build toolchain (Rust, OCaml,
9+
# Elixir, Deno/ReScript, Zig FFI, Idris2 ABI). Layers are structured so
10+
# toolchain images are shared across languages that use the same stack.
11+
12+
[metadata]
13+
name = "nextgen-languages"
14+
version = "0.1.0"
15+
description = "Monorepo of experimental programming language compilers and interpreters"
16+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>"
17+
license = "PMPL-1.0-or-later"
18+
registry = "ghcr.io/hyperpolymath"
19+
20+
[build]
21+
containerfile = "Containerfile"
22+
context = "."
23+
runtime = "podman"
24+
25+
# ── Base Layer ────────────────────────────────────────────────
26+
27+
[layers.base]
28+
description = "Chainguard Wolfi minimal base"
29+
from = "cgr.dev/chainguard/wolfi-base:latest"
30+
cache = true
31+
verify = true
32+
33+
# ── Toolchain Layers ─────────────────────────────────────────
34+
# Shared toolchains reused across multiple language builds.
35+
36+
[layers.rust-toolchain]
37+
description = "Rust nightly toolchain for Cargo-based languages"
38+
extends = "base"
39+
packages = ["rustup", "gcc", "pkgconf", "openssl-dev", "musl-dev"]
40+
commands = [
41+
"rustup-init -y --default-toolchain nightly",
42+
"rustup target add wasm32-unknown-unknown",
43+
]
44+
cache = true
45+
46+
[layers.ocaml-toolchain]
47+
description = "OCaml + opam + dune for OCaml-based languages"
48+
extends = "base"
49+
packages = ["ocaml", "opam", "gcc", "musl-dev", "m4", "patch"]
50+
commands = [
51+
"opam init --disable-sandboxing --bare -y",
52+
"eval $(opam env) && opam install dune menhir ppx_deriving -y",
53+
]
54+
cache = true
55+
56+
[layers.elixir-toolchain]
57+
description = "Elixir + Erlang/OTP for BEAM-based languages"
58+
extends = "base"
59+
packages = ["elixir", "erlang-dev"]
60+
commands = ["mix local.hex --force", "mix local.rebar --force"]
61+
cache = true
62+
63+
[layers.deno-toolchain]
64+
description = "Deno runtime for JS/ReScript-based languages"
65+
extends = "base"
66+
packages = ["deno"]
67+
cache = true
68+
69+
[layers.zig-toolchain]
70+
description = "Zig compiler for FFI implementations"
71+
extends = "base"
72+
packages = ["zig"]
73+
cache = true
74+
75+
[layers.idris2-toolchain]
76+
description = "Idris2 for ABI formal definitions"
77+
extends = "base"
78+
packages = ["idris2", "gcc", "musl-dev"]
79+
cache = true
80+
81+
# ── ABI + FFI Layer ──────────────────────────────────────────
82+
# Shared layer for languages with Idris2 ABI + Zig FFI triples.
83+
84+
[layers.abi-ffi]
85+
description = "Combined Idris2 ABI verification + Zig FFI compilation"
86+
extends = "base"
87+
depends = ["idris2-toolchain", "zig-toolchain"]
88+
commands = [
89+
# Verify ABI definitions compile cleanly
90+
"for lang in eclexia betlang tangle affinescript wokelang julia-the-viper oblibeny error-lang phronesis; do [ -d ${lang}/src/abi ] && (cd ${lang}/src/abi && idris2 --check Types.idr 2>/dev/null || true); done",
91+
# Build Zig FFI shared objects
92+
"for lang in eclexia betlang tangle affinescript julia-the-viper oblibeny error-lang; do [ -d ${lang}/ffi/zig ] && (cd ${lang}/ffi/zig && zig build 2>/dev/null || true); done",
93+
]
94+
cache = true
95+
96+
# ── Language Build Layers ────────────────────────────────────
97+
# Each language gets its own build layer extending the appropriate toolchain.
98+
99+
[layers.build-ephapax]
100+
description = "Ephapax — linear type system language (Rust + Idris2)"
101+
extends = "rust-toolchain"
102+
depends = ["idris2-toolchain"]
103+
commands = [
104+
"cd ephapax && cargo build --release --workspace",
105+
"[ -d ephapax/idris2/src ] && (cd ephapax/idris2 && idris2 --check src/Main.idr || true)",
106+
]
107+
cache = true
108+
109+
[layers.build-wokelang]
110+
description = "WokeLang — consent-aware programming language (Rust + OCaml)"
111+
extends = "rust-toolchain"
112+
depends = ["ocaml-toolchain"]
113+
commands = [
114+
"cd wokelang && cargo build --release",
115+
"cd wokelang && eval $(opam env) && dune build 2>/dev/null || true",
116+
]
117+
cache = true
118+
119+
[layers.build-eclexia]
120+
description = "Eclexia — economics-as-code language (Rust + Idris2 ABI + Zig FFI)"
121+
extends = "rust-toolchain"
122+
depends = ["abi-ffi"]
123+
commands = ["cd eclexia && cargo build --release"]
124+
cache = true
125+
126+
[layers.build-affinescript]
127+
description = "AffineScript — affine type system language (OCaml + Zig FFI)"
128+
extends = "ocaml-toolchain"
129+
depends = ["abi-ffi"]
130+
commands = ["cd affinescript && eval $(opam env) && dune build"]
131+
cache = true
132+
133+
[layers.build-betlang]
134+
description = "BetLang — probabilistic programming language (Rust + Zig FFI)"
135+
extends = "rust-toolchain"
136+
depends = ["abi-ffi"]
137+
commands = ["cd betlang && cargo build --release --workspace"]
138+
cache = true
139+
140+
[layers.build-julia-the-viper]
141+
description = "Julia the Viper — pattern-matching language (Rust + Zig FFI)"
142+
extends = "rust-toolchain"
143+
depends = ["abi-ffi"]
144+
commands = ["cd julia-the-viper && cargo build --release --workspace"]
145+
cache = true
146+
147+
[layers.build-my-lang]
148+
description = "MyLang — personal expression language (Rust)"
149+
extends = "rust-toolchain"
150+
commands = ["cd my-lang && cargo build --release --workspace"]
151+
cache = true
152+
153+
[layers.build-oblibeny]
154+
description = "Oblibeny — Turing-incomplete constrained form language (OCaml + Zig FFI)"
155+
extends = "ocaml-toolchain"
156+
depends = ["abi-ffi"]
157+
commands = ["cd oblibeny && eval $(opam env) && dune build"]
158+
cache = true
159+
160+
[layers.build-tangle]
161+
description = "Tangle — entangled computation language (OCaml + Idris2 ABI + Zig FFI)"
162+
extends = "ocaml-toolchain"
163+
depends = ["abi-ffi"]
164+
commands = ["cd tangle && eval $(opam env) && dune build"]
165+
cache = true
166+
167+
[layers.build-phronesis]
168+
description = "Phronesis — practical wisdom language (Elixir)"
169+
extends = "elixir-toolchain"
170+
commands = [
171+
"cd phronesis && mix deps.get --only prod",
172+
"cd phronesis && MIX_ENV=prod mix compile",
173+
]
174+
cache = true
175+
176+
[layers.build-error-lang]
177+
description = "Error-lang — error-centric programming language (Deno + Zig FFI)"
178+
extends = "deno-toolchain"
179+
depends = ["abi-ffi"]
180+
commands = ["cd error-lang && deno cache cli/main.js"]
181+
cache = true
182+
183+
[layers.build-me-dialect]
184+
description = "Me-dialect — personal dialect language (Deno + ReScript)"
185+
extends = "deno-toolchain"
186+
commands = ["cd me-dialect && deno cache src/run.js"]
187+
cache = true
188+
189+
[layers.build-7-tentacles]
190+
description = "7-Tentacles — multi-agent language learning (Deno + ReScript)"
191+
extends = "deno-toolchain"
192+
commands = ["cd 7-tentacles && deno cache agents/*.res 2>/dev/null || true"]
193+
cache = true
194+
195+
[layers.build-anvomidav]
196+
description = "Anvomidav — experimental language (Elixir tests)"
197+
extends = "elixir-toolchain"
198+
commands = ["cd anvomidav && true"]
199+
cache = true
200+
201+
# ── Aggregate Build Layer ────────────────────────────────────
202+
203+
[layers.build-all]
204+
description = "All languages built — aggregates every build layer"
205+
extends = "base"
206+
depends = [
207+
"build-ephapax",
208+
"build-wokelang",
209+
"build-eclexia",
210+
"build-affinescript",
211+
"build-betlang",
212+
"build-julia-the-viper",
213+
"build-my-lang",
214+
"build-oblibeny",
215+
"build-tangle",
216+
"build-phronesis",
217+
"build-error-lang",
218+
"build-me-dialect",
219+
"build-7-tentacles",
220+
"build-anvomidav",
221+
]
222+
cache = true
223+
224+
# ── Runtime Layer ────────────────────────────────────────────
225+
226+
[layers.runtime]
227+
description = "Minimal production runtime with all compiled binaries"
228+
from = "cgr.dev/chainguard/wolfi-base:latest"
229+
packages = ["ca-certificates", "curl", "libgcc"]
230+
copy-from = [
231+
# Rust-built binaries
232+
{ layer = "build-ephapax", src = "/app/ephapax/target/release/", dst = "/opt/nextgen/ephapax/" },
233+
{ layer = "build-wokelang", src = "/app/wokelang/target/release/", dst = "/opt/nextgen/wokelang/" },
234+
{ layer = "build-eclexia", src = "/app/eclexia/target/release/", dst = "/opt/nextgen/eclexia/" },
235+
{ layer = "build-betlang", src = "/app/betlang/target/release/", dst = "/opt/nextgen/betlang/" },
236+
{ layer = "build-julia-the-viper", src = "/app/julia-the-viper/target/release/", dst = "/opt/nextgen/julia-the-viper/" },
237+
{ layer = "build-my-lang", src = "/app/my-lang/target/release/", dst = "/opt/nextgen/my-lang/" },
238+
# OCaml-built binaries
239+
{ layer = "build-affinescript", src = "/app/affinescript/_build/default/bin/", dst = "/opt/nextgen/affinescript/" },
240+
{ layer = "build-oblibeny", src = "/app/oblibeny/_build/default/bin/", dst = "/opt/nextgen/oblibeny/" },
241+
{ layer = "build-tangle", src = "/app/tangle/_build/default/bin/", dst = "/opt/nextgen/tangle/" },
242+
# Elixir releases
243+
{ layer = "build-phronesis", src = "/app/phronesis/_build/prod/", dst = "/opt/nextgen/phronesis/" },
244+
# Deno-based (copy source + cached deps)
245+
{ layer = "build-error-lang", src = "/app/error-lang/", dst = "/opt/nextgen/error-lang/" },
246+
{ layer = "build-me-dialect", src = "/app/me-dialect/", dst = "/opt/nextgen/me-dialect/" },
247+
{ layer = "build-7-tentacles", src = "/app/7-tentacles/", dst = "/opt/nextgen/7-tentacles/" },
248+
# Zig FFI shared objects
249+
{ layer = "abi-ffi", src = "/app/*/ffi/zig/zig-out/lib/", dst = "/opt/nextgen/lib/" },
250+
]
251+
entrypoint = ["/bin/sh"]
252+
user = "nonroot"
253+
254+
# ── Security ─────────────────────────────────────────────────
255+
256+
[security]
257+
non-root = true
258+
read-only-root = true
259+
no-new-privileges = true
260+
cap-drop = ["ALL"]
261+
seccomp-profile = "default"
262+
263+
[security.signing]
264+
algorithm = "ML-DSA-87"
265+
provider = "cerro-torre"
266+
267+
[security.sbom]
268+
format = "spdx-json"
269+
output = "sbom.spdx.json"
270+
include-deps = true
271+
272+
# ── Verification ─────────────────────────────────────────────
273+
274+
[verify]
275+
vordr = true
276+
svalinn = true
277+
scan-on-build = true
278+
fail-on = ["critical", "high"]
279+
280+
# ── Targets ──────────────────────────────────────────────────
281+
# Targets allow building individual languages or the full monorepo.
282+
283+
[targets.development]
284+
description = "Full monorepo with all toolchains for development"
285+
layers = [
286+
"base",
287+
"rust-toolchain",
288+
"ocaml-toolchain",
289+
"elixir-toolchain",
290+
"deno-toolchain",
291+
"zig-toolchain",
292+
"idris2-toolchain",
293+
"abi-ffi",
294+
"build-all",
295+
]
296+
env = { LOG_LEVEL = "debug", RUST_BACKTRACE = "1" }
297+
298+
[targets.production]
299+
description = "Minimal runtime with compiled binaries only"
300+
layers = ["runtime"]
301+
env = { LOG_LEVEL = "info" }
302+
303+
[targets.test]
304+
description = "Full toolchains with test dependencies for CI"
305+
layers = [
306+
"base",
307+
"rust-toolchain",
308+
"ocaml-toolchain",
309+
"elixir-toolchain",
310+
"deno-toolchain",
311+
"zig-toolchain",
312+
"idris2-toolchain",
313+
"abi-ffi",
314+
"build-all",
315+
]
316+
env = { LOG_LEVEL = "debug", RUST_BACKTRACE = "full", MIX_ENV = "test" }
317+
318+
# ── Per-Language Targets ─────────────────────────────────────
319+
# Build individual languages in isolation.
320+
321+
[targets.ephapax]
322+
description = "Ephapax only — linear type system language"
323+
layers = ["base", "rust-toolchain", "idris2-toolchain", "build-ephapax"]
324+
env = { LOG_LEVEL = "debug" }
325+
326+
[targets.wokelang]
327+
description = "WokeLang only — consent-aware programming"
328+
layers = ["base", "rust-toolchain", "ocaml-toolchain", "build-wokelang"]
329+
env = { LOG_LEVEL = "debug" }
330+
331+
[targets.eclexia]
332+
description = "Eclexia only — economics-as-code"
333+
layers = ["base", "rust-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-eclexia"]
334+
env = { LOG_LEVEL = "debug" }
335+
336+
[targets.affinescript]
337+
description = "AffineScript only — affine type system"
338+
layers = ["base", "ocaml-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-affinescript"]
339+
env = { LOG_LEVEL = "debug" }
340+
341+
[targets.betlang]
342+
description = "BetLang only — probabilistic programming"
343+
layers = ["base", "rust-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-betlang"]
344+
env = { LOG_LEVEL = "debug" }
345+
346+
[targets.julia-the-viper]
347+
description = "Julia the Viper only — pattern matching"
348+
layers = ["base", "rust-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-julia-the-viper"]
349+
env = { LOG_LEVEL = "debug" }
350+
351+
[targets.my-lang]
352+
description = "MyLang only — personal expression"
353+
layers = ["base", "rust-toolchain", "build-my-lang"]
354+
env = { LOG_LEVEL = "debug" }
355+
356+
[targets.oblibeny]
357+
description = "Oblibeny only — Turing-incomplete constrained form"
358+
layers = ["base", "ocaml-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-oblibeny"]
359+
env = { LOG_LEVEL = "debug" }
360+
361+
[targets.tangle]
362+
description = "Tangle only — entangled computation"
363+
layers = ["base", "ocaml-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-tangle"]
364+
env = { LOG_LEVEL = "debug" }
365+
366+
[targets.phronesis]
367+
description = "Phronesis only — practical wisdom"
368+
layers = ["base", "elixir-toolchain", "build-phronesis"]
369+
env = { LOG_LEVEL = "debug", MIX_ENV = "prod" }
370+
371+
[targets.error-lang]
372+
description = "Error-lang only — error-centric programming"
373+
layers = ["base", "deno-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-error-lang"]
374+
env = { LOG_LEVEL = "debug" }
375+
376+
[targets.me-dialect]
377+
description = "Me-dialect only — personal dialect"
378+
layers = ["base", "deno-toolchain", "build-me-dialect"]
379+
env = { LOG_LEVEL = "debug" }
380+
381+
[targets.7-tentacles]
382+
description = "7-Tentacles only — multi-agent language learning"
383+
layers = ["base", "deno-toolchain", "build-7-tentacles"]
384+
env = { LOG_LEVEL = "debug" }
385+
386+
[targets.anvomidav]
387+
description = "Anvomidav only — experimental language"
388+
layers = ["base", "elixir-toolchain", "build-anvomidav"]
389+
env = { LOG_LEVEL = "debug" }

0 commit comments

Comments
 (0)