directory, or one you wrote. The configuration
can only choose among kinds that exist; defining one is code, and this page is how that code is written.
The config names a kind and cannot define one
There is nowhere invitruvio.toml to put a command line. That is deliberate, and it is the reason this feature has
no trust-confirmation ceremony: vitruvio.toml is committed and shared, so a field holding an argv would mean that
cloning a repository and running source pull executes a stranger’s command.
A kind vitruvio does not ship is a Python class you install, either as a file under
$XDG_CONFIG_HOME/vitruvio/sources/ or as a vitruvio.sources entry point. Importing a module you wrote from your
own configuration directory is code execution at the same trust level as your shell profile. Executing an argv that
arrived with a git clone is not, and no prompt makes it so.
Writing a source
list() returns what is on offer without fetching any of it, and fetch(item) returns one item’s
bytes. They are separate so that a duplicate can be skipped before it is downloaded. When a remote listing omits
the real filename or MIME type, return FetchResult(data, media_type=..., title=...) instead of bare bytes. The
metadata discovered from the downloaded file is then recorded on the canonical block; a declared media_type still
wins.
self.options contains the effective merge for this pull, not necessarily only the committed defaults. Reject
unknown keys in the constructor so a typo on either source add or source pull fails before fetching anything.
Use what BaseSource gives you rather than the bare equivalents. Each carries a bound the naked call does not, and
every one of them fails as a hang with nothing on screen:
The
VITRUVIO_* stripping is not paranoia: a source that shells back into vitruvio while inheriting VITRUVIO_BRAIN
writes into the brain that is pulling it. And contain refusing a FIFO is the one that has teeth — read_bytes() on
a FIFO blocks forever, and a glob will hand you one without comment.