huskies: rename project from storkit to huskies

Rename all references from storkit to huskies across the codebase:
- .storkit/ directory → .huskies/
- Binary name, Cargo package name, Docker image references
- Server code, frontend code, config files, scripts
- Fix script/test to build frontend before cargo clippy/test
  so merge worktrees have frontend/dist available for RustEmbed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Timmy
2026-04-03 16:12:52 +01:00
parent a7035b6ba7
commit 2d8ccb3eb6
572 changed files with 1340 additions and 1220 deletions
+35 -35
View File
@@ -9,7 +9,7 @@ fn default_permission_timeout_secs() -> u64 {
120
}
/// Configuration for the Matrix bot, read from `.storkit/bot.toml`.
/// Configuration for the Matrix bot, read from `.huskies/bot.toml`.
#[derive(Deserialize, Clone, Debug)]
pub struct BotConfig {
/// Matrix homeserver URL, e.g. `https://matrix.example.com`
@@ -145,12 +145,12 @@ fn default_whatsapp_provider() -> String {
}
impl BotConfig {
/// Load bot configuration from `.storkit/bot.toml`.
/// Load bot configuration from `.huskies/bot.toml`.
///
/// Returns `None` if the file does not exist, fails to parse, has
/// `enabled = false`, or specifies no room IDs.
pub fn load(project_root: &Path) -> Option<Self> {
let path = project_root.join(".storkit").join("bot.toml");
let path = project_root.join(".huskies").join("bot.toml");
if !path.exists() {
return None;
}
@@ -285,7 +285,7 @@ impl BotConfig {
/// array, and writes the result back. Errors are logged but not propagated
/// so a persistence failure never interrupts the bot's message handling.
pub fn save_ambient_rooms(project_root: &Path, room_ids: &[String]) {
let path = project_root.join(".storkit").join("bot.toml");
let path = project_root.join(".huskies").join("bot.toml");
let content = match std::fs::read_to_string(&path) {
Ok(c) => c,
Err(e) => {
@@ -334,7 +334,7 @@ mod tests {
#[test]
fn load_returns_none_when_disabled() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -354,7 +354,7 @@ enabled = false
#[test]
fn load_returns_config_when_enabled_with_room_ids() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -382,7 +382,7 @@ enabled = true
#[test]
fn load_merges_deprecated_room_id_into_room_ids() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
// Old-style single room_id key — should still work.
fs::write(
@@ -403,7 +403,7 @@ enabled = true
#[test]
fn load_returns_none_when_no_room_ids() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -422,7 +422,7 @@ enabled = true
#[test]
fn load_returns_none_when_toml_invalid() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(sk.join("bot.toml"), "not valid toml {{{").unwrap();
let result = BotConfig::load(tmp.path());
@@ -432,7 +432,7 @@ enabled = true
#[test]
fn load_respects_optional_model() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -453,7 +453,7 @@ model = "claude-sonnet-4-6"
#[test]
fn load_uses_default_history_size() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -473,7 +473,7 @@ enabled = true
#[test]
fn load_respects_custom_history_size() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -494,7 +494,7 @@ history_size = 50
#[test]
fn load_reads_display_name() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -515,7 +515,7 @@ display_name = "Timmy"
#[test]
fn load_display_name_defaults_to_none_when_absent() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -535,7 +535,7 @@ enabled = true
#[test]
fn load_uses_default_permission_timeout() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -555,7 +555,7 @@ enabled = true
#[test]
fn load_respects_custom_permission_timeout() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -579,7 +579,7 @@ permission_timeout_secs = 60
// must parse successfully — the field is simply ignored now that
// verification is always enforced unconditionally.
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -604,7 +604,7 @@ require_verified_devices = true
#[test]
fn load_reads_ambient_rooms() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -625,7 +625,7 @@ ambient_rooms = ["!abc:example.com"]
#[test]
fn load_ambient_rooms_defaults_to_empty_when_absent() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -645,7 +645,7 @@ enabled = true
#[test]
fn save_ambient_rooms_persists_to_bot_toml() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -667,7 +667,7 @@ enabled = true
#[test]
fn save_ambient_rooms_clears_when_empty() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -690,7 +690,7 @@ ambient_rooms = ["!abc:example.com"]
#[test]
fn load_transport_defaults_to_matrix() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -710,7 +710,7 @@ enabled = true
#[test]
fn load_transport_reads_custom_value() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -746,7 +746,7 @@ whatsapp_verify_token = "my-verify"
#[test]
fn load_whatsapp_returns_none_when_missing_phone_number_id() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -767,7 +767,7 @@ whatsapp_verify_token = "my-verify"
#[test]
fn load_whatsapp_returns_none_when_missing_access_token() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -788,7 +788,7 @@ whatsapp_verify_token = "my-verify"
#[test]
fn load_whatsapp_returns_none_when_missing_verify_token() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -811,7 +811,7 @@ whatsapp_access_token = "EAAtoken"
#[test]
fn load_twilio_whatsapp_reads_config() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -842,7 +842,7 @@ twilio_whatsapp_number = "+14155551234"
#[test]
fn load_whatsapp_provider_defaults_to_meta() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -865,7 +865,7 @@ whatsapp_verify_token = "my-verify"
#[test]
fn load_twilio_returns_none_when_missing_account_sid() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -887,7 +887,7 @@ twilio_whatsapp_number = "+14155551234"
#[test]
fn load_twilio_returns_none_when_missing_auth_token() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -909,7 +909,7 @@ twilio_whatsapp_number = "+14155551234"
#[test]
fn load_twilio_returns_none_when_missing_whatsapp_number() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -933,7 +933,7 @@ twilio_auth_token = "authtest"
#[test]
fn load_slack_transport_reads_config() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -959,7 +959,7 @@ slack_channel_ids = ["C01ABCDEF"]
#[test]
fn load_slack_returns_none_when_missing_bot_token() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -980,7 +980,7 @@ slack_channel_ids = ["C01ABCDEF"]
#[test]
fn load_slack_returns_none_when_missing_signing_secret() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),
@@ -1001,7 +1001,7 @@ slack_channel_ids = ["C01ABCDEF"]
#[test]
fn load_slack_returns_none_when_missing_channel_ids() {
let tmp = tempfile::tempdir().unwrap();
let sk = tmp.path().join(".storkit");
let sk = tmp.path().join(".huskies");
fs::create_dir_all(&sk).unwrap();
fs::write(
sk.join("bot.toml"),