Skip to main content

stackql_mcp/
pins.rs

1//! Per-platform sha256 pins for the packaged stackql release.
2//!
3//! The pins are NOT hand-written here: `build.rs` renders them from
4//! `platforms.json`, which `packaging/mcpb/scripts/render-platforms.sh` writes
5//! from the published `.mcpb.sha256` release assets. The same manifest drives
6//! every wrapper vector (npm, PyPI, and the other SDKs).
7
8use crate::error::{Error, Result};
9use crate::platform::Platform;
10
11/// A pinned bundle: name and sha256 as published on the GitHub release.
12#[derive(Clone, Copy, Debug)]
13pub struct Pin {
14    pub platform_key: &'static str,
15    pub bundle_name: &'static str,
16    pub sha256: &'static str,
17}
18
19// STACKQL_VERSION, BASE_URL, PINS
20include!(concat!(env!("OUT_DIR"), "/pins_gen.rs"));
21
22/// Look up the pin for a platform. Every `Platform` variant has a pin; a miss
23/// here is a crate bug, so it surfaces as `UnsupportedPlatform`.
24pub fn pin_for(platform: Platform) -> Result<&'static Pin> {
25    PINS.iter()
26        .find(|p| p.platform_key == platform.key())
27        .ok_or(Error::UnsupportedPlatform {
28            os: std::env::consts::OS,
29            arch: std::env::consts::ARCH,
30        })
31}
32
33/// Download URL for a pinned bundle: `<baseUrl>/<bundle>` from platforms.json.
34pub fn bundle_url(pin: &Pin) -> String {
35    format!("{BASE_URL}/{}", pin.bundle_name)
36}
37
38/// User-Agent for bundle downloads, so the download proxy can attribute
39/// traffic to this vector and version.
40pub fn user_agent() -> String {
41    format!("stackql-mcp-server-cargo/{STACKQL_VERSION}")
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn every_platform_has_a_pin() {
50        for platform in [
51            Platform::LinuxX64,
52            Platform::LinuxArm64,
53            Platform::WindowsX64,
54            Platform::DarwinUniversal,
55        ] {
56            let pin = pin_for(platform).unwrap();
57            assert_eq!(pin.platform_key, platform.key());
58            assert_eq!(
59                pin.bundle_name,
60                format!("stackql-mcp-{}.mcpb", platform.key())
61            );
62        }
63    }
64
65    #[test]
66    fn pins_are_well_formed_sha256_hex() {
67        for pin in PINS {
68            assert_eq!(pin.sha256.len(), 64, "{}", pin.bundle_name);
69            assert!(
70                pin.sha256.chars().all(|c| c.is_ascii_hexdigit()),
71                "{}",
72                pin.bundle_name
73            );
74            assert_eq!(pin.sha256, pin.sha256.to_lowercase());
75        }
76    }
77
78    #[test]
79    fn bundle_url_is_the_proxy_front_door_for_the_pinned_version() {
80        let pin = pin_for(Platform::LinuxX64).unwrap();
81        assert_eq!(
82            bundle_url(pin),
83            format!(
84                "https://releases.stackql.io/stackql/{STACKQL_VERSION}/stackql-mcp-linux-x64.mcpb"
85            )
86        );
87        assert_eq!(
88            user_agent(),
89            format!("stackql-mcp-server-cargo/{STACKQL_VERSION}")
90        );
91    }
92}