Contributing to Charon

Thank you for your interest in contributing to CaddyProxyManager+! This document provides guidelines and instructions for contributing to the project.

Table of Contents

Code of Conduct

This project follows a Code of Conduct that all contributors are expected to adhere to:

Getting Started

-### Prerequisites

Fork and Clone

  1. Fork the repository on GitHub
  2. Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/charon.git
cd charon
  1. Add the upstream remote:
git remote add upstream https://github.com/Wikid82/charon.git

Set Up Development Environment

Backend:

cd backend
go mod download
go run ./cmd/seed/main.go  # Seed test data
go run ./cmd/api/main.go   # Start backend

Frontend:

cd frontend
npm install
npm run dev  # Start frontend dev server

Development Workflow

Branching Strategy

Creating a Feature Branch

Always branch from development:

git checkout development
git pull upstream development
git checkout -b feature/your-feature-name

Commit Message Guidelines

Follow the Conventional Commits specification:

<type>(<scope>): <subject>

<body>

<footer>

Types:

Examples:

feat(proxy-hosts): add SSL certificate upload

- Implement certificate upload endpoint
- Add UI for certificate management
- Update database schema

Closes #123
fix(import): resolve conflict detection bug

When importing Caddyfiles with multiple domains, conflicts
were not being detected properly.

Fixes #456

Keeping Your Fork Updated

git checkout development
git fetch upstream
git merge upstream/development
git push origin development

Coding Standards

Go Backend

Example:

// GetProxyHost retrieves a proxy host by UUID.
// Returns an error if the host is not found.
func GetProxyHost(uuid string) (*models.ProxyHost, error) {
    var host models.ProxyHost
    if err := db.First(&host, "uuid = ?", uuid).Error; err != nil {
        return nil, fmt.Errorf("proxy host not found: %w", err)
    }
    return &host, nil
}

TypeScript Frontend

Example:

interface ProxyHostFormProps {
  host?: ProxyHost
  onSubmit: (data: ProxyHostData) => Promise<void>
  onCancel: () => void
}

export function ProxyHostForm({ host, onSubmit, onCancel }: ProxyHostFormProps) {
  const [domain, setDomain] = useState(host?.domain ?? '')
  // ... component logic
}

CSS/Styling

Testing Guidelines

Backend Tests

Write tests for all new functionality:

func TestGetProxyHost(t *testing.T) {
    // Setup
    db := setupTestDB(t)
    host := createTestHost(db)

    // Execute
    result, err := GetProxyHost(host.UUID)

    // Assert
    assert.NoError(t, err)
    assert.Equal(t, host.Domain, result.Domain)
}

Run tests:

go test ./... -v
go test -cover ./...

Frontend Tests

Write component and hook tests using Vitest and React Testing Library:

describe('ProxyHostForm', () => {
  it('renders create form with empty fields', async () => {
    render(
      <ProxyHostForm onSubmit={vi.fn()} onCancel={vi.fn()} />
    )

    await waitFor(() => {
      expect(screen.getByText('Add Proxy Host')).toBeInTheDocument()
    })
  })
})

Run tests:

npm test              # Watch mode
npm run test:coverage # Coverage report

CrowdSec Frontend Test Coverage

The CrowdSec integration has comprehensive frontend test coverage (100%) across all modules:

See QA Coverage Report for details.

Test Coverage

Adding New Skills

Charon uses Agent Skills for AI-discoverable development tasks. Skills are standardized, self-documenting task definitions that can be executed by humans and AI assistants.

What is a Skill?

A skill is a combination of:

When to Create a Skill

Create a new skill when you have a:

Examples: Running tests, building artifacts, security scans, database operations, deployment tasks

Skill Creation Process

1. Plan Your Skill

Before creating, define:

2. Create Directory Structure

# Create skill directory
mkdir -p .github/skills/{skill-name}-scripts

# Skill files will be:
# .github/skills/{skill-name}.SKILL.md         # Documentation
# .github/skills/{skill-name}-scripts/run.sh    # Execution script

3. Write the SKILL.md File

Use the template structure:

---
# agentskills.io specification v1.0
name: "skill-name"
version: "1.0.0"
description: "Brief description (max 120 chars)"
author: "Charon Project"
license: "MIT"
tags:
  - "tag1"
  - "tag2"
compatibility:
  os:
    - "linux"
    - "darwin"
  shells:
    - "bash"
requirements:
  - name: "tool"
    version: ">=1.0"
    optional: false
metadata:
  category: "category-name"
  execution_time: "short|medium|long"
  risk_level: "low|medium|high"
  ci_cd_safe: true|false
---

# Skill Name

## Overview

Brief description of what this skill does.

## Prerequisites

- List required tools
- List required permissions
- List environment setup

## Usage

```bash
.github/skills/scripts/skill-runner.sh skill-name

Examples

Example 1: Basic Usage

# Description
command example

Error Handling

Related Skills


Last Updated: YYYY-MM-DD Maintained by: Charon Project Source: Original implementation or script path


#### 4. Create the Execution Script

Create `.github/skills/{skill-name}-scripts/run.sh`:

```bash
#!/usr/bin/env bash
set -euo pipefail

# Source helper scripts
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILLS_SCRIPTS_DIR="$(cd "${SCRIPT_DIR}/../scripts" && pwd)"

source "${SKILLS_SCRIPTS_DIR}/_logging_helpers.sh"
source "${SKILLS_SCRIPTS_DIR}/_error_handling_helpers.sh"
source "${SKILLS_SCRIPTS_DIR}/_environment_helpers.sh"

PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"

# Validate environment
log_step "ENVIRONMENT" "Validating prerequisites"
check_command_exists "required-tool" "Please install required-tool"

# Execute skill logic
log_step "EXECUTION" "Running skill"
cd "${PROJECT_ROOT}"

# Your skill implementation here
if ! your-command; then
    error_exit "Skill execution failed"
fi

log_success "Skill completed successfully"

Make it executable:

chmod +x .github/skills/{skill-name}-scripts/run.sh

5. Validate the Skill

Run the validation tool:

# Validate single skill
python3 .github/skills/scripts/validate-skills.py --single .github/skills/{skill-name}.SKILL.md

# Validate all skills
python3 .github/skills/scripts/validate-skills.py

Fix any validation errors before proceeding.

6. Test the Skill

Test execution:

# Direct execution
.github/skills/scripts/skill-runner.sh {skill-name}

# Verify output
# Check exit codes
# Confirm expected behavior

7. Add VS Code Task (Optional)

If the skill should be available in VS Code's task menu, add to .vscode/tasks.json:

{
    "label": "Category: Skill Name",
    "type": "shell",
    "command": ".github/skills/scripts/skill-runner.sh skill-name",
    "group": "test"
}

8. Update Documentation

Add your skill to .github/skills/README.md:

| [skill-name](./skill-name.SKILL.md) | category | Description | ✅ Active |

Validation Requirements

All skills must pass validation:

Best Practices

Documentation:

Scripts:

Testing:

Metadata:

Helper Scripts Reference

Charon provides helper scripts for common operations:

Logging (_logging_helpers.sh):

Error Handling (_error_handling_helpers.sh):

Environment (_environment_helpers.sh):

Resources

Pull Request Process

Before Submitting

  1. Ensure tests pass:
# Backend
go test ./...

# Frontend
npm test -- --run
  1. Check code quality:
# Go formatting
go fmt ./...

# Frontend linting
npm run lint
  1. Update documentation if needed
  2. Add tests for new functionality
  3. Rebase on latest development branch

Submitting a Pull Request

  1. Push your branch to your fork:
git push origin feature/your-feature-name
  1. Open a Pull Request on GitHub
  2. Fill out the PR template completely
  3. Link related issues using "Closes #123" or "Fixes #456"
  4. Request review from maintainers

PR Template

## Description
Brief description of changes

## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Testing
- [ ] Unit tests added/updated
- [ ] Manual testing performed
- [ ] All tests passing

## Screenshots (if applicable)
Add screenshots of UI changes

## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review performed
- [ ] Comments added for complex code
- [ ] Documentation updated
- [ ] No new warnings generated

Review Process

Issue Guidelines

Reporting Bugs

Use the bug report template and include:

Feature Requests

Use the feature request template and include:

Issue Labels

Documentation

Code Documentation

Project Documentation

When adding features, update:

Recognition

Contributors will be recognized in:

Questions?

License

By contributing, you agree that your contributions will be licensed under the project's MIT License.


Thank you for contributing to CaddyProxyManager+! 🎉