# 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/.git` - release/snapshot archives: - `/frx/var/cache/fruix/freebsd-source/archives/-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