8.8 KiB
Fruix FreeBSD Source Policy
This document records the current intended policy for how Fruix models, fetches, caches, identifies, invalidates, and consumes FreeBSD source inputs.
It reflects the behavior implemented through Plan 4 Phases 16 and 17.
1. Source object model
Fruix represents FreeBSD source inputs explicitly with freebsd-source.
Currently supported source kinds are:
local-treegitsrc-txz
A source object records some combination of:
namekindurlpathrefcommitsha256
Fruix distinguishes between:
- the declared source
- what the operator asked for
- the effective source
- what Fruix actually resolved/materialized and built from
That distinction matters most for Git refs and local-tree snapshots.
2. Source identity boundaries
local-tree
Declared selector:
- local filesystem path
Effective identity boundary:
- filtered source-tree hash computed from
mtree
Current rule:
- Fruix computes source identity from:
mtree -c -k type,link,size,mode,sha256digest
- comment lines are removed before hashing
This avoids unstable mtree comment headers such as:
- date
- user
- machine
So the effective local-tree identity is content-oriented rather than host-comment-oriented.
git
Declared selectors:
commit, orref
Effective identity boundary:
- resolved commit
Current rule:
- if
commitis present, Fruix uses it as the fetch selector - otherwise, Fruix uses
ref - after fetch, Fruix records the resolved commit as the effective Git identity
Policy consequence:
- a Git ref is a convenience selector
- a Git commit is the reproducibility boundary
Therefore:
- use
refalone for exploratory/latest tracking when drift is acceptable - use
commitfor reproducible builds, side-by-side comparisons, installation artifacts, and rollback-sensitive workflows - it is valid to record both:
reffor human provenancecommitfor stable identity
src-txz
Declared selectors:
- URL
- expected
sha256
Effective identity boundary:
- verified archive
sha256
Policy consequence:
src-txzmaterialization is only valid whensha256is declared- archive URL alone is not enough
3. Cache policy
Default cache root:
/frx/var/cache/fruix/freebsd-source
Current cache layout:
- Git:
/frx/var/cache/fruix/freebsd-source/git/<hash>.git
- release/snapshot archives:
/frx/var/cache/fruix/freebsd-source/archives/<hash>-src.txz
Git cache behavior
Fruix keeps a bare repository cache keyed by source URL.
Current behavior:
- initialize bare repo if absent
- ensure
originmatches the declared URL - fetch the requested selector from
origin - archive the resolved commit into the materialized store object
Policy:
- the cache is a transport/proxy optimization, not the identity boundary
- the identity boundary is the resolved commit recorded in the effective source and materialization metadata
src-txz cache behavior
Fruix keeps the downloaded archive under the cache root.
Current behavior:
- if a cached archive exists, hash it
- if its hash does not match the declared
sha256, delete it - fetch the archive if missing
- verify the downloaded archive hash
- fail if the verified hash does not match the declared
sha256
Policy:
- the cache is reusable only when the declared hash still matches
- hash mismatch invalidates the cached archive immediately
local-tree
Current behavior:
- no separate network cache
- Fruix snapshots the local tree into a materialized store object
Policy:
- the local path is only a selector to a mutable host tree
- the materialized snapshot and its filtered tree hash are the meaningful Fruix identity boundary
4. Materialized source store policy
Materialized FreeBSD sources are stored in:
/frx/store/*-freebsd-source-*
Current manifest inputs for a materialized source object include:
- materializer version
- declared source
- effective source
- source identity tuple
- for example resolved commit, archive sha256, or local tree hash
Policy consequence:
- changing any of those identity inputs should produce a distinct source store path
- changing materialization semantics should bump the materializer version
Current materializer version:
freebsd-source-materializer-version = "2"
5. Effective source root policy
Not every source unpacks to the same top-level directory shape.
Current behavior:
- if
tree/Makefileexists, effective root is:tree
- else if
tree/usr/src/Makefileexists, effective root is:tree/usr/src
This is why:
- Git exports materialize effectively at
.../tree - official
src.txzarchives materialize effectively at.../tree/usr/src
Policy:
- native builds must consume the detected effective source root, not assume
/usr/src - the declared transitional
source-rootmay still be recorded for provenance, but it is not the effective build root once materialization is in use
6. Native build invalidation policy
Native FreeBSD kernel/world/runtime/bootloader outputs must be invalidated by source identity, not just by package name/version.
Current behavior:
- native package materialization rewrites the install plan to use the materialized source root
- native manifests record both:
declared-sourcematerialized-source
- package materialization caching keys on the full manifest identity rather than only package name/version
- native build common metadata includes:
source-rootsource-tree-sha256- kernconf hash
- target metadata
Policy consequence:
- two builds with the same visible base version label but different source identities must still produce different native output store paths
- that behavior is intentional and required
7. Closure provenance policy
System closures and images should preserve enough source metadata to explain exactly what source snapshot was used.
Current closure/image metadata includes:
metadata/freebsd-source.scmmetadata/freebsd-source-materializations.scmmaterialized_source_store_countmaterialized_source_stores
Native .freebsd-native-build-info.scm records:
- declared source
- materialized source store path
- materialized source root
- materialized source tree hash
- effective Git commit or archive hash when applicable
Policy:
- source provenance is part of the closure boundary, not just a transient fetch detail
8. Update policy
Recommended operator policy
For reproducible and rollback-sensitive workflows:
- prefer Git sources pinned by
commit - prefer archive sources pinned by
sha256 - treat
local-treeas a development/debugging input unless the resulting materialized snapshot is itself the explicit artifact being compared
Moving refs
A moving Git ref is expected to drift over time.
Policy:
- if only
refis declared, Fruix may legitimately produce a new materialized source store later - that new materialized source identity should then invalidate native outputs
- this is expected behavior, not a cache bug
Installed/deployed systems
For installation artifacts and generation management, the source identity should be stable enough to answer:
- what exact source revision produced this system?
- can it be rebuilt later?
- should this update be considered a new generation boundary?
That means later installation/deployment work should prefer:
- Git commit-pinned sources
- hash-pinned archives
rather than floating refs alone.
9. Patch/transformation policy
Fruix does not yet expose a first-class patch queue or transformation layer on top of freebsd-source.
Current policy until that exists:
- the declared source object should be treated as the full upstream-source identity boundary
- when a patch/transformation layer is introduced later, it must become part of the materialized source identity and manifest versioning
In other words:
- applying patches without changing source identity metadata would be wrong
10. Relation to Guix-inspired semantics
This policy follows the same important high-level idea as Guix:
- selectors are not enough
- resolved, content-stable identities matter
- cached transport objects are not the same as reproducible store identities
Fruix applies that idea in FreeBSD-specific form:
src.txzhandling- FreeBSD source-tree effective-root detection
- mtree-based FreeBSD tree identity
- native FreeBSD base builds driven from materialized source snapshots under
/frx/store
11. Practical summary
Use these rules:
- Want reproducibility?
- pin Git by
commit - pin archives by
sha256
- pin Git by
- Want side-by-side comparison?
- keep distinct source objects and let Fruix materialize them separately
- Want native base outputs to differ only when they should?
- rely on materialized source identity, not mutable
/usr/src
- rely on materialized source identity, not mutable
- Want stable deployment provenance?
- preserve the closure metadata files and materialized source store references