config
config
¶
Sandbox configuration — plain dataclass for standalone and embedded use.
SandboxConfig captures directory paths and settings that sandbox
modules need. In standalone terok-sandbox use, it is resolved from
environment variables and XDG defaults. When embedded in terok, the
orchestration layer constructs it from core.config values.
CONTAINER_RUNTIME_DIR = '/run/terok'
module-attribute
¶
Container-side mount point for the host runtime directory (socket mode).
SandboxConfig(state_dir=_state_root(), runtime_dir=_runtime_root(), config_dir=_config_root(), vault_dir=_vault_root(), gate_port=_default_gate_port(), token_broker_port=_default_token_broker_port(), ssh_signer_port=_default_ssh_signer_port(), shield_profiles=('dev-standard',), shield_audit=_default_shield_audit(), shield_bypass=False, credentials_passphrase=_default_credentials_passphrase(), credentials_use_keyring=_default_credentials_use_keyring(), credentials_passphrase_command=_default_credentials_passphrase_command(), services_mode=_default_services_mode(), experimental=_default_experimental())
dataclass
¶
Immutable configuration for the sandbox layer.
All paths default to the XDG/FHS-resolved values from paths.
Override individual fields when constructing from terok's global config
or when using terok-sandbox standalone.
state_dir = field(default_factory=_state_root)
class-attribute
instance-attribute
¶
Writable state root (tokens, gate repos, task data).
runtime_dir = field(default_factory=_runtime_root)
class-attribute
instance-attribute
¶
Transient runtime directory (PID files, sockets).
config_dir = field(default_factory=_config_root)
class-attribute
instance-attribute
¶
Sandbox-scoped configuration root.
Note: shield profiles are resolved by shield_profiles_dir
via namespace_config_root, not from
this directory.
vault_dir = field(default_factory=_vault_root)
class-attribute
instance-attribute
¶
Shared vault directory (DB, routes, env mounts).
gate_port = field(default_factory=_default_gate_port)
class-attribute
instance-attribute
¶
HTTP port for the gate server (None = auto-allocate via registry).
Default-factory reads gate_server.port from config.yml; missing
or unset keys fall through to None so the port registry can
pick one. Direct SandboxConfig(gate_port=…) always wins.
token_broker_port = field(default_factory=_default_token_broker_port)
class-attribute
instance-attribute
¶
TCP port for the vault's token broker (None = auto-allocate via registry).
Default-factory reads vault.port from config.yml.
ssh_signer_port = field(default_factory=_default_ssh_signer_port)
class-attribute
instance-attribute
¶
TCP port for the vault's SSH signer (None = auto-allocate via registry).
Default-factory reads vault.ssh_signer_port from config.yml.
shield_profiles = ('dev-standard',)
class-attribute
instance-attribute
¶
Shield egress firewall profile names.
shield_audit = field(default_factory=_default_shield_audit)
class-attribute
instance-attribute
¶
Whether shield audit logging is enabled.
Default-factory reads shield.audit from the layered config.yml
via the RawShieldSection
schema; missing/typo'd keys fall back to the schema's True
default. Direct SandboxConfig(shield_audit=…) always wins.
shield_bypass = False
class-attribute
instance-attribute
¶
DANGEROUS: when True, the egress firewall is completely disabled.
Hardcoded False here — sandbox refuses to read this field
from config.yml because the layered chain includes a
user-writable scope (~/.config/terok/config.yml) and an
$ENV-controllable override (TEROK_CONFIG_FILE), so anything
that drops a file in $HOME could silently disable the egress
firewall. Orchestrators that want bypass must pass it explicitly
to SandboxConfig(shield_bypass=True) after resolving from
their own trusted source.
credentials_passphrase = field(default_factory=_default_credentials_passphrase)
class-attribute
instance-attribute
¶
Headless-no-keyring fallback for the SQLCipher passphrase.
Read from credentials.passphrase in config.yml at construct
time. None (the default) means "no config-file fallback set"
— callers fall through to the next tier in the resolution chain.
credentials_use_keyring = field(default_factory=_default_credentials_use_keyring)
class-attribute
instance-attribute
¶
Opt-in switch for the OS keyring tier in the passphrase resolution chain.
Off by default. Linux Secret Service has per-collection (not
per-item) ACLs, so authorising terok against the default collection
grants read access to every other secret stored there. Operators
opt in via terok setup after weighing that trade-off.
credentials_passphrase_command = field(default_factory=_default_credentials_passphrase_command)
class-attribute
instance-attribute
¶
Operator-supplied shell command that prints the SQLCipher passphrase on stdout.
Resolver tier slotted between keyring and config. Canonical
headless option for hosts without systemd ≥ 257 — same shape as
git config credential.helper or BORG_PASSCOMMAND. Read
from credentials.passphrase_command in config.yml at
construct time; None (the default) means "no helper configured"
and the resolver skips this tier.
services_mode = field(default_factory=_default_services_mode)
class-attribute
instance-attribute
¶
Transport for host↔container IPC, resolved once at construction.
Validated through the same
RawServicesSection
schema terok's RawGlobalConfig composes, so standalone and
embedded paths agree on the value. Lives as an instance attribute
rather than a free-function call per site so downstream code can't
bypass config resolution — no manager without a SandboxConfig,
every SandboxConfig carries a resolved mode.
experimental = field(default_factory=_default_experimental)
class-attribute
instance-attribute
¶
Whether the ecosystem-wide experimental: opt-in is on.
Cross-package switch: gates terok's krun runtime at task launch
and sandbox's krun-only prereq probes (currently just ip) at
terok-sandbox setup. Read from the top-level experimental:
key in the layered config.yml at construct time; missing /
typo'd values fall back to False. Direct
SandboxConfig(experimental=…) always wins.
gate_base_path
property
¶
Return the gate server's repo base path.
shield_profiles_dir
property
¶
Return the directory for terok-managed shield profiles.
db_path
property
¶
Return the path to the vault sqlite3 database.
vault_socket_path
property
¶
Return the Unix socket path for the vault.
vault_pid_path
property
¶
Return the PID file path for the managed vault daemon.
vault_passphrase_file
property
¶
Return the session-unlock tmpfs path for the SQLCipher passphrase.
Lives under runtime_dir ($XDG_RUNTIME_DIR/...), so it is
RAM-backed and cleared on reboot. Written by
terok-sandbox vault unlock; read at daemon startup as the
highest-priority tier of the passphrase resolution chain.
vault_systemd_creds_file
property
¶
Return the sealed-credential path for the systemd-creds tier.
Lives under vault_dir (persistent state, 0o600) — the
credential is machine-bound (TPM2 or host key), so persistence
across reboots is the whole point. Written by
terok-sandbox vault seal; read on every chain walk via
terok_sandbox.vault.store.systemd_creds.
vault_recovery_marker_file
property
¶
Return the sidecar marker path for "operator saved the recovery passphrase".
Lives next to the sealed-credential file (persistent state,
0o600). Contents are the SHA-256 fingerprint of the
acknowledged passphrase, so a re-key invalidates the marker
and re-prompts on the next surface that reads it
(terok_sandbox.vault.store.recovery).
routes_path
property
¶
Return the path to the vault route configuration JSON.
credential_audit_log_path
property
¶
Return the path to the credential-use audit JSONL.
One file under the vault state dir, shared across every subject
the broker has ever served — sandbox doesn't model
"subject" semantically, so per-subject layout is the consumer's
concern (terok's review CLI filters by scope / subject).
ssh_signer_socket_path
property
¶
Return the Unix socket path for the vault's SSH signer.
The vault binds this socket and serves the SSH-agent protocol on it
(clients use it as $SSH_AUTH_SOCK). Filename uses the protocol
name so its purpose is recognisable to anyone tracing socket activity.
clone_cache_base_path
property
¶
Return the base directory for per-scope non-bare clone caches.
ssh_keys_dir
property
¶
Return the base directory for per-scope SSH keys.
with_resolved_ports()
¶
Return a copy with TCP ports allocated via the shared port registry.
Idempotent — returns self (no copy) when there is nothing
to allocate: socket mode never needs TCP listeners, and
already-fully-resolved cfgs short-circuit.
Side-effectful: allocation hits the shared port registry,
bind-tests each candidate, and persists the claim to
state_dir/port-claims.json. Keep this call OUT of
construction paths that don't actually launch services
(sickbay checks, config inspection, tests) — that's why it's
opt-in rather than baked into __post_init__. The
consumers that do need real ports (ShieldManager,
Sandbox) wrap their stored cfg in
self._cfg = self._cfg.with_resolved_ports() at construction
time so downstream code never sees None for the port it
needs.
Source code in src/terok_sandbox/config.py
open_credential_db(db_path=None, *, prompt_on_tty=False)
¶
Open the credentials DB with this config's resolution-chain knobs.
Single seam over open_credential_db
so call sites never plumb tier-selection kwargs by hand — adding
a new tier is one entry in the private _chain_kwargs helper,
no cross-package fan-out.
db_path defaults to self.db_path; callers that already
hold a path (a sidecar-pinned DB path, or a test override) pass
it explicitly so the open targets that DB while still using
this config's tier policy. CLI consumers pass
prompt_on_tty=True to unlock the interactive fallback;
the per-container supervisor leaves it off.
Source code in src/terok_sandbox/config.py
open_credential_db_with_source(db_path=None, *, prompt_on_tty=False)
¶
Same as open_credential_db
but also returns which tier of the chain hit.
db_path override semantics match
open_credential_db.
The returned source lets callers (status reports, the
supervisor startup log) name which tier unlocked the vault
instead of second-guessing the resolver.
Source code in src/terok_sandbox/config.py
open_sqlcipher_connection(db_path=None, **connect_kwargs)
¶
Open a raw sqlcipher3 connection via the chain (vault daemon path).
Source code in src/terok_sandbox/config.py
resolve_passphrase(*, prompt_on_tty=False)
¶
Walk the resolution chain with this config's knobs; return the passphrase or None.
Diagnostic seam — never opens the DB. Used by host-side
doctor / sickbay and by vault seal to reuse whatever tier
currently has the key. Same chain order as
open_credential_db
because both delegate here.
Source code in src/terok_sandbox/config.py
resolve_passphrase_with_source(*, prompt_on_tty=False)
¶
Walk the resolution chain with this config's knobs; return (passphrase, source).
Diagnostic counterpart to
resolve_passphrase
— feeds the daemon startup log so the operator sees which
tier unlocked the vault on this boot.
Source code in src/terok_sandbox/config.py
ssh_signer_local_socket_path(scope)
¶
Return the per-scope vault SSH-agent socket path for scope.
The vault binds one 0600 Unix socket per scope with at least one
assigned key, under the same runtime_dir as the main signer.
Host-side gate-sync points SSH_AUTH_SOCK at this path.
Rejects unsafe scope names with InvalidScopeName
as a belt-and-braces guard — writers in the DB layer enforce the
same policy, but the socket path is public API and may be called
without a preceding DB write.
Source code in src/terok_sandbox/config.py
services_mode()
¶
Resolve the services.mode setting through sandbox's own pydantic schema.
credentials_passphrase()
¶
credentials_use_keyring()
¶
credentials_passphrase_command()
¶
Resolve the credentials.passphrase_command shell-helper recipe through the schema.
shield_audit()
¶
experimental_enabled()
¶
Resolve the top-level experimental: opt-in from the layered config.
Ecosystem-wide flag: shared between sandbox (krun host-binary
prereqs), executor (krun runtime construction), and terok (krun
runtime selection at task launch). Defaults to False when the
key is absent or malformed.