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
Before Feature Development – Locate similar features to mirror naming, error handling, and data flow
Before Bug Fixes – Trace the full execution path (handlers, services, models, DB access) before patching
Before Refactoring – Map dependencies and side effects to avoid regressions
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 externallydomain/- Unified data models (all GORM models listed indomain/tables.go)adminapi/- New management API routes (v9 refactor)radiusd/- RADIUS protocol core implementationapp/- 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:
// 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.goCisco (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):
CGO_ENABLED=0 go run main.go -c toughradius.ymlProduction Build (Supports PostgreSQL & SQLite, static compilation):
make build # Output to ./release/toughradiusFrontend Development:
cd web
npm install
npm run dev # Development server with hot reload
npm run build # Production build, output to dist/Database Initialization
./toughradius -initdb -c toughradius.yml # Drop and recreate all tablesProduction environment uses MigrateDB(false) for automatic migration (configured in main.go).
Testing Standards
RADIUS protocol tests:
internal/radiusd/*_test.goBenchmark tests:
cmd/benchmark/bmtest.go(standalone tool)Frontend tests: Playwright in
web/
Run tests:
go test ./... # All unit tests
go test -bench=. ./internal/radiusd/ # Benchmark testsCommon Patterns and Conventions
Code Documentation Standards
All exported APIs MUST have comprehensive comments:
// 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":
// Huawei devices expect bandwidth in Kbps, but our plan stores it in Mbps
// Convert using 1024 (binary) not 1000 (decimal) for compatibility
return baseBandwidth * 1024Vendor-specific code must reference protocol specifications:
// 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 specificationError Handling
RADIUS authentication errors use custom AuthError type with metrics tags:
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():
// 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:
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:
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():
// 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.goGORM - ORM, automatic migration controlled by
domain.Tableslistlayeh.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
Last updated
Was this helpful?