Configuration¶
The config schema (team defaults overlaid by per-target config), its resolution to an
Effective config for one target, and the Git config source (github:owner/repo@ref:path).
bajutsu.config
¶
Configuration — team defaults overlaid by per-target config.
Split along its four responsibilities (BE-0252), one submodule each, with a one-directional
dependency from resolution outward: input schema (schema) -> resolved output types
(effective) <- merge/derivation (resolve) and platform-narrowing accessors (accessors).
The public API is re-exported here, so from bajutsu.config import Effective, resolve,
require_ios, … is unchanged and no call site outside this package is touched.
AiConfig
dataclass
¶
The resolved ai block (BE-0047): which provider/model/endpoint/key the AI paths use.
Lives with the rest of the resolved config (not the AI client) so the deterministic core can
read the block without importing the periphery AI stack (BE-0112). Every field is optional — an
absent field falls back to the environment in the AI-client factory, so a config with no ai:
block behaves exactly as before. key_env holds the NAME of the env var that carries the key,
never the key itself.
AndroidConfig
dataclass
¶
Android (adb) target knobs (BE-0126 / BE-0007). On Effective only when platform is android.
DoctorThresholds
dataclass
¶
Configurable doctor id-coverage thresholds (BE-0024), grouped out of Effective (BE-0252).
Teams with many decorative elements can tune thresholds (often lowering ok and/or fail for leniency) without changing the tool.
Effective
dataclass
¶
The resolved config for one target.
platform
property
¶
The resolved platform (ios / android / web), derived from the sub-config's type (BE-0126).
rebased(root, *, confine=True)
¶
A copy with the relative path fields resolved against root.
The common path fields — scenarios / baselines / schemas / goldens — and the iOS or
Android sub-config's app_path are rebased; a future path field is rebased by adding it here. build
(a shell command) and setup (resolved relative to the scenario, not the cwd) are
intentionally absent. Called for a Git checkout (BE-0063), for an uploaded bundle, and — with
confine=False, root the config file's own directory — for a local config (BE-0242), so the
caller's working directory no longer decides where a config's paths point.
confine gates the escape check: when true (an untrusted source — a fetched Git config or an
uploaded bundle), an absolute or ../ value that would leave root raises ValueError, mirroring
the serve-hardening path confinement (BE-0051). A local file is operator-trusted (BE-0121), so it
passes confine=False and may point at a sibling outside its own directory.
EvidenceDirs
dataclass
¶
The target's evidence directory overrides (BE-0252 grouping of Effective).
Each is the target's directory for that evidence kind (config-driven run/record). None
means "unset": scenarios then requires an explicit path, and each of baselines / schemas /
goldens falls back to the directory beside the scenario file (or the matching --<kind> flag).
IosConfig
dataclass
¶
iOS (idb / XCUITest) target knobs (BE-0126). On Effective only when platform == "ios".
RunDefaults
dataclass
¶
Per-app run-behavior defaults (BE-0177), grouped out of Effective (BE-0252).
The layer the run consults when neither a CLI flag nor the scenario sets the value.
dismiss_alerts None = built-in on with the default instruction; erase / network are the
concrete built-in defaults when unset.
WebConfig
dataclass
¶
Web (Playwright) target knobs (BE-0126). On Effective only when platform == "web".
AiSettings
¶
Bases: _Model
The ai block (BE-0047) — which provider/model/endpoint/key the AI paths use.
defaults.ai is overridable per targets.<name>.ai. Keys never live here: keyEnv is the NAME
of the env var holding the key, read at call time, so a secret never lands in the repo or an
uploaded bundle. Every field is optional; an unset field falls back to the environment in the
factory. extra="forbid" (from _Model) rejects a stray apiKey:-style field that would tempt
a literal key into config.
Config
¶
Bases: _Model
A parsed bajutsu.config.yaml: team defaults and per-target config.
The hosted multi-tenancy orgs: block is a serve concern the core does not model (BE-0129);
parse_config_dict drops it before validation so a run reading an org-bearing config keeps
working, and bajutsu.serve.orgs owns the org model.
Defaults
¶
Bases: _Model
Team-wide defaults under defaults:, overlaid by each target (see resolve).
DeviceProvider
¶
Bases: _Model
Where a target's devices come from (targets.<name>.deviceProvider, BE-0236).
kind selects the provider adapter from the device-provider registry, defaulting to local — a
locally-attached simulator / emulator / device, exactly today's --udid path — so an omitted
block is unchanged. A device-cloud kind reserves a device off-host and hands the run its serial
/ endpoint instead. endpoint carries that address for the kinds that need one (the appium live
path points at a reserved iOS device's Appium / WebDriver endpoint, BE-0238). Like the mailbox
kind, an unknown value — or a required-but-missing endpoint — fails closed when the run resolves
the provider, not here: the deterministic config must not import a cloud SDK (BE-0112).
DoctorConfig
¶
Bases: _Model
Configurable thresholds for bajutsu doctor's id-coverage grading (BE-0024).
idCoverageOk is the minimum coverage to be eligible for "Ready"; idCoverageFail
is the ceiling below which the grade drops to "Blocked". Both must be in [0, 1] with
ok >= fail.
LaunchServer
¶
Bases: _Model
How to bring up the app's target server (the host behind baseUrl) for a run.
Unlike mockServer (which stubs the dependencies the app calls), this hosts the app under
test itself — e.g. the static page for demos/web, or the inner serve the WebUI dogfood
drives. run probes readyUrl first: if it already answers it reuses it (started externally),
else it runs cmd, waits on the readiness probe (a condition wait, never a fixed sleep), and
tears the process down afterwards.
Mailbox
¶
Bases: _Model
A mailbox the email step polls (targets.<name>.mailbox, BE-0046 / BE-0186).
kind selects the transport adapter (http, later imap) from the mailbox registry, defaulting
to http so a pre-BE-0186 block is unchanged; an unknown kind fails closed when the runner
resolves the mailbox, not here (the deterministic config must not import the registry, BE-0112).
url is the inbox endpoint (GET; commonly ${secrets.*}), headers any auth. The optional
response mapping absorbs a provider's JSON shape without per-provider code: messages is a
dotted path to the message array (empty = the response is the array), and fields maps each
normalized field (to / subject / body / receivedAt / id) to the provider's key,
defaulting to the field's own name.
MockServer
¶
Bases: _Model
A mock server that stubs the dependencies the app under test calls (mockServer: config).
NotifyEndpoint
¶
Bases: _Model
One webhook notification sink (notify: list entry, BE-0099).
PricingEntry
¶
Bases: _Model
Per-token rates for one (provider, model) in ai.pricing (BE-0196), USD per million tokens.
Overrides a shipped default. cacheWrite / cacheRead default to 0 for a provider that does
not price cache separately, so an entry may name only input / output.
TargetConfig
¶
Bases: _Model
One app's config under targets.<name>, overriding defaults for that target.
XcuitestConfig
¶
Bases: _Model
Per-target XCUITest runner config (targets.<name>.xcuitest, BE-0019).
android_package(eff)
¶
The Android target's package, or "" for a non-Android target.
idb_version_pin(eff)
¶
The iOS target's declared idb version range (defaults.idbVersion), or None when unpinned.
ios_bundle_id(eff)
¶
The iOS target's bundle id, or "" for a non-iOS target.
require_android(eff)
¶
The Android sub-config, narrowed for the type checker, or a loud failure (BE-0126 / BE-0007).
The Android counterpart of require_ios / require_web, for code already on an adb-only path
(the AndroidEnvironment lifecycle).
require_ios(eff)
¶
The iOS sub-config, narrowed for the type checker, or a loud failure (BE-0126).
For code already committed to an iOS-only path (the iOS/XCUITest environment, the idb doctor
probe): it narrows the platform union to IosConfig and fails fast rather than silently reading
a default if a non-iOS target ever reaches it. Code that has not committed to a platform must
narrow with isinstance / match instead — reading a platform's knobs off platform_config
without narrowing is a type error, which is the point of the split.
require_web(eff)
¶
The web sub-config, narrowed for the type checker, or a loud failure (BE-0126).
The web counterpart of require_ios, for code already on a web-only path (the web environment,
the Playwright doctor probe).
web_base_url(eff)
¶
The web target's base URL, or None for a non-web target.
web_engine(eff)
¶
The web target's rendering engine, or the chromium default for a non-web target.
xcuitest_targets_real_device(eff)
¶
True when the target drives a real iOS device via XCUITest (xcuitest.deviceType: device).
The Simulator default — and every non-iOS target — is False. Consulted by the capability narrowing that drops the simctl-backed DeviceControl / permission tokens on a real device (BE-0238): simctl reaches only the Simulator, so those capabilities do not apply on a physical device.
load_config(text)
¶
Parse a YAML config string into a Config (see parse_config_dict).
parse_config_dict(data)
¶
Validate an already-parsed config document into a Config.
Top-level orgs: and ui: keys are dropped before validation: the hosted multi-tenancy org
model (BE-0129) and the serve UI's ui.default_theme (BE-0191) are serve concerns the
deterministic core does not model, and a run in the hosted topology legitimately reads a config
carrying them, so the core must ignore the keys rather than reject them under extra="forbid".
bajutsu.serve.orgs / bajutsu.serve.themes parse those blocks separately. Every other unknown
key still fails loudly, preserving the typo guard.
bajutsu.config_source
¶
Acquire a config (and its scenario tree) from a Git source (BE-0063).
--config keeps accepting a local path; in addition it accepts a Git spec
(github:<owner>/<repo>[@<ref>][:<path>], or git+https://<host>/<owner>/<repo>.git[@<ref>][#<path>]).
The spec is materialized at an immutable commit SHA into a content-addressed cache, and the config's
relative paths resolve against that checkout root. Only acquisition changes — the schema, runner,
drivers, and the deterministic gate are untouched (DESIGN §6.5: git holds the history).
The GitHub transport (commits API + tarball endpoint) is the one external dependency; it is a small injectable seam so the materialization logic tests offline against a fake.
GitConfigSpec
dataclass
¶
A parsed Git config source: which repo subtree, at which ref, to load the config from.
Materialized
dataclass
¶
A repo subtree checked out at an immutable SHA: the config file, the checkout root, and the SHA.
Transport
¶
Bases: Protocol
The Git-host calls materialization makes — injected so the logic tests offline.
is_full_sha(ref)
¶
Whether ref is a full 40-hex commit SHA — the only ref that is an immutable, offline pin.
parse_config_spec(value)
¶
Parse a --config value into a GitConfigSpec, or None when it is an ordinary local path.
A value with no recognized Git scheme is a local path, so every existing invocation is unchanged.
A repo of exactly . or .. is a same-segment traversal (BE-0124) and is refused here, so it
fails the same way an unparseable value does rather than reaching the cache path.
source_from_config(config)
¶
A config-source record (kind + locator) for config (BE-0225).
A Git spec becomes a git source, anything else a local file source — the discriminated shape
the project registry stores and serve auto-registers (launch_project_identity), so a config
registered from the CLI or the API round-trips back through the run/bind path.
config_from_source(source)
¶
Reconstruct a --config spec from a stored config-source record (BE-0225).
The inverse of source_from_config, so a registered project drives the ordinary run/bind path. A
git source rebuilds the github: / git+https:// spec, preferring the resolved sha (an
immutable pin the launch auto-register stamps) over a moving ref. A file source is its path.
Raises:
| Type | Description |
|---|---|
ValueError
|
the record is malformed (not a record, no locator, a |
github_http_error_message(status, headers, spec)
¶
Turn a GitHub HTTPError into an actionable message that names the real cause (BE-0224).
The rate-limit and SSO sub-types are checked before the catch-all so neither is misreported as
missing repository access — more Contents: read permission fixes neither. The 404/other-403
fall-through names the most-likely-missing grant.
github_token()
¶
A GitHub token for private repos, else gh auth token, else None.
Checks the bajutsu-owned BAJUTSU_GIT_CONFIG_TOKEN (a serve-entered credential) first, then
GITHUB_TOKEN / GH_TOKEN, so a UI credential wins over an ambient token (BE-0224).
resolve_github_credential(spec)
¶
The bearer token for spec, in documented precedence order (BE-0224).
A configured GitHub App installation first (a short-lived, per-installation, service-identity
token — the answer for an unattended host), then the GITHUB_TOKEN / GH_TOKEN / gh auth token
chain of github_token(), else anonymous. Resolved per acquisition (the transport is built
per materialize), so a rotated secret takes effect without a serve restart.
source_provenance(spec, mat)
¶
The run-provenance stamp for a Git config source: repo + the ref it was asked for + the SHA.
Recording the resolved sha makes a branch-based run reproducible after the fact (BE-0063) — it
states the exact commit executed, not just the moving branch.
materialize(spec, *, transport=None, cache_root=None, offline=False)
¶
Check out spec's subtree at its resolved commit SHA into a content-addressed cache.
The ref is resolved to an immutable SHA (the determinism anchor), then the tree is fetched once
and extracted under <cache>/<host>/<owner>/<repo>/<sha>/. Because the directory is keyed by the
SHA, a cache hit is always valid and a pinned-SHA run is offline after the first fetch.
With offline (the --config-offline switch) it never touches the network: the ref must already
be a full SHA (a branch/tag can't be resolved offline) and that SHA must already be cached.