youtube-legend-cli 0.4.0

Non-interactive Rust CLI that downloads YouTube subtitles through third-party providers, using a native Unix stdin/stdout interface.
#![allow(missing_docs)]
#![allow(clippy::redundant_locals)]
//! Nomes de provedores, endpoints e tokens usados internamente pelo binário.
//!
//! ATENCAO: este modulo e INFORMACAO RESERVADA.
//! Os identificadores aqui NAO DEVEM ser expostos em
//! - documentacao publica (README, CHANGELOG)
//! - mensagens de stderr
//! - logs de tracing
//! - issues de bug tracker publico
//! - comentarios de codigo fora deste modulo
//!
//! Politica de governanca: a existencia deste pipeline de 2 provedores
//! e segredo de implementacao. O README publico afirma apenas que a
//! ferramenta baixa legendas do `YouTube`, sem nomear fontes.
//!
//! O `#![allow(missing_docs)]` no topo do arquivo e proposital:
//! este modulo e interno e nunca aparece em rustdoc publicado,
//! portanto nao precisa de doc comments em cada constante.
//!
//! Cada constante carrega `#[doc(hidden)]` para que uma extracao de
//! superficie publica nao gere entradas com nomes sigilosos.
//!
//! CORRIGIDO em 2026-08-31: este cabecalho afirmava que um gate no job
//! CI `public-api` validava a invariante em todo PR. Esse job NAO
//! existe: o CI foi removido do projeto, e a propria remocao esta
//! registrada no CHANGELOG. A invariante ficou sem nenhum validador,
//! e a afirmacao era pior que o silencio, porque quem a lia parava de
//! procurar. Quem valida agora e o teste local
//! `secret_identifiers_never_leak_outside_this_module`, no fim deste
//! arquivo, que roda junto com o resto da suite.

// GAP-AUD-2026-038 recorded a single exclusive provider from v0.3.2,
// reached through a headless browser. That stopped being true on
// 2026-09-04: the provider was removed with the whole browser
// subsystem, and no headless path survives anywhere in this tree.
// The paragraph describing that provider's page and its extraction
// route was deleted rather than corrected, because there is nothing
// left for it to describe.
//
// The constants are `#[allow(dead_code)]` so the `snapshot` binary
// (which builds without the `headless` feature) compiles cleanly.
// The two browser-driven providers were removed on 2026-09-04, and
// their host, origin and UI-route constants left with them. What
// remains is the pair of HTTP providers that still answer.
#[doc(hidden)]
#[allow(dead_code)]
pub(crate) const DECOPY_API_HOST: &str = "api.decopy.ai";
#[doc(hidden)]
#[allow(dead_code)]
pub(crate) const DECOPY_API_BASE: &str = "https://api.decopy.ai";
#[doc(hidden)]
#[allow(dead_code)]
pub(crate) const DECOPY_CREATE_JOB_PATH: &str = "/api/decopy/youtube-video/create-job2";
#[doc(hidden)]
#[allow(dead_code)]
pub(crate) const DECOPY_PRODUCT_CODE: &str = "067003";

#[doc(hidden)]
#[allow(dead_code)]
pub(crate) const NOIZ_API_HOST: &str = "backend.noiz.io";
#[doc(hidden)]
#[allow(dead_code)]
pub(crate) const NOIZ_API_BASE: &str = "https://backend.noiz.io";
#[doc(hidden)]
#[allow(dead_code)]
pub(crate) const NOIZ_SUBTITLES_PATH: &str = "/api/landing/youtube/subtitles";

/// Resolved upstream addresses.
///
/// Each constant above is the compiled default and each accessor below
/// reads the matching `net.endpoints.*` key first, so an operator can
/// follow a third party that moves a route without waiting for a
/// rebuild, and an offline test can aim the chain at a local server.
/// The values are read at call time rather than cached, because a
/// one-shot process resolves configuration once and then runs.
macro_rules! endpoint {
    ($name:ident, $key:literal, $default:ident, $doc:literal) => {
        #[doc(hidden)]
        #[doc = $doc]
        pub(crate) fn $name() -> String {
            crate::config::tuning_string_or($key, $default)
        }
    };
}

endpoint!(
    decopy_api_host,
    "net.endpoints.decopy.host",
    DECOPY_API_HOST,
    "Host of the decopy provider API."
);
endpoint!(
    decopy_api_base,
    "net.endpoints.decopy.base",
    DECOPY_API_BASE,
    "Scheme and authority of the decopy provider API."
);
endpoint!(
    decopy_create_job_path,
    "net.endpoints.decopy.create_job_path",
    DECOPY_CREATE_JOB_PATH,
    "Path of the decopy create-job endpoint."
);
endpoint!(
    decopy_product_code,
    "net.endpoints.decopy.product_code",
    DECOPY_PRODUCT_CODE,
    "Product code the decopy API requires."
);
endpoint!(
    noiz_api_host,
    "net.endpoints.noiz.host",
    NOIZ_API_HOST,
    "Host of the noiz provider API."
);
endpoint!(
    noiz_api_base,
    "net.endpoints.noiz.base",
    NOIZ_API_BASE,
    "Scheme and authority of the noiz provider API."
);
endpoint!(
    noiz_subtitles_path,
    "net.endpoints.noiz.subtitles_path",
    NOIZ_SUBTITLES_PATH,
    "Path of the noiz subtitles endpoint."
);

#[cfg(test)]
mod tests {
    /// Every reserved constant must carry `#[doc(hidden)]`.
    ///
    /// This replaces the CI gate the module header used to claim, which
    /// never existed. The check reads this file's own source rather than
    /// the compiled items, because the attribute is erased by the time
    /// the constants are values, and it is the attribute — not the
    /// value — that keeps the name out of a rendered doc page.
    #[test]
    fn every_reserved_constant_is_doc_hidden() {
        let source = include_str!("secret_endpoints.rs");
        let lines: Vec<&str> = source.lines().collect();
        let mut undeclared = Vec::new();
        for (index, line) in lines.iter().enumerate() {
            if !line.trim_start().starts_with("pub(crate) const ") {
                continue;
            }
            // Walk back over the attribute block that precedes the
            // constant; order among the attributes is not fixed, so the
            // search covers all of them instead of the line just above.
            let hidden = lines[..index]
                .iter()
                .rev()
                .take_while(|prior| prior.trim_start().starts_with('#'))
                .any(|prior| prior.contains("doc(hidden)"));
            if !hidden {
                undeclared.push(*line);
            }
        }
        assert!(
            undeclared.is_empty(),
            "reserved constants without #[doc(hidden)]: {undeclared:?}"
        );
    }

    /// Every endpoint accessor answers its compiled default when the
    /// tuning registry carries nothing.
    ///
    /// This pins the accessor to the constant, so a future edit that
    /// changes one without the other fails here. It does NOT prove that
    /// an override reaches the wire: that needs the binary aimed at a
    /// local server, which is the offline corpus work these keys exist
    /// to unblock.
    #[test]
    fn every_endpoint_accessor_falls_back_to_its_constant() {
        assert_eq!(super::decopy_api_host(), super::DECOPY_API_HOST);
        assert_eq!(super::decopy_api_base(), super::DECOPY_API_BASE);
        assert_eq!(
            super::decopy_create_job_path(),
            super::DECOPY_CREATE_JOB_PATH
        );
        assert_eq!(super::decopy_product_code(), super::DECOPY_PRODUCT_CODE);
        assert_eq!(super::noiz_api_host(), super::NOIZ_API_HOST);
        assert_eq!(super::noiz_api_base(), super::NOIZ_API_BASE);
        assert_eq!(super::noiz_subtitles_path(), super::NOIZ_SUBTITLES_PATH);
    }

    /// The API hosts must not appear in reader-facing docs.
    ///
    /// MEASURED on 2026-08-31, the first time this check ever ran: the
    /// README already names two of the four providers, so the module
    /// header's claim that it "names no sources" was false. That is a
    /// policy question for the owner, recorded as a gap, and this test
    /// does not decide it. What it does enforce is the half that is not
    /// in question: `api.decopy.ai` and `backend.noiz.io` are internal
    /// API endpoints that no document has ever had a reason to name,
    /// and a future edit that leaks one must fail here.
    ///
    /// The two site hosts are deliberately absent from this list. A
    /// test that fails on the current tree teaches the reader to
    /// ignore it, which is how the project ended up with an ignored
    /// SIGTERM test asserting a revoked contract.
    #[test]
    fn api_hosts_never_reach_the_public_readme() {
        let reserved = [super::DECOPY_API_HOST, super::NOIZ_API_HOST];
        for doc in ["README.md", "README.pt-BR.md"] {
            let Ok(body) = std::fs::read_to_string(doc) else {
                // A missing README is a packaging question, not a
                // secrecy breach, so it is not this test's business.
                continue;
            };
            for host in reserved {
                assert!(!body.contains(host), "{doc} names the reserved host {host}");
            }
        }
    }
}