# Coding Standards
## AtlasOS - Calypso Backup Appliance

**Version:** 1.0.0-alpha  
**Date:** 2025-01-XX  
**Status:** Active

---

## 1. Overview

This document defines the coding standards and best practices for the Calypso project. All code must adhere to these standards to ensure consistency, maintainability, and quality.

## 2. General Principles

### 2.1 Code Quality
- **Readability**: Code should be self-documenting and easy to understand
- **Maintainability**: Code should be easy to modify and extend
- **Consistency**: Follow consistent patterns across the codebase
- **Simplicity**: Prefer simple solutions over complex ones
- **DRY**: Don't Repeat Yourself - avoid code duplication

### 2.2 Code Review
- All code must be reviewed before merging
- Reviewers should check for adherence to these standards
- Address review comments before merging

### 2.3 Documentation
- Document complex logic and algorithms
- Keep comments up-to-date with code changes
- Write clear commit messages

---

## 3. Backend (Go) Standards

### 3.1 Code Formatting

#### 3.1.1 Use gofmt
- Always run `gofmt` before committing
- Use `goimports` for import organization
- Configure IDE to format on save

#### 3.1.2 Line Length
- Maximum line length: 100 characters
- Break long lines for readability

#### 3.1.3 Indentation
- Use tabs for indentation (not spaces)
- Tab width: 4 spaces equivalent

### 3.2 Naming Conventions

#### 3.2.1 Packages
```go
// Good: lowercase, single word, descriptive
package storage
package auth
package monitoring

// Bad: mixed case, abbreviations
package Storage
package Auth
package Mon
```

#### 3.2.2 Functions
```go
// Good: camelCase, descriptive
func createZFSPool(name string) error
func listNetworkInterfaces() ([]Interface, error)
func validateUserInput(input string) error

// Bad: unclear names, abbreviations
func create(name string) error
func list() ([]Interface, error)
func val(input string) error
```

#### 3.2.3 Variables
```go
// Good: camelCase, descriptive
var poolName string
var networkInterfaces []Interface
var isActive bool

// Bad: single letters, unclear
var n string
var ifs []Interface
var a bool
```

#### 3.2.4 Constants
```go
// Good: PascalCase for exported, camelCase for unexported
const DefaultPort = 8080
const maxRetries = 3

// Bad: inconsistent casing
const defaultPort = 8080
const MAX_RETRIES = 3
```

#### 3.2.5 Types and Structs
```go
// Good: PascalCase, descriptive
type ZFSPool struct {
    ID      string
    Name    string
    Status  string
}

// Bad: unclear names
type Pool struct {
    I string
    N string
    S string
}
```

### 3.3 File Organization

#### 3.3.1 File Structure
```go
// 1. Package declaration
package storage

// 2. Imports (standard, third-party, local)
import (
    "context"
    "fmt"
    
    "github.com/gin-gonic/gin"
    
    "github.com/atlasos/calypso/internal/common/database"
)

// 3. Constants
const (
    defaultTimeout = 30 * time.Second
)

// 4. Types
type Service struct {
    db *database.DB
}

// 5. Functions
func NewService(db *database.DB) *Service {
    return &Service{db: db}
}
```

#### 3.3.2 File Naming
- Use lowercase with underscores: `handler.go`, `service.go`
- Test files: `handler_test.go`
- One main type per file when possible

### 3.4 Error Handling

#### 3.4.1 Error Return
```go
// Good: always return error as last value
func createPool(name string) (*Pool, error) {
    if name == "" {
        return nil, fmt.Errorf("pool name cannot be empty")
    }
    // ...
}

// Bad: panic, no error return
func createPool(name string) *Pool {
    if name == "" {
        panic("pool name cannot be empty")
    }
}
```

#### 3.4.2 Error Wrapping
```go
// Good: wrap errors with context
if err != nil {
    return fmt.Errorf("failed to create pool %s: %w", name, err)
}

// Bad: lose error context
if err != nil {
    return err
}
```

#### 3.4.3 Error Messages
```go
// Good: clear, actionable error messages
return fmt.Errorf("pool '%s' already exists", name)
return fmt.Errorf("insufficient disk space: need %d bytes, have %d bytes", needed, available)

// Bad: unclear error messages
return fmt.Errorf("error")
return fmt.Errorf("failed")
```

### 3.5 Comments

#### 3.5.1 Package Comments
```go
// Package storage provides storage management functionality including
// ZFS pool and dataset operations, disk discovery, and storage repository management.
package storage
```

#### 3.5.2 Function Comments
```go
// CreateZFSPool creates a new ZFS pool with the specified configuration.
// It validates the pool name, checks disk availability, and creates the pool.
// Returns an error if the pool cannot be created.
func CreateZFSPool(ctx context.Context, name string, disks []string) error {
    // ...
}
```

#### 3.5.3 Inline Comments
```go
// Good: explain why, not what
// Retry up to 3 times to handle transient network errors
for i := 0; i < 3; i++ {
    // ...
}

// Bad: obvious comments
// Loop 3 times
for i := 0; i < 3; i++ {
    // ...
}
```

### 3.6 Testing

#### 3.6.1 Test File Naming
- Test files: `*_test.go`
- Test functions: `TestFunctionName`
- Benchmark functions: `BenchmarkFunctionName`

#### 3.6.2 Test Structure
```go
func TestCreateZFSPool(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        wantErr bool
    }{
        {
            name:    "valid pool name",
            input:   "tank",
            wantErr: false,
        },
        {
            name:    "empty pool name",
            input:   "",
            wantErr: true,
        },
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            err := createPool(tt.input)
            if (err != nil) != tt.wantErr {
                t.Errorf("createPool() error = %v, wantErr %v", err, tt.wantErr)
            }
        })
    }
}
```

### 3.7 Concurrency

#### 3.7.1 Context Usage
```go
// Good: always accept context as first parameter
func (s *Service) CreatePool(ctx context.Context, name string) error {
    // Use context for cancellation and timeout
    ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
    defer cancel()
    // ...
}

// Bad: no context
func (s *Service) CreatePool(name string) error {
    // ...
}
```

#### 3.7.2 Goroutines
```go
// Good: use context for cancellation
go func() {
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()
    // ...
}()

// Bad: no cancellation mechanism
go func() {
    // ...
}()
```

### 3.8 Database Operations

#### 3.8.1 Query Context
```go
// Good: use context for queries
rows, err := s.db.QueryContext(ctx, query, args...)

// Bad: no context
rows, err := s.db.Query(query, args...)
```

#### 3.8.2 Transactions
```go
// Good: use transactions for multiple operations
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
    return err
}
defer tx.Rollback()

// ... operations ...

if err := tx.Commit(); err != nil {
    return err
}
```

---

## 4. Frontend (TypeScript/React) Standards

### 4.1 Code Formatting

#### 4.1.1 Use Prettier
- Configure Prettier for consistent formatting
- Format on save enabled
- Maximum line length: 100 characters

#### 4.1.2 Indentation
- Use 2 spaces for indentation
- Consistent spacing in JSX

### 4.2 Naming Conventions

#### 4.2.1 Components
```typescript
// Good: PascalCase, descriptive
function StoragePage() { }
function CreatePoolModal() { }
function NetworkInterfaceCard() { }

// Bad: unclear names
function Page() { }
function Modal() { }
function Card() { }
```

#### 4.2.2 Functions
```typescript
// Good: camelCase, descriptive
function createZFSPool(name: string): Promise<ZFSPool> { }
function handleSubmit(event: React.FormEvent): void { }
function formatBytes(bytes: number): string { }

// Bad: unclear names
function create(name: string) { }
function handle(e: any) { }
function fmt(b: number) { }
```

#### 4.2.3 Variables
```typescript
// Good: camelCase, descriptive
const poolName = 'tank'
const networkInterfaces: NetworkInterface[] = []
const isActive = true

// Bad: unclear names
const n = 'tank'
const ifs: any[] = []
const a = true
```

#### 4.2.4 Constants
```typescript
// Good: UPPER_SNAKE_CASE for constants
const DEFAULT_PORT = 8080
const MAX_RETRIES = 3
const API_BASE_URL = '/api/v1'

// Bad: inconsistent casing
const defaultPort = 8080
const maxRetries = 3
```

#### 4.2.5 Types and Interfaces
```typescript
// Good: PascalCase, descriptive
interface ZFSPool {
  id: string
  name: string
  status: string
}

type PoolStatus = 'online' | 'offline' | 'degraded'

// Bad: unclear names
interface Pool {
  i: string
  n: string
  s: string
}
```

### 4.3 File Organization

#### 4.3.1 Component Structure
```typescript
// 1. Imports (React, third-party, local)
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { zfsApi } from '@/api/storage'

// 2. Types/Interfaces
interface Props {
  poolId: string
}

// 3. Component
export default function PoolDetail({ poolId }: Props) {
  // 4. Hooks
  const [isLoading, setIsLoading] = useState(false)
  
  // 5. Queries
  const { data: pool } = useQuery({
    queryKey: ['pool', poolId],
    queryFn: () => zfsApi.getPool(poolId),
  })
  
  // 6. Handlers
  const handleDelete = () => {
    // ...
  }
  
  // 7. Effects
  useEffect(() => {
    // ...
  }, [poolId])
  
  // 8. Render
  return (
    // JSX
  )
}
```

#### 4.3.2 File Naming
- Components: `PascalCase.tsx` (e.g., `StoragePage.tsx`)
- Utilities: `camelCase.ts` (e.g., `formatBytes.ts`)
- Types: `camelCase.ts` or `types.ts`
- Hooks: `useCamelCase.ts` (e.g., `useStorage.ts`)

### 4.4 TypeScript

#### 4.4.1 Type Safety
```typescript
// Good: explicit types
function createPool(name: string): Promise<ZFSPool> {
  // ...
}

// Bad: any types
function createPool(name: any): any {
  // ...
}
```

#### 4.4.2 Interface Definitions
```typescript
// Good: clear interface definitions
interface ZFSPool {
  id: string
  name: string
  status: 'online' | 'offline' | 'degraded'
  totalCapacityBytes: number
  usedCapacityBytes: number
}

// Bad: unclear or missing types
interface Pool {
  id: any
  name: any
  status: any
}
```

### 4.5 React Patterns

#### 4.5.1 Hooks
```typescript
// Good: custom hooks for reusable logic
function useZFSPool(poolId: string) {
  return useQuery({
    queryKey: ['pool', poolId],
    queryFn: () => zfsApi.getPool(poolId),
  })
}

// Usage
const { data: pool } = useZFSPool(poolId)
```

#### 4.5.2 Component Composition
```typescript
// Good: small, focused components
function PoolCard({ pool }: { pool: ZFSPool }) {
  return (
    <div>
      <PoolHeader pool={pool} />
      <PoolStats pool={pool} />
      <PoolActions pool={pool} />
    </div>
  )
}

// Bad: large, monolithic components
function PoolCard({ pool }: { pool: ZFSPool }) {
  // 500+ lines of JSX
}
```

#### 4.5.3 State Management
```typescript
// Good: use React Query for server state
const { data, isLoading } = useQuery({
  queryKey: ['pools'],
  queryFn: zfsApi.listPools,
})

// Good: use local state for UI state
const [isModalOpen, setIsModalOpen] = useState(false)

// Good: use Zustand for global UI state
const { user, setUser } = useAuthStore()
```

### 4.6 Error Handling

#### 4.6.1 Error Boundaries
```typescript
// Good: use error boundaries
function ErrorBoundary({ children }: { children: React.ReactNode }) {
  // ...
}

// Usage
<ErrorBoundary>
  <App />
</ErrorBoundary>
```

#### 4.6.2 Error Handling in Queries
```typescript
// Good: handle errors in queries
const { data, error, isLoading } = useQuery({
  queryKey: ['pools'],
  queryFn: zfsApi.listPools,
  onError: (error) => {
    console.error('Failed to load pools:', error)
    // Show user-friendly error message
  },
})
```

### 4.7 Styling

#### 4.7.1 TailwindCSS
```typescript
// Good: use Tailwind classes
<div className="flex items-center gap-4 p-6 bg-card-dark rounded-lg border border-border-dark">
  <h2 className="text-lg font-bold text-white">Storage Pools</h2>
</div>

// Bad: inline styles
<div style={{ display: 'flex', padding: '24px', backgroundColor: '#18232e' }}>
  <h2 style={{ fontSize: '18px', fontWeight: 'bold', color: 'white' }}>Storage Pools</h2>
</div>
```

#### 4.7.2 Class Organization
```typescript
// Good: logical grouping
className="flex items-center gap-4 p-6 bg-card-dark rounded-lg border border-border-dark hover:bg-border-dark transition-colors"

// Bad: random order
className="p-6 flex border rounded-lg items-center gap-4 bg-card-dark border-border-dark"
```

### 4.8 Testing

#### 4.8.1 Component Testing
```typescript
// Good: test component behavior
describe('StoragePage', () => {
  it('displays pools when loaded', () => {
    render(<StoragePage />)
    expect(screen.getByText('tank')).toBeInTheDocument()
  })
  
  it('shows loading state', () => {
    render(<StoragePage />)
    expect(screen.getByText('Loading...')).toBeInTheDocument()
  })
})
```

---

## 5. Git Commit Standards

### 5.1 Commit Message Format
```
<type>(<scope>): <subject>

<body>

<footer>
```

### 5.2 Commit Types
- **feat**: New feature
- **fix**: Bug fix
- **docs**: Documentation changes
- **style**: Code style changes (formatting, etc.)
- **refactor**: Code refactoring
- **test**: Test additions or changes
- **chore**: Build process or auxiliary tool changes

### 5.3 Commit Examples
```
feat(storage): add ZFS pool creation endpoint

Add POST /api/v1/storage/zfs/pools endpoint with validation
and error handling.

Closes #123

fix(shares): correct dataset_id field in create share

The frontend was sending dataset_name instead of dataset_id.
Updated to use UUID from dataset selection.

docs: update API documentation for snapshot endpoints

refactor(auth): simplify JWT token validation logic
```

### 5.4 Branch Naming
- **feature/**: New features (e.g., `feature/object-storage`)
- **fix/**: Bug fixes (e.g., `fix/share-creation-error`)
- **docs/**: Documentation (e.g., `docs/api-documentation`)
- **refactor/**: Refactoring (e.g., `refactor/storage-service`)

---

## 6. Code Review Guidelines

### 6.1 Review Checklist
- [ ] Code follows naming conventions
- [ ] Code is properly formatted
- [ ] Error handling is appropriate
- [ ] Tests are included for new features
- [ ] Documentation is updated
- [ ] No security vulnerabilities
- [ ] Performance considerations addressed
- [ ] No commented-out code
- [ ] No console.log statements (use proper logging)

### 6.2 Review Comments
- Be constructive and respectful
- Explain why, not just what
- Suggest improvements, not just point out issues
- Approve when code meets standards

---

## 7. Documentation Standards

### 7.1 Code Comments
- Document complex logic
- Explain "why" not "what"
- Keep comments up-to-date

### 7.2 API Documentation
- Document all public APIs
- Include parameter descriptions
- Include return value descriptions
- Include error conditions

### 7.3 README Files
- Keep README files updated
- Include setup instructions
- Include usage examples
- Include troubleshooting tips

---

## 8. Performance Standards

### 8.1 Backend
- Database queries should be optimized
- Use indexes appropriately
- Avoid N+1 query problems
- Use connection pooling

### 8.2 Frontend
- Minimize re-renders
- Use React.memo for expensive components
- Lazy load routes
- Optimize bundle size

---

## 9. Security Standards

### 9.1 Input Validation
- Validate all user inputs
- Sanitize inputs before use
- Use parameterized queries
- Escape output

### 9.2 Authentication
- Never store passwords in plaintext
- Use secure token storage
- Implement proper session management
- Handle token expiration

### 9.3 Authorization
- Check permissions on every request
- Use principle of least privilege
- Log security events
- Handle authorization errors properly

---

## 10. Tools and Configuration

### 10.1 Backend Tools
- **gofmt**: Code formatting
- **goimports**: Import organization
- **golint**: Linting
- **go vet**: Static analysis

### 10.2 Frontend Tools
- **Prettier**: Code formatting
- **ESLint**: Linting
- **TypeScript**: Type checking
- **Vite**: Build tool

---

## 11. Exceptions

### 11.1 When to Deviate
- Performance-critical code may require optimization
- Legacy code integration may require different patterns
- Third-party library constraints

### 11.2 Documenting Exceptions
- Document why standards are not followed
- Include comments explaining deviations
- Review exceptions during code review

---

## Document History

| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0.0-alpha | 2025-01-XX | Development Team | Initial coding standards document |

