13. Layout

In plain words: Design rule 13: Folder layout

Partial 5 min read 9 glossary terms 11 connected pages
The short version written for the Snayu team

Defines where LychD keeps files, following XDG: Settings Folder (~/.config/lychd), Data Folder or Crypt (~/.local/share/lychd) and a disposable build cache (~/.cache/lychd), and which paths it may create, change or delete.

Why read it: Read this before writing code that creates, moves or deletes files on the host.
  1. 1src/lychd/system/constants.py is the executable path contract.
  2. 2LychD never recursively owns shared XDG parent folders; it removes only identities it recorded creating.
  3. 3The Data Folder holds PostgreSQL data, triggers, snapshots, lab and extensions; the cache is disposable.

Partial The CLI path works; real-host lifecycle proof is still pending.

Words on this page, decoded click one for its card

The original text Underlined words open their plain-English card.

Context and decision

XDG geography tells LychD where an object belongs; typed creation and binding receipts decide what it may later change or remove.

The three domains

src/lychd/system/constants.py is the executable path contract. ~ is the effective LychD user's home. Shared XDG parents are never recursively owned by LychD.

Domain XDG root and default LychD root Purpose
CodexSettings Folder XDG_CONFIG_HOME or ~/.config/ ~/.config/lychd/ lychd.toml, lifecycle receipt, RunesService Config Files
CryptData Folder XDG_DATA_HOME or ~/.local/share/ ~/.local/share/lychd/ durable data, triggers, PostgreSQL, Lab, Core, Extensions
Forge XDG_CACHE_HOME or ~/.cache/ ~/.cache/lychd/ disposable assembly staging

The CodexSettings Folder contains lychd.toml, .lychd-lifecycle.json, and runes/ including the AnimatorModel Runtime, SoulstoneLocal Model, and PortalCloud Model anchors. The CryptData Folder contains the VesselEngine Room's runtime-guard, triggers/inbox and triggers/journal, postgres/init_db.sh, postgres/pg_hba_v1.conf, postgres/data, snapshots, lab, core, and extensions. postgres/data may be an ordinary directory, external mount, or LychD-created Btrfs subvolume. The Forge contains assembly. Configuration (12) owns what these paths mean; Security owns credentials and network policy.

Binding takes place in shared host namespaces: ~/.config/containers/, ~/.config/containers/systemd/, ~/.config/systemd/, and ~/.config/systemd/user/, with XDG overrides applied. The lifecycle and Scribe receipts identify exactly which names and objects LychD owns there. These regular, non-symlink, invoking-UID-owned 0600 files grant no authority over the shared parents.

Creation, binding, and deletion authority

init --dry-run describes a plan without mutation; init journals only successful creation identities. At the shared binding sites, init creates missing components as 0700 and preserves safe existing modes. Planning and execution refuse symlinks, non-directories, foreign ownership, unsafe effective access or group/other writability, and unsafe ancestry (except an appropriate sticky root/invoker-owned directory or a foreign read-only mount). bind applies the same binding-site law while planning and committing, but never creates a missing site. The per-UID/per-Codex lifecycle lock is under fixed host /tmp, not caller-selected TMPDIR.

The exact existing PostgreSQL data/ leaf is a preservation-only exception to host-UID ownership: rootless PostgreSQL may own it through a subordinate UID. Init verifies its real, host-owned parent through no-follow descriptors and observes the leaf without entering it; neither may be group/other-writable. It neither changes that ownership or mode nor adopts the leaf into ordinary directory deletion authority. This observation proves safe preservation, not container access, database readiness, or permission to repair an arbitrary foreign directory.

Publish an owned object

Every traversal is descriptor-relative and no-follow. A missing component is made under a private same-directory staging name, opened and device/inode-attested, then atomically published without replacement. The receipt records the opened identity and parent descriptor authority rather than a replaceable pathname. File publication follows the same rule: write and fsync a candidate, publish no-clobber, re-attest through the pinned parent, fsync the directory, then journal. A race winner, replacement, ambiguous result, or failed journal is preserved or quarantined as typed recovery; it is never broadened into deletion authority.

The Designed Reliquary profile binds an explicitly supplied isolated private root to its exact owned identity; it introduces no implicit CryptData Folder path or container mount. Artifact identifiers and producer labels never supply unchecked path components. Reads and publication re-attestation use nonblocking, no-follow opens and verify the opened inode before reading. Payload retirement follows a durable tombstone and exact identity attestation, then namespace sync. Unknown names, extra hardlinks, replacements and interrupted outcomes remain recovery evidence rather than deletion authority.

Retire only recorded identities

After a complete transaction, the receipt may adopt the exact device/inode identities of the dedicated CodexSettings Folder, CryptData Folder, and Forge roots. Shared XDG parents, mounts, source checkouts, and external model shelves remain outside that grant. del is a separately confirmed destructive lifecycle: it joins receipt authority to a live inventory, stops managed installation state, and refuses unknown mounts, identity mismatches, invalid receipts, foreign objects, or ambiguous ancestry. Recursive walks reject mount crossings and possible Btrfs root/stub signatures. Deletion moves a re-attested leaf to a collision-resistant private sibling before type-specific removal; mismatch or failure restores it when possible, otherwise leaves a typed recovery marker. Published init creations are never pathname-deleted as rollback.

PostgreSQL substrate

Only an absent PostgreSQL data/ target on trusted Btrfs may receive a new subvolume and +C attempt. Creation addresses the leaf through its inherited parent descriptor. Identity observation uses a bounded, fixed read-only helper with only the opened leaf descriptor: it requires a real Btrfs root directory and a supported kernel ABI before reading its own UUID and ID through BTRFS_IOC_GET_SUBVOL_INFO. No privileged path or snapshot lookup is required. No-COW mutation and before/after confirmation remain descriptor-bound. A successful subvolume records canonical UUID and non-reserved ID as well as device/inode in the version-2 lifecycle receipt. Existing storage is never retrofitted; +C is only an inheritance policy and a false result is a warning.

Retiring a subvolume requires identity established at creation; observing an existing subvolume cannot adopt it or fill in a missing identity. A mounted PhylacteryMemory Vault requires complete live mount and Btrfs agreement. An unmounted one requires the exact version-2 creation receipt, matching live identity, and a safe top-level mapping. Once those checks succeed, LychD emits the attested btrfs subvolume delete --subvolid ID TOP_LEVEL operator handoff and waits for proven absence before generic retirement. It never invokes sudo.

Host and container geography

The VesselEngine Room uses identical host/container targets: CodexSettings Folder is read-only; lab and runtime-guard are read-write; core and extensions are read-only; and when selected, Reactor inbox is read-write and journal is read-only. PostgreSQL data belongs to its PostgreSQL unit; there is no blanket CryptData Folder mount. ~/work/ is an explicit read-write Outland mount and never gains Three-Domain lifecycle authority.

TombSandbox's reserved task, workspace, artifact, and cache targets sit beneath ~/.local/share/lychd/tomb/, but it receives no CodexSettings Folder and no trigger/signalling path. Its envelope is secret-forbidden. This is a designed trust delta, not an executor: Security (09) owns its credentials/network/isolation and Workers (14) any executor.

Consequences

XDG overrides relocate roots while preserving relative topology and ownership law. Knowing an object's location helps find it; only the appropriate ownership evidence permits adoption, overwrite, or deletion. The implemented CLI path is Partial, with real-host lifecycle proof still separate. State of Work owns that maturity boundary.