Commit graph

12 commits

Author SHA1 Message Date
Sprite
fa2dc64438 refactor: consolidate cloud-init userdata to shared/common.sh
Moved duplicate get_cloud_init_userdata() function from all 4 cloud
provider common.sh files to shared/common.sh. This eliminates 60+ lines
of duplication and centralizes cloud-init configuration.

Changes:
- Added get_cloud_init_userdata() to shared/common.sh with detailed comments
- Removed duplicate function from hetzner/lib/common.sh
- Removed duplicate function from digitalocean/lib/common.sh
- Removed duplicate function from vultr/lib/common.sh
- Removed duplicate function from linode/lib/common.sh
- Added comment that clouds can override if needed

All tests pass (42 passed, 0 failed).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 21:45:44 +00:00
Sprite
26f8205cd9 refactor: Improve error messages for missing API tokens
Enhanced error messages across all cloud providers to be more actionable:
- Changed generic "API token/key is required" to "cannot be empty"
- Added specific authentication failure messages with provider URLs
- Included permission verification hints
- Added non-interactive mode environment variable suggestions

Benefits:
- Users get clear guidance on how to fix authentication issues
- Error messages now include direct links to token management pages
- Better UX for both interactive and non-interactive usage

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 21:45:06 +00:00
Sprite
8ead0752d5 refactor: consolidate SSH_OPTS to shared/common.sh
Moved duplicate SSH_OPTS constant from all 4 cloud provider common.sh
files to shared/common.sh. This removes 4 lines of duplication and
centralizes SSH configuration.

Changes:
- Added SSH_OPTS to shared/common.sh with comment explaining clouds can override
- Removed SSH_OPTS from hetzner/lib/common.sh
- Removed SSH_OPTS from digitalocean/lib/common.sh
- Removed SSH_OPTS from vultr/lib/common.sh
- Removed SSH_OPTS from linode/lib/common.sh

All tests pass (42 passed, 0 failed).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 21:44:19 +00:00
Sprite
5954455030 refactor: Add comprehensive bash safety flags to all agent scripts
- Changed 'set -e' to 'set -euo pipefail' in all 35 agent scripts
- Provides better error handling:
  - 'e': Exit on command failure
  - 'u': Exit on undefined variable usage
  - 'o pipefail': Exit on any pipe command failure
- Improves script reliability and debugging
- All tests pass (42/42)

Affected files:
- sprite/{aider,claude,codex,goose,interpreter,nanoclaw,openclaw}.sh
- hetzner/{aider,claude,codex,goose,interpreter,nanoclaw,openclaw}.sh
- digitalocean/{aider,claude,codex,goose,interpreter,nanoclaw,openclaw}.sh
- linode/{aider,claude,codex,goose,interpreter,nanoclaw,openclaw}.sh
- vultr/{aider,claude,codex,goose,interpreter,nanoclaw,openclaw}.sh

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 20:06:51 +00:00
Sprite
7162f9c236 refactor: secure temp files with chmod 600 before writing credentials
Added chmod 600 to all temporary files that contain sensitive data (API keys, tokens, configs):
- ENV_TEMP: 35 files (all agent scripts across 5 clouds)
- OPENCLAW_CONFIG_TEMP: 5 files (already done in previous commit)
- SETTINGS_TEMP: 5 files (Claude Code settings)
- GLOBAL_STATE_TEMP: 5 files (Claude Code global state)
- DOTENV_TEMP: 5 files (NanoClaw .env files)

Total: 55 temp files secured

This prevents race conditions where sensitive data could be read by other users
between mktemp creation (mode 600 by default) and data being written.

Security hardening for task #23.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 20:03:55 +00:00
Sprite
da7724da68 refactor: Extract SSH key management helpers to reduce nesting
Created helper functions in shared/common.sh to simplify ensure_ssh_key():
- generate_ssh_key_if_missing(key_path): Generate SSH key if needed
- get_ssh_fingerprint(pub_path): Get MD5 fingerprint
- json_escape(string): JSON-escape strings for API bodies

Refactored ensure_ssh_key() in all cloud providers to use these helpers:
- Reduced function length from 35-52 lines to 24-28 lines
- Eliminated nested conditionals
- Made the code flow more linear and readable
- Centralized SSH key generation and fingerprint logic

Benefits:
- Single source of truth for SSH key operations
- Reduced code duplication (~40 lines per provider → 3 helper functions)
- Easier to maintain and test
- More consistent error handling

All tests pass (42/42).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 20:03:43 +00:00
Sprite
528694123d refactor: Extract SSH wait logic to shared generic_ssh_wait function
Created generic_ssh_wait() in shared/common.sh to eliminate ~100 lines
of duplicated waiting logic across all cloud providers.

Changes:
- Added generic_ssh_wait(ip, ssh_opts, test_cmd, description, max_attempts, interval)
  to shared/common.sh
- Refactored verify_server_connectivity() in all clouds to use generic_ssh_wait
- Refactored wait_for_cloud_init() in all clouds to use generic_ssh_wait

Benefits:
- Single source of truth for SSH polling logic
- Consistent error messages across providers
- Reduced code duplication (~20 lines per provider → 2 lines)
- Easier to maintain and test

All tests pass (42/42).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 20:01:29 +00:00
Sprite
a403578721 refactor: linode/lib - add bash safety flags and variable quoting
- Add set -euo pipefail for strict error handling
- Make color constants readonly (RED, GREEN, YELLOW, NC)
- Make LINODE_API_BASE and SSH_OPTS readonly
- Quote numeric comparison variables in verify_server_connectivity
- Quote numeric comparison variables in wait_for_cloud_init
- Quote numeric comparison variables in create_server
- Quote process IDs and timeout variables in try_oauth_flow

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 19:54:11 +00:00
Sprite
d689f6f06c security: Add MODEL_ID input validation to prevent injection
Added validate_model_id() function to all common.sh files to prevent
command injection via user-supplied MODEL_ID values. MODEL_ID is used
in JSON configs, shell commands, and exported to remote systems, so
validation is critical.

Validation enforces that MODEL_ID contains only safe characters:
- Letters (a-z, A-Z)
- Numbers (0-9)
- Separators: / - _ : .

Rejects dangerous characters like backticks, $(), quotes, semicolons
that could be used for command injection.

Changes:
- Added validate_model_id() to all lib/common.sh files
- Added validation calls after MODEL_ID input in all agent scripts
- Tests pass for all sprite scripts

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 19:52:07 +00:00
Sprite
355c330507 security: Fix command injection in openclaw.sh files
Fixed command injection vulnerability in sprite/openclaw.sh where
OPENCLAW_CONFIG was echoed directly into remote shell command with
user-controlled MODEL_ID variable. Changed to use temp file + secure
upload instead of inline echo.

Also added chmod 600 to all OPENCLAW_CONFIG_TEMP files across all
cloud providers (linode, vultr, digitalocean, hetzner, sprite) to
prevent race condition where credentials could be exposed in temp
files before being written.

Changes:
- sprite/openclaw.sh: Replaced echo with temp file + sprite exec -file
- All openclaw.sh: Added chmod 600 after mktemp for credentials

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 19:48:09 +00:00
L
4f4d87c234
Add Open Interpreter as seventh agent across all clouds (#13)
Open Interpreter provides a natural language interface for computer control.
Works with OpenRouter via OPENAI_BASE_URL=https://openrouter.ai/api/v1.

- Implemented on all 5 clouds: sprite, hetzner, digitalocean, vultr, linode
- Matrix now 7 agents x 5 clouds = 35/35 implemented

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 09:30:27 -08:00
L
e781506604
Add Linode (Akamai) as fifth cloud provider with all 6 agents (#12)
Linode instances via REST API v4, with cloud-init via metadata.user_data.
- linode/lib/common.sh: API wrapper, token management, instance lifecycle
- All 6 agents: claude, openclaw, nanoclaw, aider, goose, codex

Matrix now 6 agents x 5 clouds = 30/30 implemented.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 09:26:31 -08:00