Skip to content
All posts
2 min readtebakoarchitecturepackaging

Architecture: The host boundary (4 of 5)

How tebako v2 works, concept by concept — this post: the host boundary.

The Tebako team

github.com/tamatebako
Note

Post 4 of 5 in the series Tebako v2 architecture.

○ ○ ○ ● ○

A package that can touch anything on its host machine is a liability. This post describes the boundary tebako draws: what a running package may touch, who decides, and how the decision is enforced.

The model has three rules:

  1. Read-only by default. Every file access a payload makes flows through one choke point in tebako’s filesystem layer, and the default answer to each access is no.

  2. The payload declares; the run binds. Grants are written in the manifest under needs:, with a reason for each one, and the run binds them per invocation.

  3. Denials are named. A denied access is reported with the path, the operation, and a documented exit code — never a crash.

The jail and the host the payload declares needs: ~/.fontist rw read-only everywhere else the run binds it config or flag, per invocation the TFS layer every file access passes here — one choke point no daemon, no root the host granted: rw everything else: ro record mode runs it once, writes the grants for you to review policy is declared in the manifest, bound at run time, enforced at one choke point

Figure 1 — A payload declares what it needs; the run binds it; one choke point enforces it — and record mode can draft the grants for you.

The grant

A grant names a path, an access level, and a reason:

needs:
  host:
    - path: $HOME/.fontist
      access: rw
      when: [macos]
      why: "fontist caches and resolves fonts here"

The why is mandatory grammar: a declaration that cannot explain itself does not parse. Symbolic paths ($HOME, $TMPDIR, $CWD, the store itself) resolve at bind time, per user, per run.

Discovery, not guessing

Record mode runs the package for real and writes the draft grants from what the run actually touched. The operator reviews the draft, adjusts read and write, fills in the reasons, and binds it — the same run serves as both acceptance test and policy discovery.

One declaration, every platform

The declaration is identical everywhere; only enforcement differs. On Linux and macOS the choke point sits in the filesystem layer. On Windows, where that layer is not interposable, enforcement moves to the spawn tier — executables materialize into a cache and start with rewritten arguments, under the same policy computed from the same declarations.

The last post in this series covers what holds the whole ecosystem together: trust.

Note

Continue with part 5 of 5: Trust and the release chain.