internal/api/handler.go-- Main API handler with POST /exec, GET /health, GET /versioninternal/api/ratelimit.go-- Token bucket rate limiter per SSH key fingerprintinternal/api/handler_test.go-- 18 tests covering all endpoints and error casesinternal/db/migrations/004_api_tokens.sql-- Migration for api_tokens table
internal/db/models.go-- Added APIToken modelinternal/db/queries.go-- Added CRUD methods for API tokens
- POST /exec endpoint with JSON and text/plain body support
- GET /health -- returns status + timestamp
- GET /version -- returns version + Go version
- Authentication:
usy0.stateless tokens (SSH-key-signed permissions JSON)usy1.short tokens (DB-backed, opaque token ID)
- Token permissions: time-based (exp/nbf) + command whitelist
- Rate limiting: per-fingerprint token bucket (60 req/min default, burst 10)
- Error codes: 400, 401, 403, 404, 405, 413, 422, 429, 500, 504
- API token CRUD: Create, Read, List, Revoke, Touch (last_used_at), Delete
All 18 tests passing.
internal/admin/admin.go-- Main admin handler (760+ lines): sessions, auth, routes, DB queries, template helpersinternal/admin/embed.go-- go:embed directive for WebFS (templates + static assets)internal/admin/admin_test.go-- 27 tests covering session mgmt, auth, login flow, all page handlers, trust level updates, template helpersinternal/admin/web/static/style.css-- Dark theme CSS with purple accent, terminal aestheticinternal/admin/web/templates/layout.html-- Shared layout with sidebar nav, logout forminternal/admin/web/templates/login.html-- Login page with magic link instructionsinternal/admin/web/templates/dashboard.html-- Dashboard with stats grid + recent users tableinternal/admin/web/templates/users.html-- Users table with VM/key countsinternal/admin/web/templates/user_detail.html-- User detail with trust level form, SSH keys table, VMs tableinternal/admin/web/templates/vms.html-- VMs table with owner, status, resources, IPinternal/admin/web/templates/vm_detail.html-- VM detail grid with tags, shares tableinternal/admin/web/templates/nodes.html-- Nodes placeholder page (scheduler.NodeProvider not in SQLite)
- Authentication: Magic link token login via
/admin/login/callback?token=xxx - Session management: In-memory session store with auto-cleanup goroutine, 24h TTL, secure cookies
- Trust level gate: Only
operatorandadminusers can access the panel - Dashboard: Aggregate stats (users, VMs by status, shares, API tokens) + recent users
- Users page: Full user listing with VM/key counts (correlated subqueries)
- User detail: User info, SSH keys, VMs, trust level update form (POST)
- VMs page: All VMs with owner handles (LEFT JOIN), status badges
- VM detail: Full VM info, tags, shares
- Nodes page: Placeholder for scheduler.NodeProvider integration
- CSS handler: Serves embedded static CSS with cache headers
- Template helpers:
timeAgo,trustBadge,statusBadge,nullStr,nullInt,truncate,add
GET /admin/-- Dashboard (auth required)GET /admin/login-- Login pageGET /admin/login/callback-- Magic link callbackPOST /admin/logout-- LogoutGET /admin/users-- Users list (auth required)GET /admin/users/{id}-- User detail (auth required)POST /admin/users/{id}/trust-- Update trust level (auth required)GET /admin/vms-- VMs list (auth required)GET /admin/vms/{id}-- VM detail (auth required)GET /admin/nodes-- Nodes (auth required, placeholder)GET /admin/static/style.css-- Static CSS
All 27 tests passing:
- Session store: Create/Get, expired session, delete, clean expired, unique IDs
- Auth middleware: no cookie redirect, invalid session redirect, valid session access
- Login page: renders OK
- Login callback: missing token, invalid token, non-admin rejected, admin success, operator success
- Logout: session deleted, cookie cleared
- Dashboard: authenticated with stats
- Users page: lists users
- User detail: shows user/VM/key data, invalid ID (400), not found (404)
- Trust level: update success, invalid level rejected
- VMs page: lists VMs with owners
- VM detail: shows VM data, not found (404)
- Nodes page: shows placeholder
- CSS handler: serves CSS with correct content type
- Template helpers: timeAgo (9 cases), trustBadge (5 cases), statusBadge (5 cases)
internal/db/migrations/008_user_quotas.sql-- Addsvm_limit,cpu_limit,ram_limit_mb,disk_limit_mbcolumns to users tableinternal/db/quota_test.go-- 7 tests covering trust levels, quotas, and enforcement
internal/db/models.go-- AddedTrustLimitsstruct,ValidTrustLevels,IsValidTrustLevel(),GetTrustLimits()internal/db/queries.go-- AddedGetUserTrustLevel,SetUserTrustLevel,GetUserVMCount,GetUserQuotasinternal/ssh/commands.go-- Added quota checks incmdNew/cmdCp,admincommand withset-trustsubcommand, conditional admin help section
- Trust levels: newbie (3 VMs, 1 CPU, 2GB RAM, 5GB disk), citizen (10/4/8GB/25GB), operator (25/8/16GB/100GB), admin (unlimited)
- Quota enforcement: VM creation (
new,cp) checks user's VM count against trust level limits - Admin command:
admin set-trust <handle> <level>-- admin-only gate on trust_level - DB queries: Trust level CRUD, quota retrieval, VM count (alias for API consistency)
All 7 quota tests passing:
TestGetTrustLimits(4 levels + unknown fallback)TestIsValidTrustLevel(4 valid + 5 invalid)TestGetUserTrustLevel(default newbie)TestSetUserTrustLevel(upgrade to citizen, admin; verify quotas updated; invalid level error)TestGetUserVMCount(0 count, 3 after creates)TestQuotaEnforcement(limit reached, upgrade expands, admin unlimited, delete decreases)TestGetUserQuotas(newbie defaults match)
internal/db/migrations/009_custom_domains.sql-- Createscustom_domainstable with vm_id, domain (UNIQUE), verified, verification_token, created_at, verified_at; CASCADE delete on vm removalinternal/db/custom_domain_test.go-- 8 tests covering full CRUD, duplicate prevention, cascade delete, and constraint enforcement
internal/db/models.go-- AddedCustomDomainstructinternal/db/queries.go-- AddedCreateCustomDomain,GetCustomDomain,VerifyCustomDomain,ListCustomDomains,DeleteCustomDomaininternal/ssh/commands.go-- Addedshare cname,share cname-verify,share cname-rmsubcommands; updated share help text; addedisValidDomainhelperinternal/proxy/caddy.go-- AddedAddCustomDomain(domain, vmName)andRemoveCustomDomain(domain)methods withcustomDomainRouteIDhelper
- Custom domain mapping:
share cname <vm> <domain>creates a domain record with a verification token - DNS verification:
share cname-verify <vm> <domain>performs anet.LookupTXTon_ussycode-verify.<domain>to verify ownership - Domain removal:
share cname-rm <vm> <domain>removes the domain and its proxy route - Proxy integration: Verified domains get a Caddy reverse proxy route via
AddCustomDomain; routes are cleaned up on removal - Domain validation:
isValidDomain()checks length (3-253), requires at least one dot, validates label format (a-z, 0-9, hyphens, max 63 chars) - Duplicate prevention: UNIQUE constraint on domain column prevents same domain on multiple VMs
- Cascade delete: Deleting a VM automatically removes its custom domains (ON DELETE CASCADE)
- User guidance: Commands display DNS setup instructions (CNAME record + TXT verification record)
share cname <vm> <domain>-- Add custom domain, display verification instructionsshare cname-verify <vm> <domain>-- Verify DNS TXT record and activate domainshare cname-rm <vm> <domain>-- Remove custom domain and proxy route
All 8 custom domain tests passing:
TestCreateCustomDomain-- Creates domain, verifies fieldsTestCreateCustomDomain_Duplicate-- UNIQUE constraint enforcementTestVerifyCustomDomain-- Marks domain verified, sets verified_atTestListCustomDomains-- Lists 3 domains for VM, 0 for other VMTestDeleteCustomDomain-- Deletes domain, confirms goneTestGetCustomDomain_NotFound-- Returns sql.ErrNoRowsTestCustomDomain_CascadeDelete-- VM deletion cascades to custom domainsTestIsValidDomainLogic-- UNIQUE constraint across different VMs