Skip to content
All posts
2 min readtebakoarchitecturepackaging

Architecture: Composition (3 of 5)

How tebako v2 works, concept by concept — this post: composition.

The Tebako team

github.com/tamatebako
Note

Post 3 of 5 in the series Tebako v2 architecture.

○ ○ ● ○ ○

The first two posts covered the parts: packages, runtimes, payload slices. This post covers the grammar that ties them together — how a package says what it needs, and how those needs become mounts in one process.

Everything is declared in the payload’s manifest, under requires::

Composition the manifest declares requires: a language runtime engine: ruby, constraint: ~> 3.3.0 requires: a spawned runtime engine: java, expose: [java] requires: a toolkit payload name: inkscape, mount: /opt/inkscape resolution newest compatible per triplet one process ruby runtime mounted java runtime spawned toolkit at /opt/inkscape declarative and per-invocation: pinned, side-by-side versions are possible

Figure 1 — The manifest declares requirements; resolution turns them into mounted runtimes, spawned runtimes, and toolkits inside one process.

requires:
  - kind: language
    engine: ruby
    constraint: "~> 3.3.0"
  - kind: runtime
    engine: java
    constraint: ">= 21, < 26"
    expose: [java]
  - kind: toolkit
    name: inkscape
    constraint: ">= 1.3"
    mount: /opt/inkscape

Three kinds of requirement, three mechanisms:

  • A language runtime boots the application: its two artifacts mount as described in the previous post.

  • A runtime requirement like java is spawned, not mounted: when the application runs java, tebako starts that runtime’s own executable with its own environment image, as a child process. The expose: list names the commands that appear.

  • A toolkit requirement mounts at a declared path, exactly like a data slice.

Resolution

Resolution picks, per platform triplet, the newest artifact that satisfies every constraint. The result is deterministic and recorded — the same package resolves the same way on the same machine, and a payload with native code can pin an ABI line so a wrong runtime is a named error, never a crash.

Declarative, per invocation

The same declaration drives dispatch: an installed payload provides commands, and each invocation resolves the declared composition before it starts. Because nothing is implied, pinned and side-by-side versions of the same tool are ordinary — the next post covers what those processes may touch on the host.

Note

Continue with part 4 of 5: The host boundary.