Skip to main content

Contribution Guide

This page covers everything you need to know to submit high-quality contributions to AuroraSOC — from coding conventions to the pull request workflow, plus step-by-step guides for the most common extension tasks.


Branching Strategy

AuroraSOC uses a simple feature-branch workflow:

  1. Create a branch from main:
    git checkout -b feature/your-feature-name
  2. Make your changes with clear, atomic commits.
  3. Push and open a Pull Request against main.
  4. Address review feedback until approved.
  5. Squash-merge into main.

Branch Naming

PrefixUse CaseExample
feature/New functionalityfeature/add-dns-tools
fix/Bug fixesfix/circuit-breaker-timeout
docs/Documentation onlydocs/update-agent-reference
refactor/Code restructuringrefactor/memory-stores
test/Test additions/fixestest/add-playbook-tests

Coding Standards

Python (Backend)

AuroraSOC uses ruff for linting and formatting, and mypy for type checking. The configuration lives in pyproject.toml.

Key rules:

RuleDetail
TargetPython 3.12+
Line length100 characters
Formatterruff format
Linter rulesE, F, W, I (imports), N (naming), UP (pyupgrade), ANN (annotations), B (bugbear), A (builtins), SIM (simplify)
Type checkingmypy with --ignore-missing-imports
AsyncAll I/O must be async (async def, await)
ImportsSorted by ruff (isort compatible)

Before committing:

make format     # Auto-format code
make lint # Check for issues
make type-check # Verify type annotations

Style examples:

# ✅ Good — typed, async, descriptive
async def get_alert_by_id(session: AsyncSession, alert_id: str) -> Alert | None:
result = await session.execute(select(Alert).where(Alert.id == alert_id))
return result.scalar_one_or_none()

# ❌ Bad — untyped, sync, unclear
def get_alert(s, id):
return s.query(Alert).filter_by(id=id).first()

Rust (Core Engine)

make rust-clippy  # Lint with clippy (warnings are errors)
make rust-test # Run tests

All Rust code must pass clippy -- -D warnings with zero warnings.

TypeScript (Dashboard)

make dashboard-lint  # ESLint + TypeScript checks

Follow the existing patterns in dashboard/src/ — React Server Components by default, client components only when needed.


Testing Requirements

Every pull request must include tests for new or changed functionality.

Python Tests

  • Tests live in tests/ (flat structure, one file per module)
  • Use pytest with pytest-asyncio for async tests
  • Name files test_<module>.py and functions test_<behavior>()

Writing a test:

# tests/test_my_feature.py
import pytest
from aurorasoc.my_module import my_function


@pytest.mark.asyncio
async def test_my_function_returns_expected_value():
result = await my_function(input_data)
assert result == expected_output


@pytest.mark.asyncio
async def test_my_function_raises_on_invalid_input():
with pytest.raises(ValueError, match="invalid"):
await my_function(bad_data)

Shared fixtures go in tests/conftest.py (async database sessions, mock Redis clients, etc.).

Running tests:

make test           # All tests
make test-cov # With coverage
python -m pytest tests/test_my_feature.py -v # Single file
python -m pytest tests/test_my_feature.py::test_specific -v # Single test

Rust Tests

make rust-test

Rust tests live alongside the source code in #[cfg(test)] modules.

Minimum Coverage

Aim for meaningful tests that cover the happy path, error paths, and edge cases. Coverage is measured with make test-cov — keep the overall coverage from decreasing.


Pull Request Workflow

Before Opening a PR

Run the full check suite:

make check

This runs: linttype-checktestrust-clippyrust-testdashboard-lint.

All checks must pass before opening a PR.

PR Description Template

When opening a PR, include:

## What
Brief description of the change.

## Why
Link to the issue or explain the motivation.

## How
Key technical decisions and approach taken.

## Testing
How was this tested? What tests were added?

## Checklist
- [ ] `make check` passes
- [ ] Tests added for new functionality
- [ ] Documentation updated (if applicable)
- [ ] No new warnings introduced

Review Process

  1. At least one maintainer review is required.
  2. All CI checks must be green.
  3. Reviewers may request changes — address each comment.
  4. Once approved, the PR will be squash-merged.

Common Contribution Tasks

Adding a New AI Agent

This is the most common extension task. Follow these 8 steps:

1. Define the agent spec in aurorasoc/agents/factory.py:

# Add to the AGENT_SPECS dict
"my_new_agent": AgentSpec(
role="My New Agent",
instructions=MY_NEW_AGENT_PROMPT,
memory_template="ANALYST", # Choose from: ANALYST, HUNTER, RESPONDER, INTEL, ORCHESTRATOR, LIGHTWEIGHT
exclude_tools=[], # Tools to deny (e.g., ["block_ip"] for read-only agents)
),

2. Write the system prompt in aurorasoc/agents/prompts.py:

MY_NEW_AGENT_PROMPT = """You are the My New Agent for AuroraSOC.

## Primary Mission
[Describe what this agent does]

## Capabilities
- [Capability 1]
- [Capability 2]

## Investigation Methodology
1. [Step 1]
2. [Step 2]

## Output Requirements
Always structure your findings as:
- **Finding**: What was discovered
- **Severity**: Critical/High/Medium/Low
- **Evidence**: Supporting data
- **Recommendation**: Suggested action
"""

3. Assign MCP tool bindings in aurorasoc/agents/mcp_agent_loader.py:

# Add to AGENT_MCP_BINDINGS dict
"my_new_agent": ["siem", "threat_intel"], # List the MCP domains this agent needs

4. Create the agent directory:

mkdir -p aurorasoc/agents/my_new_agent
touch aurorasoc/agents/my_new_agent/__init__.py

5. Create the server file in aurorasoc/agents/my_new_agent/server.py:

from aurorasoc.agents.generic_server import deploy_agent

if __name__ == "__main__":
deploy_agent("my_new_agent", port=9017) # Next available port

6. Register with the Orchestrator — add the agent name to SPECIALIST_NAMES in aurorasoc/agents/orchestrator/server.py.

7. Add tests in tests/test_my_new_agent.py.

8. Update documentation — add the agent to docs/docs/contributor/ai-agents.md and docs/docs/developer/agents/.

Adding a New MCP Tool Domain

1. Create the tool directory:

mkdir -p aurorasoc/tools/my_domain
touch aurorasoc/tools/my_domain/__init__.py

2. Implement tools following the base class pattern in aurorasoc/tools/base.py.

3. Register the domain in aurorasoc/tools/mcp_domain_registry.py with the next available port (8116+).

4. Bind agents to the new domain in aurorasoc/agents/mcp_agent_loader.py — add the domain name to the relevant agent entries in AGENT_MCP_BINDINGS.

5. Add tests for the new tools.

Adding a New API Endpoint

1. Add the route in aurorasoc/api/main.py:

@app.get("/api/v1/my-endpoint", tags=["my-feature"])
async def my_endpoint(
current_user: dict = Depends(require_permissions("my_feature:read")),
session: AsyncSession = Depends(get_db),
):
# Implementation
return {"data": result}

2. Add request/response models in aurorasoc/models/domain.py if needed.

3. Add the required permission to the appropriate roles in aurorasoc/core/auth.py.

4. Write tests covering authentication, authorization, success, and error cases.

Adding a Database Model

1. Define the model in aurorasoc/core/models.py:

class MyModel(Base):
__tablename__ = "my_models"

id = Column(String, primary_key=True, default=lambda: str(uuid4()))
name = Column(String, nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())

2. Generate a migration:

make migrate-new MSG="add my_models table"

3. Review the auto-generated migration in alembic/versions/.

4. Apply the migration:

make migrate

Documentation Contributions

The documentation site uses Docusaurus with Mermaid diagram support.

Running Docs Locally

cd docs
npm install # First time only
npm run start # Starts on http://localhost:3000

Writing Docs

  • All docs are Markdown files in docs/docs/.
  • Use Mermaid code blocks for diagrams (they render automatically).
  • Every page needs YAML frontmatter:
---
id: my-page
title: My Page Title
sidebar_label: Short Label
sidebar_position: 1
description: One-line description for SEO.
---
  • After adding a new page, register it in docs/sidebars.ts.

Internationalisation

AuroraSOC docs support English and Arabic. English is the primary language — Arabic translations live in docs/i18n/ar/.


Commit Message Convention

Use clear, imperative-mood commit messages:

feat: add DNS resolution tools to network domain
fix: prevent circuit breaker from opening on timeout
docs: update agent reference with new CPS agent
test: add regression test for playbook rollback
refactor: extract memory store interface
PrefixWhen
feat:New feature
fix:Bug fix
docs:Documentation
test:Tests
refactor:Code restructuring
chore:Build/CI/config changes

Getting Help


Summary

StepCommand
Format codemake format
Lintmake lint
Type checkmake type-check
Run testsmake test
Run everythingmake check
Build Rustmake rust-build
Build dashboardmake dashboard-build
Apply migrationsmake migrate

Thank you for contributing to AuroraSOC. Every contribution — whether it's a typo fix, a new agent, or a documentation improvement — makes the project better.