Pool & Metadata Views
The invariant
Within one Repository, every live Package Object has one canonical payload path under
pool/. Dists and architecture views own metadata, not aliases of package bytes:
The same digest in another Repository or publication prefix is a separately owned object. SOW deliberately does not turn local deduplication into shared distributed ownership.
What a built Repository looks like
An RPM Dist with one x86_64 package and one noarch package has this shape:
There is no dists/.../pool/ subtree. Content-addressed metadata from a retained live
generation may coexist with the current files; repomd.xml is the pointer that selects
the active set.
RPM views use computed parent-relative hrefs
rpm-md resolves each package <location href> relative to the architecture view. SOW
computes the path from that view to the canonical Pool object:
The depth is derived from the actual view root, not copied from a hostname or hard-coded
deployment path. sow check resolves and normalizes each href, rejects escapes outside the
Repository, and proves that it reaches the expected Pool object.
The complete Repository root is therefore the client and delivery boundary. Point DNF at
dists/el9/x86_64/, but serve or copy the parent Repository that also contains pool/.
Why views contain metadata only
Copying each package into every architecture view would create extra object keys and uploads on storage systems without inode identity. SOW therefore gives payload ownership to the Repository Pool and lets indexes project membership. A complete copy, archive, or publication preserves that contract without depending on hardlinks.
The one-copy boundary is one Repository or one publication prefix—not a Workspace, bucket, account, or fleet. Identical packages in separate Repositories or targets retain separate owners.
Neutral packages are selected, not duplicated
An x86_64 view selects x86_64 + noarch; an aarch64 view selects aarch64 + noarch.
The neutral package remains one Pool object. Each view gets its own metadata record whose
location resolves to that same object.
DEB works the same way at the archive-root level: all packages appear in each applicable
Packages index, while Filename: pool/... points to one canonical payload.
APT views
APT already defines Filename relative to the archive root:
SOW renders Packages, Packages.gz, and by-hash entries under
dists/<dist>/main/binary-<arch>/. Release, InRelease, and Release.gpg are the
protocol pointers and signatures. There is no per-view package alias and no per-architecture
Release stub.
Ordinary clients and reposync are different contracts
The canonical layout is designed for package clients that consume the complete Repository
and honor relative protocol paths. Default EL dnf reposync has a different contract: its
safe-write check rejects a package
location that normalizes above the per-repository download directory. This is an explicit
unsupported combination; use an exported leaf for that workflow.
When a self-contained RPM leaf is required, create it outside the Repository and every configured filesystem publication root:
The export contains its own package tree, repodata, manifest, and .sow-export.json
completion marker. Copy is the default. --hardlink is an explicit same-filesystem,
trusted read-only optimization. The export is not Membership, Generation, publication
input, or a garbage-collection root.
Copy and publication
Canonical correctness does not depend on inode identity. Prefer a configured publication
target. If another transport is required, copy the complete settled pool/ + dists/ tree
with rsync, cp, or tar into an offline staging location, verify it, and switch it into
service atomically. Never update the live tree file by file. Copying only one RPM
architecture leaf is not supported because its metadata intentionally references the
sibling root Pool.
sow changes lists each payload once under pool/, followed by metadata and pointers:
There are no package-payload entries under dists/.
Next
- Managed Workspaces — ownership and Generation state
- Platforms & Integrations — tested and unsupported combinations
- Serve Repositories — HTTP, copies, and publication targets
- Repository Layout — exact public and private paths