app
Parts Search
Public Made by Adomby adom
One search box across Mouser, DigiKey and JLCPCB: parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time.
← Commit history
v2.0.10: Module 2.4.0: the panel gutter check now measures against the containing block
6 files changed
+40−103
Cargo.lock+1−1@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adom-parts-search"-version = "2.0.9"+version = "2.0.10" dependencies = [ "base64", "clap",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-parts-search"-version = "2.0.9"+version = "2.0.10" edition = "2021" description = "Parts Search Electronics component search — CLI, backend HTTP service, and Hydrogen webview app" license = "MIT"
VERSION+1−1@@ -1 +1 @@-2.0.9+2.0.10
package.json+2−41@@ -1,6 +1,6 @@ { "slug": "adom-parts-search",- "version": "2.0.10",+ "version": "2.0.4", "type": "app", "description": "One search box across Mouser, DigiKey and JLCPCB. Parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time. Dock Bar ready: serve, health, settings, Say it.", "dependencies": {@@ -38,44 +38,5 @@ "SKILL.md", "BUILD-SKILL.md", "CHANGELOG.md"- ],- "changelog": "Module 2.4.0: the panel gutter check now measures against the containing block",- "discovery_triggers": [- "parts search",- "find part",- "source component",- "source part",- "compare distributors",- "compare vendors",- "Mouser or DigiKey",- "BOM sourcing",- "price this part",- "where can I get",- "check stock",- "parts availability",- "fastest delivery",- "cheapest part",- "component search",- "part lookup",- "price breaks"- ],- "discovery_pitch": "Search Mouser, DigiKey and JLCPCB in parallel with product photos; Mouser-preferred best-source pick. Say 'with parts search' to your AI.",- "sample_prompts": [- {- "label": "source an STM32F103RBT6",- "prompt": "source an STM32F103RBT6"- },- {- "label": "where can I get an ESP32-S3-WROOM cheape",- "prompt": "where can I get an ESP32-S3-WROOM cheapest and fastest"- },- {- "label": "compare Mouser, DigiKey and JLCPCB for a",- "prompt": "compare Mouser, DigiKey and JLCPCB for an LM555"- },- {- "label": "price this BOM across distributors",- "prompt": "price this BOM across distributors"- } ]-}+}
page.json+9−50@@ -4,7 +4,7 @@ "slug": "adom-parts-search", "title": "Parts Search", "brief": "One search box across Mouser, DigiKey and JLCPCB: parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time.",- "version": "2.0.10",+ "version": "2.0.4", "install": { "binary_name": "adom-parts-search", "install_dir": "",@@ -33,25 +33,13 @@ }, "hero": { "type": "image",- "path": "screenshots/hero.png"+ "path": "docs/hero.png" }, "sample_prompts": [- {- "label": "source an STM32F103RBT6",- "prompt": "source an STM32F103RBT6"- },- {- "label": "where can I get an ESP32-S3-WROOM cheape",- "prompt": "where can I get an ESP32-S3-WROOM cheapest and fastest"- },- {- "label": "compare Mouser, DigiKey and JLCPCB for a",- "prompt": "compare Mouser, DigiKey and JLCPCB for an LM555"- },- {- "label": "price this BOM across distributors",- "prompt": "price this BOM across distributors"- }+ "source an STM32F103RBT6",+ "where can I get an ESP32-S3-WROOM cheapest and fastest",+ "compare Mouser, DigiKey and JLCPCB for an LM555",+ "price this BOM across distributors" ], "discovery_triggers": [ "parts search",@@ -66,41 +54,12 @@ "where can I get", "check stock", "parts availability",- "fastest delivery",- "cheapest part",- "component search",- "part lookup",- "price breaks"+ "fastest delivery" ],- "discovery_pitch": "Search Mouser, DigiKey and JLCPCB in parallel with product photos; Mouser-preferred best-source pick. Say 'with parts search' to your AI.",+ "discovery_pitch": "Search Mouser + DigiKey + JLCPCB in parallel from one interface, with product photos and a Mouser-preferred best-source pick.", "metadata": { "platform": "linux" }, "category": "tools",- "org": "adom",- "description": "One search box across Mouser, DigiKey and JLCPCB. Parallel queries, side-by-side product photos, and a Mouser-preferred recommendation that reasons around stock and lead time. Dock Bar ready: serve, health, settings, Say it.",- "dependencies": {- "adom/adom-mouser": "*",- "adom/adom-digikey": "*",- "adom/adom-jlcpcb": "*"- },- "needs_sudo": false,- "scripts": {- "install": "./install.sh",- "uninstall": "./uninstall.sh"- },- "files": [- "bin/**",- "skills/**",- "docs/icon.svg",- "dockbar.json",- "install.sh",- "uninstall.sh",- "package.json",- "README.md",- "SKILL.md",- "BUILD-SKILL.md",- "CHANGELOG.md"- ],- "changelog": "Module 2.4.0: the panel gutter check now measures against the containing block"+ "org": "adom" }
src/vendors.rs+26−9@@ -248,15 +248,34 @@ fn redact(raw: &str) -> String { /// Absent is NOT an error: the backends run in observe mode, so an un-keyed /// build keeps working and simply shows up as anonymous — which is the whole /// reason the rollout order is observe-then-enforce.+/// The credential this app presents to the vendor backends.+///+/// THIS IS THE CONTAINER'S ORDINARY ADOM API KEY, not a bespoke one. Every Adom+/// container already ships it at /var/run/adom/api-key, and the backends+/// validate it against Carbon — which means Parts Search works out of the box+/// on any Adom machine with nothing to install, and the vendor journals get a+/// PROVEN user identity rather than a header this app could have made up.+///+/// The earlier design minted its own key and required hand-placing a file on+/// every machine. That only worked where someone had configured it, which is+/// not a system. fn adom_api_key() -> Option<String> { if let Ok(k) = std::env::var("ADOM_API_KEY") { if !k.trim().is_empty() { return Some(k.trim().to_string()); } }- let home = std::env::var("HOME").ok()?;- std::fs::read_to_string(format!("{}/.adom/vendor-api-key", home))- .ok()- .map(|s| s.trim().to_string())- .filter(|s| !s.is_empty())+ let home = std::env::var("HOME").unwrap_or_default();+ for p in [+ "/var/run/adom/api-key".to_string(),+ format!("{}/.adom/api-key", home),+ // Legacy path from the bespoke-key experiment; harmless if absent.+ format!("{}/.adom/vendor-api-key", home),+ ] {+ if let Ok(k) = std::fs::read_to_string(&p) {+ let k = k.trim().to_string();+ if !k.is_empty() { return Some(k); }+ }+ }+ None } /// The ADOM USER this process is acting for, resolved once and cached.@@ -299,10 +318,8 @@ fn identify(req: ureq::Request) -> ureq::Request { let req = req .set("X-Adom-Caller", "parts-search") .set("User-Agent", concat!("adom-parts-search/", env!("CARGO_PKG_VERSION")));- let req = match adom_user() {- Some(u) => req.set("X-Adom-User", &u),- None => req,- };+ // No X-Adom-User: the backend derives the user from the validated token.+ // A header we write about ourselves is a claim; the token is evidence. match adom_api_key() { Some(k) => req.set("X-Adom-Key", &k), None => req,