The executable contract for the YAML representation of Vis configuration.
YAMLStar returns maps with string keys. This namespace validates that exact representation: snake_case string keys ONLY (kebab-case is rejected), no recursive keywordization, and no acceptance of keyword-keyed lookalikes. Maps are closed unless their keys are deliberately user-defined (environment variables, headers, toggle ids, MCP server names, pricing/model tables, and provider request bodies).
Security consumers derive their internal policy maps through the adapters at the end of this namespace, so validation and enforcement share one contract.
The executable contract for the YAML representation of Vis configuration. YAMLStar returns maps with string keys. This namespace validates that exact representation: snake_case string keys ONLY (kebab-case is rejected), no recursive keywordization, and no acceptance of keyword-keyed lookalikes. Maps are closed unless their keys are deliberately user-defined (environment variables, headers, toggle ids, MCP server names, pricing/model tables, and provider request bodies). Security consumers derive their internal policy maps through the adapters at the end of this namespace, so validation and enforcement share one contract.
(applicable-entries entries)(applicable-entries entries env)The catalog entries that apply to this host, in declaration order: a when
that does not match and an optional root whose path is absent are dropped.
The catalog entries that apply to this host, in declaration order: a `when` that does not match and an `optional` root whose path is absent are dropped.
(assert-config! config)(assert-config! config source)Return a string-keyed YAML config when it satisfies the complete contract. The thrown message names each offending field path, because the raw spec problem for a closed map is an unreadable dump of the entire config.
The violation is a USER error (:vis/user-error) carrying a rendered
:vis/panel: a mistyped key deserves the field list, never a stack trace.
Return a string-keyed YAML config when it satisfies the complete contract. The thrown message names each offending field path, because the raw spec problem for a closed map is an unreadable dump of the entire config. The violation is a USER error (`:vis/user-error`) carrying a rendered `:vis/panel`: a mistyped key deserves the field list, never a stack trace.
(assert-process-jail-config! policy)Validate and return the exact internal policy consumed by process-jail.
Validate and return the exact internal policy consumed by process-jail.
The wire dialects a provider may declare. api_style remains the raw svar
escape hatch for anything outside this two-dialect world (e.g. gemini).
The wire dialects a provider may declare. `api_style` remains the raw svar escape hatch for anything outside this two-dialect world (e.g. `gemini`).
(config-error-panel fields source)Caller-facing screen for an invalid config: the offending field lines and
nothing else. Entry points print :vis/panel verbatim, so a bad YAML key
must never reach the fatal path (a Java stack trace tells the user nothing
about which key they mistyped).
Caller-facing screen for an invalid config: the offending field lines and nothing else. Entry points print `:vis/panel` verbatim, so a bad YAML key must never reach the fatal path (a Java stack trace tells the user nothing about which key they mistyped).
(entry-draft-policy entry)The catalog entry's DRAFT isolation policy as a keyword. Absent/unknown →
:shared (write through to the real root), the historical behaviour.
The catalog entry's DRAFT isolation policy as a keyword. Absent/unknown → `:shared` (write through to the real root), the historical behaviour.
(entry-mount-status entry)(entry-mount-status entry {:keys [os exists?]})Why a catalog entry does or does not mount on this host:
:mounted — declared, present, admitted.
:os-mismatch — when.os names other platforms.
:when-absent — when.exists names a path that is not there.
:optional-absent — optional: true and the root itself is missing.
:missing — admitted, but the root does not exist yet (a warning,
not a removal: the historical behaviour is preserved).
Why a catalog entry does or does not mount on this host:
`:mounted` — declared, present, admitted.
`:os-mismatch` — `when.os` names other platforms.
`:when-absent` — `when.exists` names a path that is not there.
`:optional-absent` — `optional: true` and the root itself is missing.
`:missing` — admitted, but the root does not exist yet (a warning,
not a removal: the historical behaviour is preserved).(entry-mounted? entry)(entry-mounted? entry env)True when the entry belongs in THIS host's catalog.
True when the entry belongs in THIS host's catalog.
(explain-problems config)Best-effort, model-readable reasons a string-keyed YAML config fails the
contract — one line per offending FIELD, named by its dotted path
(grep.include_gitignored_paths, providers[1].models[0].context,
mcp.servers.docs.transport): a non-string key, an unknown key (maps are
closed, with a did-you-mean when a known key is close), a missing required
key, or a value the schema rejects. Returns [] for a valid or nil map, so a
caller surfaces a config_error hint ONLY when the live config is actually
denied. This points a fix straight at the field rather than dumping the whole
opaque spec problem.
Best-effort, model-readable reasons a string-keyed YAML `config` fails the contract — one line per offending FIELD, named by its dotted path (`grep.include_gitignored_paths`, `providers[1].models[0].context`, `mcp.servers.docs.transport`): a non-string key, an unknown key (maps are closed, with a did-you-mean when a known key is close), a missing required key, or a value the schema rejects. Returns [] for a valid or nil map, so a caller surfaces a `config_error` hint ONLY when the live config is actually denied. This points a fix straight at the field rather than dumping the whole opaque spec problem.
(host-os)This host's when.os token: macos, windows, wsl (Linux under WSL),
linux, or unknown when the platform can't be identified.
This host's `when.os` token: `macos`, `windows`, `wsl` (Linux under WSL), `linux`, or `unknown` when the platform can't be identified.
The Mach services a confined child must reach to read the macOS Keychain:
the security server itself plus the trust/revocation daemons it calls into.
Verified against security, gh auth token and git credential-osxkeychain
under sandbox-exec; without them the lookup fails with
SecKeychainSearchCreateFromAttributes: … parameters … not valid.
The Mach services a confined child must reach to read the macOS Keychain: the security server itself plus the trust/revocation daemons it calls into. Verified against `security`, `gh auth token` and `git credential-osxkeychain` under `sandbox-exec`; without them the lookup fails with `SecKeychainSearchCreateFromAttributes: … parameters … not valid`.
Keychain databases the same lookup reads. Kept OUT of the search sweep — they are credentials, never grep fodder.
Keychain databases the same lookup reads. Kept OUT of the search sweep — they are credentials, never grep fodder.
(mount-env)The LIVE host facts a when clause is evaluated against:
{:os "macos" :exists? <pred>}. Passed explicitly everywhere so mounting is
testable without touching this machine.
The LIVE host facts a `when` clause is evaluated against:
`{:os "macos" :exists? <pred>}`. Passed explicitly everywhere so mounting is
testable without touching this machine.(network-config config)Derive the keyword-keyed internal egress policy from validated YAML config.
Egress filtering is one facet of the process jail: jail.enabled is the single
gate. When the jail is off the policy is empty (egress open); when on, the
jail.network block (allowed/denied/exclude domains, allow_private, rules)
is enforced alongside the filesystem and inbound-port confinement.
Derive the keyword-keyed internal egress policy from validated YAML config. Egress filtering is one facet of the process jail: `jail.enabled` is the single gate. When the jail is off the policy is empty (egress open); when on, the `jail.network` block (allowed/denied/exclude domains, `allow_private`, rules) is enforced alongside the filesystem and inbound-port confinement.
(process-jail-config config)(process-jail-config config env)Derive the internal process-jail policy from validated string-keyed config.
The workspace.filesystem catalog is the single source of roots. When the
jail is DISABLED (the default) nothing is confined, so every catalog root is
available and the allow list is ignored. When ENABLED,
jail.filesystem.allow selects which catalog ids enter the OS jail
(deny-by-omission). Each admitted entry's access sets RW vs read-only and
search: false marks it out of the default search sweep.
Roots this host does not mount are dropped FIRST (applicable-entries), so a
when-gated id may be listed in allow on every machine; pass an explicit
env to resolve against something other than the live host.
jail.mach_services opens macOS Mach lookups. keychain: true additionally
grants read access to the keychain databases (kept out of the search sweep),
which is what makes security, gh auth token and
git credential-osxkeychain work inside the jail.
Vis's own session folder (vis-home-entry, ~/.vis) is ALWAYS appended to the
admitted set — engine-level, so it survives both an undeclared catalog and a
live jail's deny-by-omission. A catalog entry for the same path wins.
Derive the internal process-jail policy from validated string-keyed config. The `workspace.filesystem` catalog is the single source of roots. When the jail is DISABLED (the default) nothing is confined, so every catalog root is available and the `allow` list is ignored. When ENABLED, `jail.filesystem.allow` selects which catalog ids enter the OS jail (deny-by-omission). Each admitted entry's `access` sets RW vs read-only and `search: false` marks it out of the default search sweep. Roots this host does not mount are dropped FIRST (`applicable-entries`), so a `when`-gated id may be listed in `allow` on every machine; pass an explicit `env` to resolve against something other than the live host. `jail.mach_services` opens macOS Mach lookups. `keychain: true` additionally grants read access to the keychain databases (kept out of the search sweep), which is what makes `security`, `gh auth token` and `git credential-osxkeychain` work inside the jail. Vis's own session folder (`vis-home-entry`, `~/.vis`) is ALWAYS appended to the admitted set — engine-level, so it survives both an undeclared catalog and a live jail's deny-by-omission. A catalog entry for the same path wins.
How a session gets its name. Only llm spends a provider call; the other
two derive the title locally from the request itself, and disabled leaves
the session unnamed (Blockether/vis#71).
How a session gets its name. Only `llm` spends a provider call; the other two derive the title locally from the request itself, and `disabled` leaves the session unnamed (Blockether/vis#71).
Vis's OWN session folder — ~/.vis: state.yml, the session DB, the gateway
event journals, drafts and logs. An IMPLICIT workspace.filesystem catalog
entry the engine always grants, independent of what a project declares and of
jail.filesystem.allow: Vis must reach its own state even inside a live jail,
and that reach is engine-level — never a feature toggle (the introspection
toggle governs the session_state/sessions TOOLS, not this grant). Kept out of
the DEFAULT search sweep (search: false); explicit paths still reach it.
Vis's OWN session folder — `~/.vis`: `state.yml`, the session DB, the gateway event journals, drafts and logs. An IMPLICIT `workspace.filesystem` catalog entry the engine always grants, independent of what a project declares and of `jail.filesystem.allow`: Vis must reach its own state even inside a live jail, and that reach is engine-level — never a feature toggle (the `introspection` toggle governs the session_state/sessions TOOLS, not this grant). Kept out of the DEFAULT search sweep (`search: false`); explicit paths still reach it.
(workspace-draft-policies config)(workspace-draft-policies config env){catalog-path -> policy} for every declared root that opts OUT of the default
:shared behaviour. Independent of jail.filesystem.allow: the policy governs
draft isolation, which applies whether or not the OS jail is enabled. Roots
this host does not mount never appear.
`{catalog-path -> policy}` for every declared root that opts OUT of the default
`:shared` behaviour. Independent of `jail.filesystem.allow`: the policy governs
draft isolation, which applies whether or not the OS jail is enabled. Roots
this host does not mount never appear.Per-root DRAFT isolation vocabulary.
shared — the draft writes THROUGH to the real root (default).
copy-only — the draft gets a private copy; apply! never lands it back.
copy-and-apply — private copy, landed back into the real root on apply!.
not-allowed — the root is withheld from a drafted session entirely.
Per-root DRAFT isolation vocabulary. `shared` — the draft writes THROUGH to the real root (default). `copy-only` — the draft gets a private copy; `apply!` never lands it back. `copy-and-apply` — private copy, landed back into the real root on `apply!`. `not-allowed` — the root is withheld from a drafted session entirely.
(workspace-mount-diagnostics config)(workspace-mount-diagnostics config env)One message per declared root that did NOT mount as written: conditional roots
the host skipped (:info) and admitted roots whose path is missing (:warn,
or :info when optional: true). Empty when every root is present, so it
doubles as the startup hint and the doctor check.
One message per declared root that did NOT mount as written: conditional roots the host skipped (`:info`) and admitted roots whose path is missing (`:warn`, or `:info` when `optional: true`). Empty when every root is present, so it doubles as the startup hint and the `doctor` check.
Host tokens when.os may name. wsl is Linux under WSL: a WSL host also
matches a linux clause, but a plain Linux host never matches wsl.
Host tokens `when.os` may name. `wsl` is Linux under WSL: a WSL host also matches a `linux` clause, but a plain Linux host never matches `wsl`.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |