Files
fruix/docs/freebsd-source-policy.md

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-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

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