331 lines
8.8 KiB
Markdown
331 lines
8.8 KiB
Markdown
# 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-tree`
|
|
- `git`
|
|
- `src-txz`
|
|
|
|
A source object records some combination of:
|
|
|
|
- `name`
|
|
- `kind`
|
|
- `url`
|
|
- `path`
|
|
- `ref`
|
|
- `commit`
|
|
- `sha256`
|
|
|
|
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`, or
|
|
- `ref`
|
|
|
|
Effective identity boundary:
|
|
|
|
- resolved commit
|
|
|
|
Current rule:
|
|
|
|
- if `commit` is 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 `ref` alone for exploratory/latest tracking when drift is acceptable
|
|
- use `commit` for reproducible builds, side-by-side comparisons, installation artifacts, and rollback-sensitive workflows
|
|
- it is valid to record both:
|
|
- `ref` for human provenance
|
|
- `commit` for stable identity
|
|
|
|
### `src-txz`
|
|
|
|
Declared selectors:
|
|
|
|
- URL
|
|
- expected `sha256`
|
|
|
|
Effective identity boundary:
|
|
|
|
- verified archive `sha256`
|
|
|
|
Policy consequence:
|
|
|
|
- `src-txz` materialization is only valid when `sha256` is 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 `origin` matches 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/Makefile` exists, effective root is:
|
|
- `tree`
|
|
- else if `tree/usr/src/Makefile` exists, effective root is:
|
|
- `tree/usr/src`
|
|
|
|
This is why:
|
|
|
|
- Git exports materialize effectively at `.../tree`
|
|
- official `src.txz` archives materialize effectively at `.../tree/usr/src`
|
|
|
|
Policy:
|
|
|
|
- native builds must consume the detected effective source root, not assume `/usr/src`
|
|
- the declared transitional `source-root` may 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-source`
|
|
- `materialized-source`
|
|
- package materialization caching keys on the full manifest identity rather than only package name/version
|
|
- native build common metadata includes:
|
|
- `source-root`
|
|
- `source-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.scm`
|
|
- `metadata/freebsd-source-materializations.scm`
|
|
- `materialized_source_store_count`
|
|
- `materialized_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-tree` as 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 `ref` is 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.txz` handling
|
|
- 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`
|
|
- **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`
|
|
- **Want stable deployment provenance?**
|
|
- preserve the closure metadata files and materialized source store references
|