# ToughRADIUS AI Coding Agent Instructions

## 🔍 Mandatory Requirements Before Development

**Never modify code blindly. Always gather context from the existing implementation, related tests, and documentation first.**

### When to Perform Context Retrieval

1. **Before Feature Development** – Locate similar features to mirror naming, error handling, and data flow
2. **Before Bug Fixes** – Trace the full execution path (handlers, services, models, DB access) before patching
3. **Before Refactoring** – Map dependencies and side effects to avoid regressions
4. **When Learning Conventions** – Study logging patterns, configuration helpers, and TDD expectations

### Recommended Search Techniques

```
# Feature exploration
semantic_search "vendor attribute parsing" in internal/radiusd/vendors
file_search "*/internal/adminapi/*routes*.go"

# Bug fixing
list_code_usages AuthenticateUser
grep_search "AuthError" --include internal/radiusd/**

# Refactoring
semantic_search "errgroup" in main.go
grep_search "app.GDB" --include internal/app/**
```

**Core Principle: Understand existing code → Follow project conventions → Maintain consistency**

***

## Project Overview

ToughRADIUS is an enterprise-grade RADIUS server developed in Go, supporting standard RADIUS protocols (RFC 2865/2866) and RadSec (RADIUS over TLS). The frontend uses React Admin framework for the management interface.

## Architecture Highlights

### Core Service Concurrency Model

`main.go` uses `errgroup` to start multiple independent services concurrently. If any service crashes, the entire application exits:

* **Web/Admin API** - Echo framework, port 1816 (`internal/webserver` + `internal/adminapi`)
* **RADIUS Auth** - Authentication service, UDP 1812 (`internal/radiusd`)
* **RADIUS Acct** - Accounting service, UDP 1813 (`internal/radiusd`)
* **RadSec** - TLS-encrypted RADIUS over TCP, port 2083 (`internal/radiusd`)

### Project Structure Pattern

Follows golang-standards/project-layout:

* `internal/` - Private code, cannot be imported externally
  * `domain/` - **Unified data models** (all GORM models listed in `domain/tables.go`)
  * `adminapi/` - New management API routes (v9 refactor)
  * `radiusd/` - RADIUS protocol core implementation
  * `app/` - Global application instance (database, config, scheduled tasks)
* `pkg/` - Reusable public libraries (utilities, encryption, Excel, etc.)
* `web/` - React Admin frontend (TypeScript + Vite)

### Database Access Pattern

**Always** obtain GORM instance through `app.GDB()`, do not inject DB connection directly:

```go
// Correct
user := &domain.RadiusUser{}
app.GDB().Where("username = ?", name).First(user)

// Wrong - Don't do this
type Service struct { DB *gorm.DB }
```

Supports PostgreSQL (default) and SQLite (pure Go, no CGO). Database migration is automatically handled by `app.MigrateDB()`.

### Vendor Extension Handling

RADIUS protocol supports multi-vendor features, distinguished by `VendorCode` field:

* Huawei (2011) - `internal/radiusd/vendors/huawei/`
* Mikrotik (14988) - See `auth_accept_config.go`
* Cisco (9) / Ikuai (10055) / ZTE (3902) / H3C (25506)

When adding new vendor support, define constants in `radius.go`, then add switch cases in `auth_accept_config.go` and related processing functions.

## Key Development Workflows

### Build and Run

**Local Development** (SQLite supported, CGO disabled):

```bash
CGO_ENABLED=0 go run main.go -c toughradius.yml
```

**Production Build** (Supports PostgreSQL & SQLite, static compilation):

```bash
make build  # Output to ./release/toughradius
```

**Frontend Development**:

```bash
cd web
npm install
npm run dev      # Development server with hot reload
npm run build    # Production build, output to dist/
```

### Database Initialization

```bash
./toughradius -initdb -c toughradius.yml  # Drop and recreate all tables
```

Production environment uses `MigrateDB(false)` for automatic migration (configured in main.go).

### Testing Standards

* RADIUS protocol tests: `internal/radiusd/*_test.go`
* Benchmark tests: `cmd/benchmark/bmtest.go` (standalone tool)
* Frontend tests: Playwright in `web/`

Run tests:

```bash
go test ./...                    # All unit tests
go test -bench=. ./internal/radiusd/  # Benchmark tests
```

## Common Patterns and Conventions

### Code Documentation Standards

**All exported APIs MUST have comprehensive comments:**

```go
// AuthenticateUser validates user credentials against the RADIUS database.
// It checks username/password, account expiration, and session limits.
//
// Parameters:
//   - username: User's login name (case-sensitive)
//   - password: Plain text password (will be hashed internally)
//   - nasIP: Network Access Server IP address for session tracking
//
// Returns:
//   - *domain.RadiusUser: User object if authentication succeeds
//   - error: AuthError with metrics tag if validation fails
//
// Common errors:
//   - MetricsRadiusRejectUserNotFound: Username doesn't exist
//   - MetricsRadiusRejectPasswordError: Password mismatch
func AuthenticateUser(username, password, nasIP string) (*domain.RadiusUser, error) {
    // Implementation
}
```

**Complex logic requires inline comments explaining the "why":**

```go
// Huawei devices expect bandwidth in Kbps, but our plan stores it in Mbps
// Convert using 1024 (binary) not 1000 (decimal) for compatibility
return baseBandwidth * 1024
```

**Vendor-specific code must reference protocol specifications:**

```go
// ParseHuaweiInputAverageRate extracts bandwidth limit from Huawei VSA attribute.
// Format: Type=11, Length=variable, Value=bandwidth_in_kbps
// See: internal/radiusd/vendors/huawei/README.md for full VSA specification
```

### Error Handling

RADIUS authentication errors use custom `AuthError` type with metrics tags:

```go
return NewAuthError(app.MetricsRadiusRejectExpire, "user expire")
```

These errors are automatically recorded to Prometheus metrics (`internal/app/metrics.go`).

### Configuration Reading

Access global config and settings via `app.GApp()`:

```go
// Read RADIUS config items
eapMethod := app.GApp().GetSettingsStringValue("radius", "EapMethod")
maxSessions := app.GApp().GetSettingsInt64Value("radius", "MaxSessions")
```

System configuration is stored in `sys_config` table, initialized with default values through `checkSettings()`.

### Concurrency Handling

RADIUS request processing uses ants goroutine pool to limit concurrency:

```go
radiusService.TaskPool.Submit(func() { /* Handle request */ })
```

Pool size is configured via environment variable `TOUGHRADIUS_RADIUS_POOL` (default 1024).

### Logging Standards

Use zap structured logging, **always** add namespace:

```go
zap.L().Error("update user failed",
    zap.Error(err),
    zap.String("namespace", "radius"))
```

### Admin API Route Registration

When adding new management APIs, create file in `internal/adminapi/` and register in `adminapi.go`'s `Init()`:

```go
// users.go
func registerUserRoutes() {
    // Route definitions
}

// adminapi.go
func Init() {
    registerUserRoutes()  // Add this line
}
```

## Key Dependencies and Integrations

* **Echo v4** - Web framework, middleware configured in `internal/webserver/server.go`
* **GORM** - ORM, automatic migration controlled by `domain.Tables` list
* **layeh.com/radius** - RADIUS protocol library, don't mix with other RADIUS packages
* **React Admin 5.0** - Frontend framework, REST data provider in `web/src/dataProvider.ts`


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.toughradius.net/.github/copilot-instructions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
