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:
- Create a branch from
main:git checkout -b feature/your-feature-name - Make your changes with clear, atomic commits.
- Push and open a Pull Request against
main. - Address review feedback until approved.
- Squash-merge into
main.
Branch Naming
| Prefix | Use Case | Example |
|---|---|---|
feature/ | New functionality | feature/add-dns-tools |
fix/ | Bug fixes | fix/circuit-breaker-timeout |
docs/ | Documentation only | docs/update-agent-reference |
refactor/ | Code restructuring | refactor/memory-stores |
test/ | Test additions/fixes | test/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:
| Rule | Detail |
|---|---|
| Target | Python 3.12+ |
| Line length | 100 characters |
| Formatter | ruff format |
| Linter rules | E, F, W, I (imports), N (naming), UP (pyupgrade), ANN (annotations), B (bugbear), A (builtins), SIM (simplify) |
| Type checking | mypy with --ignore-missing-imports |
| Async | All I/O must be async (async def, await) |
| Imports | Sorted 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>.pyand functionstest_<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: lint → type-check → test → rust-clippy → rust-test → dashboard-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
- At least one maintainer review is required.
- All CI checks must be green.
- Reviewers may request changes — address each comment.
- 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
| Prefix | When |
|---|---|
feat: | New feature |
fix: | Bug fix |
docs: | Documentation |
test: | Tests |
refactor: | Code restructuring |
chore: | Build/CI/config changes |
Getting Help
- GitHub Issues: Report bugs or request features.
- Code Questions: Read the System Architecture and AI Agents pages first — they explain the design patterns in depth.
- Stuck on Setup: See the Troubleshooting section in Getting Started.
Summary
| Step | Command |
|---|---|
| Format code | make format |
| Lint | make lint |
| Type check | make type-check |
| Run tests | make test |
| Run everything | make check |
| Build Rust | make rust-build |
| Build dashboard | make dashboard-build |
| Apply migrations | make 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.