Expand description
Platform seams: one capability trait per concern, one adapter per platform.
ARCHITECTURE.md says core crates sit behind platform traits so the seam
stays clean. This crate is that seam. A second OS is what makes the
abstraction pay for itself, and the native Windows port (plan 0027) is what
built it out from the original Clock + SecretStore stub.
§The rules every adapter here follows
- One adapter per capability per platform, named
<Platform><Capability>, living insrc/<capability>/{mod,unix,windows}.rs.mod.rsholds the trait and everything platform-free. - Static dispatch. Each capability exports a
#[cfg]-selected type alias and a unit const, so a call site writeshotl_platform::PRIVATE_FS.create_dir(p)?and pays nothing. There is exactly one implementation in any build; the point is that the contract is named, documented and testable, not that it is swappable at runtime. The onedynin this crate isSecretStore, whose set genuinely is heterogeneous at runtime (env → keychain → prompt). - Traits are sealed — see
sealed. - Capability-narrow by construction. Before adding a method, ask what
it would let a caller do that the module exists to forbid. A general
Fstrait withopen(&Path)would demotefsguard’s structural one-door invariant to a discipline invariant;DirHandleinstead exposes only relative-to-handle, one-component-at-a-time operations. - Totality: no silent no-ops. Where a platform genuinely lacks a
capability the method returns
Unsupported, neverOk(()). - Adapters are thin, and policy never lives in one. An adapter translates one contract into one platform’s syscalls. The moment it makes a decision, two platforms have begun to diverge silently.
- The doc comment carries the contract, including what differs.
- Parity tests are generic over the trait, instantiated on the active adapter, so one test body runs on every OS.
- Test adapters live behind the
testingfeature, never the default build. - Adding a platform means implementing the traits, not editing call
sites. If a future WASM or arm64-Windows port has to touch anything
outside
src/*/, the seam leaked. That is the acceptance test.
Re-exports§
pub use console::ActiveConsoleControl;pub use console::ConsoleControl;pub use console::HandlerContract;pub use entropy::ActiveEntropy;pub use entropy::Entropy;pub use ipc::ActiveIpc;pub use ipc::Ipc;pub use ipc::IpcListener;pub use ipc::Liveness;pub use ipc::PeerReject;pub use openat::ActiveDirHandle;pub use openat::DirHandle;pub use openat::Excl;pub use openat::GuardIo;pub use openat::NodeId;pub use openat::NodeKind;pub use openat::OpenMode;pub use paths::ActiveKnownPaths;pub use paths::KnownPaths;pub use privatefs::ActivePrivateFs;pub use privatefs::EffectiveAccess;pub use privatefs::PrivateFs;pub use privatefs::Writes;pub use process::ActiveProcessControl;pub use process::ProcessControl;pub use process::TreeReaper;
Modules§
- console
ConsoleControl— save/restore terminal state, and trap the interrupt-class events that would otherwise skip every destructor.- entropy
Entropy— bytes from the OS CSPRNG, or an error.- ipc
Ipc— a private, same-user, local-only session endpoint.- openat
DirHandle— the syscall layer underfsguard’s containment descent.- paths
KnownPaths— where hotl’s home, config, data and runtime directories are.- privatefs
PrivateFs— filesystem objects only the current user can read.- process
ProcessControl— detachment, and reaping a whole process tree.- sealed
- Sealing, so a trait doc can make absolute statements about all implementors.
Structs§
- EnvSecrets
- System
Clock - Unsupported
- A capability this platform does not have.
Constants§
- CONSOLE
- ENTROPY
- IPC
- KNOWN_
PATHS - PRIVATE_
FS - The active adapters. Call sites use these rather than naming a platform type, which is what keeps rule 10 checkable.
- PROCESS_
CONTROL
Traits§
- Clock
- Secret
Store - Resolution order: env var → SecretStore → prompt.