Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,14 @@ jobs:
- run: cargo test --workspace

release-invariants:
# #176: turn the #161-class privacy invariant into a permanent gate. CI's
# #176/#177: turn the #161-class privacy invariant into a permanent gate. CI's
# other jobs only compile/test the DEBUG profile, so a dropped
# `#[cfg(debug_assertions)]` guard (e.g. a bad merge on the #64 bleed dump or a
# #108 dev flag) is invisible to them and only surfaces at tag time. This job
# compiles livecap-app in RELEASE and asserts the debug-only env-escape NAMES
# are absent from the binary — they exist only inside `#[cfg(debug_assertions)]`
# items, so a release build compiles them out entirely (#146/#161).
# `#[cfg(debug_assertions)]` guard (e.g. a bad merge on the #64 bleed dump, a
# #108 dev flag, or the #177 model-base-url knob) is invisible to them and only
# surfaces at tag time. This job compiles livecap-app in RELEASE and asserts the
# debug-only env-escape NAMES are absent from the binary — they exist only
# inside `#[cfg(debug_assertions)]` items, so a release build compiles them out
# entirely (#146/#161/#177).
runs-on: macos-14
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
Expand Down Expand Up @@ -98,7 +99,7 @@ jobs:
# These env vars are read ONLY inside #[cfg(debug_assertions)] items, so a
# release build must contain none of their names. A hit means a guard was
# dropped and the shipped binary regained a covert env path (#161-class).
FORBIDDEN="LIVECAP_BLEED_DUMP_DIR LIVECAP_CAPTURE_VISIBLE LIVECAP_AUTOSTART LIVECAP_UI_PROBE"
FORBIDDEN="LIVECAP_BLEED_DUMP_DIR LIVECAP_CAPTURE_VISIBLE LIVECAP_AUTOSTART LIVECAP_UI_PROBE LIVECAP_MODEL_BASE_URL"
fail=0
for name in $FORBIDDEN; do
if strings "$BIN" | grep -q "$name"; then
Expand Down
18 changes: 17 additions & 1 deletion crates/livecap-core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,29 @@ const HF_REPO: &str = "https://huggingface.co/ggerganov/whisper.cpp";
/// source — [`pointer_url`] is pinned to the official [`HF_REPO`] — so an
/// overridden host cannot serve a fake LFS pointer alongside a matching fake
/// blob; any blob that does not match the OFFICIAL digest fails verification.
// Release builds never read this env var (#177), so the const is unused there —
// which is the point: an unused const emits no string, so the release binary
// carries no `LIVECAP_MODEL_BASE_URL` symbol (asserted by the release-invariants
// CI gate). The `allow(dead_code)` only silences the release-profile warning.
#[cfg_attr(not(debug_assertions), allow(dead_code))]
const MODEL_BASE_URL_ENV: &str = "LIVECAP_MODEL_BASE_URL";

/// The effective BLOB download base URL (env override or the official repo).
/// The effective BLOB download base URL. Debug builds honor the
/// [`MODEL_BASE_URL_ENV`] dev-run knob (#110 download-failure fallback); RELEASE
/// builds ALWAYS use the official [`HF_REPO`] — the env read is compiled out
/// entirely (#177, mirroring #146/#161), so a shipped binary exposes no such knob
/// and its model-download host can't be redirected. The pure
/// [`base_url_or_default`] core stays testable in both profiles.
#[cfg(debug_assertions)]
fn blob_base_url() -> String {
base_url_or_default(std::env::var(MODEL_BASE_URL_ENV).ok())
}

#[cfg(not(debug_assertions))]
fn blob_base_url() -> String {
base_url_or_default(None)
}

/// Pure core of [`blob_base_url`]: `None`/blank → the official repo. Trailing
/// slashes are trimmed so the joined download URLs stay well-formed.
fn base_url_or_default(overridden: Option<String>) -> String {
Expand Down
Loading