Thanks for contributing to the AetherCode Execution Engine. This project executes untrusted user code at scale, so the bar for correctness and security is high. Please read this before opening a PR.
- Go 1.25+
- Docker + Docker Compose (for the full dev stack)
- Optionally golangci-lint (v2.12.2 — the version CI pins; config in
.golangci.yml) if you don't want to lean on CI
For bug fixes and small improvements, go ahead and open a PR — no prior discussion needed.
For new features, API changes, or anything that touches the sandbox boundary, auth, or the queue, open an issue first. Describing the problem and your proposed approach before writing code prevents wasted effort and helps maintainers give early feedback on the design.
git clone https://github.com/stjosephsplacements/AetherCode-Execution-Engine.git
cd AetherCode-Execution-Engine
make help # list all targets
make build # build the engine binary
make test # run unit tests
make lint # run golangci-lintThe fastest way to run everything (engine + PostgreSQL + Redis + go-judge sandbox) is Docker Compose:
make up # docker compose up --build
curl http://127.0.0.1:5100/api/v1/health
make e2e # run the end-to-end suite against the stack
make down # stop the stackThe go-judge container runs with
privileged: truein the dev stack because its sandbox needs cgroups + namespaces. That is fine for a machine you control; use the systemd deployment with explicit limits in production.
# Branch from development (the default branch)
git checkout development
git pull
git checkout -b feat/my-change
# Edit, then verify the full local gate matches CI:
make build
make test
make lint
make fmt # only if you want gofmt applied for youRun the same checks CI runs before pushing. CI fails on any of:
go build, go vet, gofmt -s, go test -race ./..., or golangci-lint run.
This project uses a four-branch, environment-mapped model. All work starts on
development (the default branch) and moves one branch at a time toward
production. Every promotion is driven by the CI automation described below —
no manual cherry-picks.
development → testing → staging → production
(default)
| Branch | Role |
|---|---|
development |
Day-to-day feature work. All PRs target this branch. |
testing |
Integrated, buildable candidate. Auto-promoted from development when CI is green. |
staging |
Pre-release; mirrors the staging environment. Auto-promoted from testing when CI is green. |
production |
What is served. Promoted from staging — requires one approving review before merge. |
- No direct pushes to any of the four branches — everything goes through a pull request.
- A PR merges only when the
testandlintCI checks are green. development → testing → stagingpromotions happen automatically: once CI is green ondevelopment, the CI workflow opens a PR intotesting, waits for its checks, and merges it. The same happens fortesting → staging.staging → productionis the only human gate: the CI workflow opens the PR automatically, but an org member must approve it before it can be merged. Organization admins have bypass access for emergency situations.- Topic branches (
feat/*,fix/*,security/*,ci/*,docs/*,chore/*,refactor/*) are also handled: once CI is green on the topic branch, a PR intodevelopmentis opened and merged automatically. - Merge policy: all promotions use a standard merge commit. Squash and rebase merges are disabled to keep a linear, auditable history across the pipeline.
If a regression reaches production, do not skip stages:
# Branch from production so the fix contains exactly what is live
git checkout production
git pull
git checkout -b fix/my-hotfix
# Fix, test, push
# Open a PR into production — an org admin can approve and merge it
# Back-port: open a PR from your fix branch into staging, then testing, then development
# (or let the promotion pipeline carry it forward once CI is green on production)Every environment's tests still run against the fix. The extra few minutes are worth it.
- gofmt-clean — run
gofmt -s -w .(ormake fmt) before committing. - errcheck matters. This engine has intentional fail-open paths (best-effort
logging, connection reuse, advisory-lock release). Those are marked with a
//nolint:errcheck // reasoncomment. A bare ignored error without a reason is a review blocker. - Keep the linters honest. The enabled set is in
.golangci.yml. Don't weaken it to silence a finding; fix the finding, or add a scoped, reasoned//nolint. - Follow the existing structure in
CLAUDE.md→ Code map.
- Unit tests must be hermetic. They run in CI with no external services. The
rate-limiter tests use an in-process
miniredis; follow that pattern if you need Redis in a test. - Never run real submissions in a test or in the sandbox from a test. Expected outputs live in the worker, not in the sandbox environment.
- Add tests for new behavior.
make e2eexercises the full pipeline but requires a running stack — it is not part of the hermetic unit suite.
Several invariants in CLAUDE.md exist to make "zero lost jobs" provable. If a
change touches them, call it out explicitly in the PR description:
- Insert before enqueue — the PG row exists before the Redis
XADD. - Subscribe before replay — SSE subscribes before reading the event log.
- Cancel-safe writes — DB/publish and
XAckusecontext.WithoutCancel. - CAS verdict writes —
UPDATE … WHERE status NOT IN ('completed','failed').
Use imperative, scoped messages: worker: deduplicate test-case output trims.
Keep the body focused; reference the invariant you touched if relevant.
A good PR description covers:
- What changed — one sentence summary.
- Why — the motivation (links to an issue if one exists).
- How it was tested — unit tests added,
make e2erun, manual steps. - Invariants touched — if any of the four design invariants above apply, say which one and why the change is still safe.
- Security/correctness reasoning — required for anything touching the sandbox boundary, auth, the queue, or rate limiting.
Other guidelines:
- Small, focused diffs. One concern per PR.
- CI must be green (build, vet, fmt, tests, lint) before requesting review.
- PRs into
developmentneed one approving review. The same rule applies at every stage through toproduction.