diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md deleted file mode 100644 index 3bc8ceb92..000000000 --- a/.claude/CLAUDE.md +++ /dev/null @@ -1,189 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -This is the Hive platform - an AWS-compatible infrastructure stack for bare-metal, edge, and on-premise deployments. Hive orchestrates multiple independent components that work together to provide AWS-compatible services. - -## Component Repositories - -The Hive platform consists of these independent repositories: - -- **[viperblock](../viperblock/)** - High-performance block storage service (EBS alternative) with WAL-backed storage -- **[predastore](../predastore/)** - S3-compatible object storage service with Reed-Solomon erasure coding -- **nbdkit/** - Network Block Device (NBD) server for exporting block devices (upstream project) -- **hive/** (this repo) - VM orchestration service and platform coordinator - -Each component can be used independently or as part of the integrated Hive stack. See component-specific `CLAUDE.md` files for detailed development guidance: -- `../viperblock/CLAUDE.md` -- `../predastore/CLAUDE.md` - -## Commands - -### Go (backend) - -```bash -make preflight # Run ALL CI checks locally (format + vet + security + tests) -make build # Build hive binary to ./bin/hive -make test # Run all unit tests (sets LOG_IGNORE=1) -make check-format # Check gofmt (fails on diff, same as CI) -make format # Fix gofmt in place -make vet # Run go vet (fails on issues) -make security # Run go vet + govulncheck, gosec, staticcheck (fails on issues) -make bench # Run benchmarks -make clean # Remove build artifacts -make test-docker # Run single + multi-node E2E in Docker (requires /dev/kvm) -make test-docker-single # Single-node E2E only -make test-docker-multi # Multi-node E2E only -``` - -### Frontend (hive-ui) - -```bash -make build-ui # Production build -cd hive/services/hiveui/frontend && pnpm dev # Dev server on port 3000 -cd hive/services/hiveui/frontend && pnpm fix # Biome lint/format fix -cd hive/services/hiveui/frontend && pnpm build # Build + typecheck -``` - -Frontend stack: React 19, TanStack Router/Query, Tailwind CSS v4, Biome (lint/format), Vite, pnpm. See `.claude/rules/frontend-standards.md` for coding standards. - -### Dev Environment - -```bash -scripts/dev-setup.sh # One-time setup: creates directories, generates config/certs -scripts/start-dev.sh # Start all services (NATS → Predastore → Viperblock → NBDkit → Gateway → Daemon → UI) -scripts/stop-dev.sh # Stop all services -``` - -Data directory: `~/hive/` (logs in `~/hive/logs/`, config in `~/hive/config/`) - -## Development Process - -All non-trivial work (features, bug fixes, improvements) follows a plan-first, document-as-you-go process. Plans are committed to git so they are visible to the whole team, reviewable in PRs, and serve as permanent documentation. - -### When to write a plan - -- **Required**: New features, multi-file changes, architectural changes, performance work, non-obvious bug fixes -- **Not required**: Typo fixes, single-line bug fixes, config tweaks, small refactors contained to one function - -### Plan location - -Plans live in `docs/development/` under the appropriate category: - -``` -docs/development/ -├── bugs/ # Bug fixes -├── feature/ # New features -└── improvements/ # Performance, refactoring, tech debt -``` - -File naming: lowercase kebab-case describing the work, e.g. `nbd-performance.md`, `attach-volume.md`, `instance-state.md`. - -### Plan lifecycle - -#### 1. Planning phase - -When entering plan mode for non-trivial work, **create the plan document first** and write it to the appropriate `docs/development/{category}/` path. The plan must include: - -- **Summary** — What and why, in 1-3 sentences -- **Context / Problem Statement** — Current behavior, what's wrong or missing -- **Proposed Changes** — What will change, which files, key design decisions -- **Files to Modify** — List of files with brief description of changes -- **Testing** — How the changes will be verified - -The plan document is committed to git before implementation begins. This makes the plan reviewable and visible to the team. - -#### 2. Implementation phase - -During implementation, **update the plan document as you go**: - -- Mark completed steps (use `[x]` checkboxes or note "Done" inline) -- Record findings, corrections, or deviations from the original plan -- Add code references (file paths, line numbers, struct/function names) for what was actually implemented -- Note any follow-up work discovered during implementation - -#### 3. Completion - -When development is complete, update the document to serve as **permanent reference documentation**: - -- Add a status line near the top: `**Status: Complete**` (or `**Status: In Progress**`, `**Status: Planned**`) -- Replace future-tense plan language with past-tense description of what was done -- Add a **"Files Modified"** summary table -- Add a **"Future Work"** section if there are known follow-ups -- Keep the original context (benchmarks, research, root cause analysis) — this is valuable reference material -- The document should read as a complete technical reference, not just a plan - -#### Example status markers - -```markdown -**Status: Planned** — Awaiting review/approval before implementation -**Status: In Progress** — Implementation underway -**Status: Complete** — All changes implemented and tests passing -``` - -### Git history as context - -When starting work on a feature or investigating an issue, review the last 10-20 git commits (`git log --oneline -20`) to understand the current development context. Recent commits contain valuable context about in-progress features, architectural decisions, and related changes. - -### Existing examples - -- `docs/development/improvements/nbd-performance.md` — Complete improvement with benchmarks, root cause analysis, implementation details, and future work -- `docs/development/feature/attach-volume.md` — Complete feature with request flow, files changed, and design decisions -- `docs/development/bugs/instance-state.md` — Bug fix with problem statement, proposed architecture, and state transitions - -## Project Standards - -- Use `log/slog` instead of `log`. Use appropriate log level, eg `slog.Debug` -- All new features must have comprehensive unit tests -- For returning AWS errors, use `awserrors` package instead of manually typed strings - -**Preflight Policy:** -- Run `make preflight` before pushing any major changes — it runs the same checks as GitHub Actions (gofmt, go vet, gosec, staticcheck, govulncheck, and all unit tests) -- All developers must install the pre-push hook to enforce this automatically: - -```bash -cat > .git/hooks/pre-push << 'EOF' -#!/bin/sh -make preflight -make test -EOF -chmod +x .git/hooks/pre-push -``` - -**Testing Policy:** -- **All unit tests MUST pass** before committing changes -- **No exceptions** - failing tests block commits -- Tests must complete without errors or panics - -## Architecture - -Read `DESIGN.md` to understand the full architecture. - -### Message-Driven Architecture - -``` -AWS SDK (custom endpoint) → AWS Gateway (port 9999) → NATS → Specialized Daemons → Response -``` - -- **AWS Gateway** (`hive/services/awsgw/`): TLS endpoint, SigV4 auth, routes to service handlers via NATS -- **Daemons** (`hive/daemon/`): Subscribe to NATS topics, process requests, manage QEMU/KVM VMs -- **NATS Topics**: `ec2.*`, `ebs.*`, `s3.*`, `vpc.*` — queue groups (`hive-workers`) for load balancing, no queue group for fan-out (e.g., DescribeInstances) -- **Storage**: Viperblock for EBS volumes (`ebs.mount` topic), Predastore for S3/AMI/key storage - -### Go Workspace - -Uses `go.work` with local module replacements — all repos must be cloned to the same parent directory: -``` -mulga/ -├── hive/ # This repo -├── predastore/ # S3-compatible storage -└── viperblock/ # Block storage -``` - -### Testing with AWS CLI - -```bash -AWS_PROFILE=hive aws ec2 describe-instances -``` diff --git a/.claude/rules/frontend-standards.md b/.claude/rules/frontend-standards.md deleted file mode 100644 index ee0158541..000000000 --- a/.claude/rules/frontend-standards.md +++ /dev/null @@ -1,90 +0,0 @@ -# Quick Reference - -Most formatting and common issues are automatically fixed by Biome. Run `pnpm fix` before committing to ensure compliance and run `pnpm build` for typechecking and route tree generation. - -## Core Principles - -Write code that is **accessible, performant, type-safe, and maintainable**. Focus on clarity and explicit intent over brevity. - -### Type Safety & Explicitness - -- Use explicit types for function parameters and return values when they enhance clarity -- Prefer `unknown` over `any` when the type is genuinely unknown -- Use const assertions (`as const`) for immutable values and literal types -- Leverage TypeScript's type narrowing instead of type assertions -- Use meaningful variable names instead of magic numbers - extract constants with descriptive names - -### Modern JavaScript/TypeScript - -- Use arrow functions for callbacks and short functions -- Prefer `for...of` loops over `.forEach()` and indexed `for` loops -- Use optional chaining (`?.`) and nullish coalescing (`??`) for safer property access -- Prefer template literals over string concatenation -- Use destructuring for object and array assignments -- Use `const` by default, `let` only when reassignment is needed, never `var` -- Use interfaces for objects, otherwise use type aliases -- Prefer using function declarations over arrow functions for named functions - -### Async & Promises - -- Always `await` promises in async functions - don't forget to use the return value -- Use `async/await` syntax instead of promise chains for better readability -- Handle errors appropriately in async code with try-catch blocks -- Don't use async functions as Promise executors - -### React & JSX - -- Use function components over class components -- Call hooks at the top level only, never conditionally -- Specify all dependencies in hook dependency arrays correctly -- Use the `key` prop for elements in iterables (prefer unique IDs over array indices) -- Nest children between opening and closing tags instead of passing as props -- Don't define components inside other components -- Use semantic HTML and ARIA attributes for accessibility: - - Provide meaningful alt text for images - - Use proper heading hierarchy - - Add labels for form inputs - - Include keyboard event handlers alongside mouse events - - Use semantic elements (` -} -``` - -**Correct (reads on demand, no subscription):** - -```tsx -function ShareButton({ chatId }: { chatId: string }) { - const handleShare = () => { - const params = new URLSearchParams(window.location.search) - const ref = params.get('ref') - shareChat(chatId, { ref }) - } - - return -} -``` diff --git a/.claude/skills/react-best-practices/rules/rerender-dependencies.md b/.claude/skills/react-best-practices/rules/rerender-dependencies.md deleted file mode 100644 index 47a4d9268..000000000 --- a/.claude/skills/react-best-practices/rules/rerender-dependencies.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Narrow Effect Dependencies -impact: LOW -impactDescription: minimizes effect re-runs -tags: rerender, useEffect, dependencies, optimization ---- - -## Narrow Effect Dependencies - -Specify primitive dependencies instead of objects to minimize effect re-runs. - -**Incorrect (re-runs on any user field change):** - -```tsx -useEffect(() => { - console.log(user.id) -}, [user]) -``` - -**Correct (re-runs only when id changes):** - -```tsx -useEffect(() => { - console.log(user.id) -}, [user.id]) -``` - -**For derived state, compute outside effect:** - -```tsx -// Incorrect: runs on width=767, 766, 765... -useEffect(() => { - if (width < 768) { - enableMobileMode() - } -}, [width]) - -// Correct: runs only on boolean transition -const isMobile = width < 768 -useEffect(() => { - if (isMobile) { - enableMobileMode() - } -}, [isMobile]) -``` diff --git a/.claude/skills/react-best-practices/rules/rerender-derived-state-no-effect.md b/.claude/skills/react-best-practices/rules/rerender-derived-state-no-effect.md deleted file mode 100644 index 3d9fe4050..000000000 --- a/.claude/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Calculate Derived State During Rendering -impact: MEDIUM -impactDescription: avoids redundant renders and state drift -tags: rerender, derived-state, useEffect, state ---- - -## Calculate Derived State During Rendering - -If a value can be computed from current props/state, do not store it in state or update it in an effect. Derive it during render to avoid extra renders and state drift. Do not set state in effects solely in response to prop changes; prefer derived values or keyed resets instead. - -**Incorrect (redundant state and effect):** - -```tsx -function Form() { - const [firstName, setFirstName] = useState('First') - const [lastName, setLastName] = useState('Last') - const [fullName, setFullName] = useState('') - - useEffect(() => { - setFullName(firstName + ' ' + lastName) - }, [firstName, lastName]) - - return

{fullName}

-} -``` - -**Correct (derive during render):** - -```tsx -function Form() { - const [firstName, setFirstName] = useState('First') - const [lastName, setLastName] = useState('Last') - const fullName = firstName + ' ' + lastName - - return

{fullName}

-} -``` - -References: [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect) diff --git a/.claude/skills/react-best-practices/rules/rerender-derived-state.md b/.claude/skills/react-best-practices/rules/rerender-derived-state.md deleted file mode 100644 index e5c899f6c..000000000 --- a/.claude/skills/react-best-practices/rules/rerender-derived-state.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Subscribe to Derived State -impact: MEDIUM -impactDescription: reduces re-render frequency -tags: rerender, derived-state, media-query, optimization ---- - -## Subscribe to Derived State - -Subscribe to derived boolean state instead of continuous values to reduce re-render frequency. - -**Incorrect (re-renders on every pixel change):** - -```tsx -function Sidebar() { - const width = useWindowWidth() // updates continuously - const isMobile = width < 768 - return