You've already forked fruix-bootstrap
240 lines
7.1 KiB
Markdown
240 lines
7.1 KiB
Markdown
# Fruix bootstrap boundary
|
|
|
|
This document defines the architectural boundary between:
|
|
|
|
- `fruix`
|
|
- `fruix-bootstrap`
|
|
|
|
The goal is to keep Fruix itself small, self-hosting, and canonical, while isolating the foreign-host bring-up logic required to get the first Fruix-capable environment running on plain FreeBSD.
|
|
|
|
## Short version
|
|
|
|
- `fruix` is the canonical source of Fruix package, system, installer, deployment, and node-management logic.
|
|
- `fruix-bootstrap` is a thin foreign-host layer that turns a plain FreeBSD installation into a **Fruix builder**.
|
|
- A booted Fruix system must be able to continue operating from `fruix` alone, without depending on `fruix-bootstrap`.
|
|
|
|
## Core concept: the Fruix builder
|
|
|
|
`fruix-bootstrap` should not be thought of as a permanent alternate Fruix implementation or a long-lived compatibility layer.
|
|
|
|
Its job is to create a **Fruix builder**: an environment capable of evaluating and materializing a pinned `fruix` revision on a non-Fruix FreeBSD host.
|
|
|
|
A Fruix builder should be able to:
|
|
|
|
- run the Fruix CLI and evaluator
|
|
- load a pinned `fruix` checkout or channel revision
|
|
- materialize Fruix package outputs
|
|
- build Fruix system closures
|
|
- build Fruix installer ISOs and VM images
|
|
- install or deploy the first Fruix system
|
|
|
|
That builder may run:
|
|
|
|
- on a plain FreeBSD machine
|
|
- in CI
|
|
- in a jail
|
|
- on a later Fruix node
|
|
|
|
The important point is that the builder is generic. It is a build/evaluation environment for Fruix, not a second product identity.
|
|
|
|
## Ownership boundary
|
|
|
|
### `fruix` owns
|
|
|
|
Anything that should still matter after first Fruix boot belongs in `fruix`.
|
|
|
|
This includes:
|
|
|
|
- package definitions
|
|
- system definitions
|
|
- source objects and source provenance logic
|
|
- native-build and promotion logic
|
|
- executor model
|
|
- system artifact materializers:
|
|
- closures
|
|
- root filesystems
|
|
- disk images
|
|
- installers
|
|
- installer ISOs
|
|
- installed-node management logic:
|
|
- build
|
|
- build-base
|
|
- deploy
|
|
- reconfigure
|
|
- switch
|
|
- rollback
|
|
- later upgrade
|
|
- installer application / TUI logic
|
|
- publication/substitution logic when added later
|
|
- metadata formats that define Fruix identity and lifecycle
|
|
|
|
Rule of thumb:
|
|
|
|
> If a booted Fruix node should conceptually understand it, it belongs in `fruix`.
|
|
|
|
### `fruix-bootstrap` owns
|
|
|
|
Anything only required to turn plain FreeBSD into a Fruix-capable builder belongs in `fruix-bootstrap`.
|
|
|
|
This includes:
|
|
|
|
- host environment checks
|
|
- locating or building bootstrap tool dependencies
|
|
- foreign-host setup glue
|
|
- wrapper entrypoints for invoking a pinned `fruix` revision
|
|
- initial bootstrap documentation
|
|
- tests for the path from vanilla FreeBSD to first Fruix-capable builder or first Fruix artifact
|
|
|
|
Rule of thumb:
|
|
|
|
> If it is only needed before Fruix exists as Fruix, it belongs in `fruix-bootstrap`.
|
|
|
|
## Dependency direction
|
|
|
|
The dependency direction must remain one-way.
|
|
|
|
Allowed:
|
|
|
|
- `fruix-bootstrap` depends on a pinned `fruix` revision
|
|
- `fruix-bootstrap` invokes `fruix` to build packages, systems, installers, and images
|
|
|
|
Not allowed:
|
|
|
|
- `fruix` depending on `fruix-bootstrap`
|
|
- a booted Fruix node needing `fruix-bootstrap` in order to keep building or upgrading itself
|
|
|
|
This keeps `fruix` canonical and prevents the bootstrap repo from becoming a second source of truth.
|
|
|
|
## Canonical source of truth
|
|
|
|
`fruix` is the only canonical home for Fruix product logic.
|
|
|
|
In particular, these should not be duplicated long-term in `fruix-bootstrap`:
|
|
|
|
- canonical package definitions
|
|
- canonical system logic
|
|
- installer workflow semantics
|
|
- deployment semantics
|
|
- long-lived metadata definitions
|
|
- installed-node lifecycle behavior
|
|
|
|
`fruix-bootstrap` may temporarily wrap or seed those capabilities, but it should consume them from `fruix`, not fork them.
|
|
|
|
## Pinning
|
|
|
|
`fruix-bootstrap` should operate on a clear Fruix identity, not an ambient checkout with unclear provenance.
|
|
|
|
Initially, that identity can be simple:
|
|
|
|
- a local checkout path
|
|
- a git commit
|
|
- a tag
|
|
- a branch plus locked commit
|
|
|
|
Later, this can become a proper Fruix channel lock/update model.
|
|
|
|
Whatever form is used, the important property is:
|
|
|
|
> the first Fruix artifact is built from a known `fruix` identity.
|
|
|
|
That identity should eventually be recorded in:
|
|
|
|
- installer metadata
|
|
- image metadata
|
|
- deployed generation metadata
|
|
- installed-node metadata
|
|
|
|
## Product flow
|
|
|
|
The intended lifecycle is:
|
|
|
|
1. start from plain FreeBSD
|
|
2. use `fruix-bootstrap` to create a Fruix builder
|
|
3. point that builder at a pinned `fruix` revision
|
|
4. materialize artifacts from `fruix`, such as:
|
|
- package outputs
|
|
- system closures
|
|
- installer ISOs
|
|
- VM images
|
|
- installed systems
|
|
5. boot or install the resulting Fruix system
|
|
6. from that point onward, use `fruix` alone to move the system forward
|
|
|
|
In short:
|
|
|
|
```text
|
|
plain FreeBSD
|
|
-> fruix-bootstrap
|
|
-> Fruix builder
|
|
-> pinned fruix revision
|
|
-> build/install/deploy Fruix artifacts
|
|
-> booted Fruix node
|
|
-> future lifecycle managed by fruix
|
|
```
|
|
|
|
## Installer implication
|
|
|
|
The installer UI and workflow belong to `fruix`, not `fruix-bootstrap`.
|
|
|
|
Why:
|
|
|
|
- the installer is part of the Fruix product surface
|
|
- Fruix should be able to build its own installer artifacts
|
|
- installed systems should be traceable to a pinned Fruix revision
|
|
- later Fruix nodes should be able to rebuild the installer without returning to bootstrap-only logic
|
|
|
|
So the split should be:
|
|
|
|
- `fruix-bootstrap`: makes it possible to build the installer
|
|
- `fruix`: defines the installer artifact and the TUI installer behavior
|
|
|
|
## Success criteria
|
|
|
|
The boundary is working when all of the following are true:
|
|
|
|
1. a plain FreeBSD host can become a Fruix builder using `fruix-bootstrap`
|
|
2. that builder can build a Fruix installer ISO or VM image from a pinned `fruix` revision
|
|
3. the resulting Fruix system boots without requiring `fruix-bootstrap`
|
|
4. the booted Fruix system can keep using `fruix` for:
|
|
- build
|
|
- build-base
|
|
- reconfigure
|
|
- deploy
|
|
- rollback
|
|
- later upgrade
|
|
5. package and system evolution happens in `fruix`, not in duplicated bootstrap logic
|
|
|
|
## Non-goals
|
|
|
|
This split does not mean:
|
|
|
|
- `fruix-bootstrap` becomes a permanent parallel Fruix distribution
|
|
- booted Fruix nodes should keep consulting bootstrap state
|
|
- bootstrap should own package or system semantics long-term
|
|
|
|
It also does not require all historical bootstrap leakage to disappear immediately. Some transitional host assumptions may remain for a while, but they should be treated as technical debt against this boundary.
|
|
|
|
## Working rule for future refactors
|
|
|
|
When deciding where code belongs, ask:
|
|
|
|
> Should a booted Fruix node still care about this?
|
|
|
|
- If yes, it belongs in `fruix`.
|
|
- If no, and it only exists to bring up Fruix from foreign FreeBSD, it belongs in `fruix-bootstrap`.
|
|
|
|
## Current direction
|
|
|
|
Near-term work should follow this boundary:
|
|
|
|
- keep bootstrap generic and thin
|
|
- move as much canonical logic as possible into `fruix`
|
|
- make the first user-facing installer a Fruix-defined product artifact
|
|
- ensure installed nodes record and operate from a pinned Fruix identity
|
|
|
|
That gives Fruix a clean product story:
|
|
|
|
- bootstrap creates a Fruix builder
|
|
- Fruix builds Fruix
|
|
- Fruix systems move forward using Fruix
|