Guidance for AI coding agents working in this repository. Keep changes minimal, follow the patterns already in the codebase, and verify with the commands below before submitting.
- Name:
mega2(single Cargo package: libmega2_core+ binaries, seeCargo.toml). - Edition: Rust 2024.
- Purpose: Mono‑repo / Git hosting + service engine. Ports and extends
several subsystems originally from the Mega project (notably
callistoentities andjupiterstorage/migration). - Entry point:
src/main.rs→cli::parse(None). - Config: TOML loaded from
config/config.toml(override via--configflag orMEGA_CONFIGenv var). Loader lives insrc/config/loader.rs.
- Language: Rust 2024 (stable toolchain).
- CLI:
clapv4 (derive + builder), subcommands registered insrc/commands/mod.rs(builtin()/builtin_exec()). - Async runtime:
tokio(full features). - HTTP / API:
axum0.8 +tower-http, OpenAPI viautoipa+ Swagger UI. - Storage / DB:
sea-orm1.1 (Postgres + SQLite,runtime-tokio-rustls) andsea-orm-migration. Entities are insrc/callisto/. - Cache / queue:
redis(withconnection-manager). - Auth / policy:
cedar-policy(schema insrc/contract/policy/mega.cedarschema, policies insrc/contract/policy/mega_policies.cedar). - Crypto / TLS:
rustls,ring,openssl,ed25519-dalek,rsa,secp256k1,pgp. Vault‑style PKI/secret engine via thelibvaultcrate (crates.io0.3.0, featuresstorage_pg+crypto_adaptor_openssl) and the mega2 integration layer (src/contract/vault/). The RustyVault sources used to be vendored undersrc/vault/; that module was removed on 2026-08-21 (docs/plan/plan-20260820.md), so import library types fromlibvault::*. - Email:
lettre(rustls + tokio). - Object storage: inlined
src/orbit_api/(traits/config) andsrc/orbit/(object_store backends). Built viacrate::orbit::factory::ObjectStorageFactoryfromsrc/jupiter/storage/object_storage.rs::build_object_storage. - Allocator:
jemallocon non‑Windows,mimallocon Windows (configured insrc/main.rs). - Logging:
tracing+tracing-subscriber+tracing-appender(hourly rolling file undermega_cache()/logs, or stdout whenlog.print_std = true).
Run these from the repo root (the agent's shell already starts there).
| Task | Command |
|---|---|
| Build (release-ish) | cargo build |
| Build incl. tests | cargo build --tests |
| Run all tests | cargo test |
| Run one test | cargo test --test <name> or cargo test <substring> -- --nocapture |
| Format | cargo fmt --all |
| Lint | cargo clippy --all-targets -- -D warnings (when used) |
| Run the binary | cargo run -p mega2 -- --config config/config.toml <subcommand> |
| HTTP service example | cargo run -p mega2 -- --config config/config.toml service http --host 0.0.0.0 -p 9000 |
Invariants the build must hold (verified in prior sessions):
cargo buildMUST produce 0 errors and 0 warnings.cargo build --testsMUST produce 0 errors and 0 warnings.- Never silence warnings by adding broad
#[allow(...)]on items you just touched without a reason — the crate‑level#![allow(dead_code)]insrc/lib.rsis intentional (large pub API surface ported from Mega); do not narrow or remove it without a plan to clean the dead items.
Any change to the codebase MUST satisfy all three of the following gates.
These are not optional — do not submit a change until each one is green.
Use the exact commands below (do not substitute simpler variants such as
cargo fmt --all --check or cargo clippy -- -D warnings):
-
Formatting (nightly, check‑only):
cargo +nightly fmt --all --check
Must report no diff. If it does, run
cargo +nightly fmt --allto apply formatting and re‑run the check until clean. The nightly toolchain is required becauserustfmt.tomlmay enable unstable options. -
Lints (all targets, all features, warnings denied):
cargo clippy --all-targets --all-features -- -D warnings
Must exit with 0 warnings, 0 errors. Do not bypass a clippy lint with a blanket
#[allow(...)]; prefer fixing the underlying code. When an allow is genuinely required (e.g. a deliberate API name that tripsclippy::wrong_self_convention), scope it to the smallest possible item and add a brief rationale. -
Tests (with project test env loaded):
source .env.test && cargo test --all
Must finish with all tests passing (0 failures, 0 errored). The
.env.testfile provides DB / cache / service endpoints the test suite expects; do not skip sourcing it. Do not weaken or#[ignore]tests to make this gate pass — fix the root cause.
If .env.test is missing in your environment, stop and ask before
submitting; do not silently fall back to running cargo test --all
without it.
Cargo.toml # package `mega2` (lib `mega2_core` + [[bin]])
config/config.toml # default runtime config (TOML)
src/
├── main.rs # `mega2` binary entry (allocator + CLI dispatch)
├── lib.rs # library root; declares top-level modules
├── cli.rs # clap parsing, log init, ctrlc handler
├── orbit_api/ # object-storage contract (traits, config, errors)
├── orbit/ # object_store backends (adapter, factory)
├── bin/ # auxiliary binaries (e.g. migrate_local_to_s3)
├── commands/ # subcommand registry (builtin / builtin_exec)
├── common/ # error types (MegaError/MegaResult), utils
├── config/ # config loader, profiles, SecretRef, hot reload
├── api/ # axum HTTP API surface
├── api_model/ # request/response DTOs (utoipa schemas)
├── server/ # HTTP/SSH/etc. server bootstrap
├── callisto/ # sea-orm entity models (one file per table)
├── jupiter/ # storage, service, migration, redis, utils
│ ├── storage/ # *Storage structs (BaseStorage + per-domain)
│ ├── migration/ # sea-orm-migration migrators
│ ├── service/
│ ├── redis/
│ └── tests.rs # `pub mod tests` (cfg(test)) — shared test helpers
├── notification/ # email notifications: dispatcher, triggers, storage
├── email/ # Mailer trait + impls (incl. NoopMailer)
├── contract/
│ ├── policy/ # cedar authz: mega.cedarschema, mega_policies.cedar
│ └── vault/ # PKI / KV / secret engine integration layer over the
│ │ # `libvault` crate (no vendored module since 2026-08-21)
│ └── integration/
│ ├── jupiter_backend.rs
│ └── vault_core.rs # VaultCore, VaultCoreInterface
├── ceres/ context/
tests/ # process-level integration tests (integration_*.rs)
target/ # build artifacts (gitignored)
pub use crate::callisto::*; is re‑exported from lib.rs; importing
callisto entities elsewhere should use crate::callisto::<table> paths.
Object storage public types are available from crate::orbit_api::*; the
concrete backend is built through crate::jupiter::storage::object_storage::build_object_storage
(which calls crate::orbit::factory::ObjectStorageFactory::build).
- Formatting: match
cargo +nightly fmt --alloutput (the same formatter used by the requiredcargo +nightly fmt --all --checkgate). Don't hand‑format around it. - Imports: group by
std→ external crates →crate::(matches the existing files). Avoid wildcarduse crate::*;in library code; wildcards are fine insidemod tests. - Errors: use
crate::common::errors::{MegaError, MegaResult}for application code paths that already use them;anyhow::Resultis used in lower‑level utilities andthiserrorfor new typed errors. Don't mix the three within the same module. - Async: functions returning
Resultshould beasync fn -> Result<T, E>usingtokioruntime. Don't addblock_oninside async contexts. - Logging: use
tracing::{info, warn, error, debug, trace}macros, notprintln!. Structured fields preferred (e.g.info!(path = %p, "loaded")). - DB access: go through the
*Storagetypes insrc/jupiter/storage/rather than callingsea_ormdirectly from API/handler code. - Comments: sparse, English. Match the surrounding density — do not add comments to files that don't already use them.
- Files / modules: snake_case filenames, one module per file,
mod.rsonly for directory module roots.
- Bilingual guide docs: the user-facing guides under
docs/(quick-start,user-guide,configuration,deployment,architecture,contributing) ship in two languages. English is the default file (<name>.md); Chinese lives in the<name>.zh.mdsibling (same convention asREADME.md/README.zh.md). Write the Chinese version first, then translate; both versions must keep identical structure, carry the language switcher line at the top, and cross-link within the same language (zh →.zh.md, en →.md). When you change one language version of a guide, update the other in the same change. - Link, don't copy: facts that have an authoritative home
(
config/config.toml,docs/monorepo.md,docs/deploy-trunk.md,docs/refactoring/*.md) are linked, not duplicated. Every relative link in a doc must resolve to a file in the current checkout. - Plan docs under
docs/plan/followdocs/plan/README.mdand the plan templates; they are Chinese-first and unchanged by the bilingual convention above.
sea_ormimports inside tests. There is nocrate::jupiter::sea_ormre‑export. Import traits from the top‑level crate:Forgetting these traits produces misleading errors such asuse sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
email_jobs::Entity is not an iterator.VaultCorepath.src/contract/vault/integration/mod.rsdoes not re‑exportVaultCore. Import it directly from its submodule:use crate::contract::vault::integration::vault_core::{VaultCore, VaultCoreInterface};
- Glob re‑exports / the
vaultname. There is no top-levelmod vault;any more — the vendored RustyVault module was removed on 2026-08-21 and the library comes from thelibvaultcrate.crate::vault::*is not a valid path;rg 'crate::vault' src binshould stay at zero hits. Three different things still share the name, so keep imports explicit:crate::callisto::vaultis the SeaORM entity,crate::contract::vaultis the product integration layer, andlibvault::*is the library itself. - Crate‑level
dead_codeallow.#![allow(dead_code)]inmain.rsis intentional. If you add a new pub API item, you don't need to add per‑item allows; if you remove the crate‑level allow, expect ~70 warnings. - Test DB helpers. Tests requiring a database use
crate::jupiter::tests::test_db_connection(<TempDir path>)followed bycrate::jupiter::migration::apply_migrations(&db, true).await. Reuse these helpers instead of constructing connections by hand. - Allocator cfg. Don't touch the
#[global_allocator]blocks inmain.rsunless intentionally changing allocators on a platform. unwrap()in non‑test code. Avoid introducing newunwrap/expecton fallible operations; returnMegaResult/anyhow::Resultinstead. Existing call sites invault/pki.rstest helpers are OK because they are test‑only.
- Implement the command module under
src/commands/<name>.rs. - Register it in
src/commands/mod.rsviabuiltin()(clapCommand) and wire its executor inbuiltin_exec()socli::exec_subcommandfinds it. - The executor signature is
fn(config: Config, args: &ArgMatches) -> MegaResult. - Add unit tests next to the command and, where useful, a CLI parsing test
mirroring the existing ones in
src/cli.rs::tests.
- Generate or hand‑write the entity file under
src/callisto/<table>.rsand add it tosrc/callisto/mod.rs. - Add a migrator under
src/jupiter/migration/and register it in that module's migrator list. - If a new domain storage is needed, add
<domain>_storage.rsundersrc/jupiter/storage/and re‑export fromstorage/mod.rs. - Cover with a
#[cfg(test)] mod teststhat usestest_db_connection+apply_migrationsas shown innotification/dispatcher.rs::tests.
When you change ../megaui sources that affect apps/web, rebuild and
restart the compose website-next service after
the change (do not wait for the user to ask):
./scripts/reload-website-next.shThe script debounces rapid edits (~3s) and runs docker compose build + recreate
in the background. Logs: ${TMPDIR:-/tmp}/mega2-reload-website-next/build.log.
Project hooks in .cursor/hooks.json trigger the same script on megaui file
edits and again on agent stop when a reload was requested.
When a plan task card is complete (Lifecycle=done, dual review PASS), do
not wait for the user to ask: bump version, commit that card only, and
push. VCS is Libra (no git).
- Bump
Cargo.tomlversionby the card’sVersion increment(default patch +1) and refreshCargo.lockformega2. libra add+libra commit -mfor that card only.libra push origin main. Never--force. If the branch has diverged from origin, stop and report.- Start the next card only after this card’s commit and push succeed.
See .cursor/rules/task-card-release.mdc.
- Do not commit secrets, real tokens, or production
config.tomlvalues. - Do not add new dependencies to
Cargo.tomlwithout confirming they pull their weight (compile time / binary size / license). Prefer reusing what's already vendored (e.g.reqwest,rustls,tokio). - Do not rewrite working modules to "modernize" them; keep diffs focused on the requested change.
- Do not disable or weaken tests (
#[ignore],--skip, deleted asserts) to make a build pass. Fix the root cause or ask. - Do run
cargo buildandcargo build --testsbefore submitting any change that touchessrc/.
Required gates (see Required Checks Before Submitting Code Changes):
-
cargo +nightly fmt --all --check→ no diff. -
cargo clippy --all-targets --all-features -- -D warnings→ 0 warnings, 0 errors. -
source .env.test && cargo test --all→ all tests pass.
Additional sanity checks:
-
cargo build→ 0 errors, 0 warnings. -
cargo build --tests→ 0 errors, 0 warnings. - No stray debug files (
.warnings.log,.output.txt, ad‑hoc scripts) left in the repo root. - No new top‑level
#[allow(...)]other than what already exists.