Skip to content

STORY WORKFLOW

github-actions[bot] edited this page Jul 29, 2026 · 2 revisions

Executing a Nuncio story (guide for LLM contributors)

You have been assigned one GitHub issue ("story") from the Nuncio roadmap and are working on your own machine. This is the canonical protocol for doing it successfully and getting it merged. Every story issue links here — read this first, then the issue.

Product-owner / reviewer: the coordinating session (referred to as "the PO"). You implement; the PO reviews and merges. Do not merge your own work.

1. Orient (read before coding)

2. The definition of done (non-negotiable)

A story is done only when all of these hold:

  1. engine + proto (if the API surface changes) + CLI command + offline E2E test exist together and prove the capability end to end.
  2. The full local gate is green — that is cargo fmt --all -- --check, cargo check-all (clippy --all-targets --workspace -D warnings, zero warnings), and cargo test-all (cargo test --workspace), run as three separate commands (there is no combined cargo verify alias — Cargo aliases can't chain subcommands). 0 ignored tests.
  3. No fabricated success. A path that cannot do the real thing returns an honest Unimplemented/error — never canned data, never a fake "sent"/"ok". (Anti-pattern to never imitate: a client that logs "fetching…" and returns a hardcoded result; a test that asserts on fabricated output.)
  4. All external protocols are mocked (wiremock / Mock*Backend); live network calls in tests are forbidden. Never connect to a real server.
  5. The proto contract-stability test passes (see §5).

3. Hard constraints

  • Rust edition 2021. No unsafe. No unwrap/expect/panic/todo in non-test code (tests are exempt via each crate's #![cfg_attr(test, allow(...))]). Use thiserror error types.
  • Comment convention: code comments (.rs/.proto) state the code's intent/constraints/rationale ONLY. No backlog/story numbers, no GitHub issue refs (#NNN, GH-, Refs #), no "Phase N"/"story"/"backlog" breadcrumbs in comments. Keep genuine technical rationale (RFC citations, algorithm notes, why-not-X). That traceability lives in git history + PRs.
  • Toolchain is pinned (rust-toolchain.toml = 1.97.1). Green locally == green in CI. The pre-commit hook runs the full gate.

4. The security invariant (do not violate)

Every gRPC service MUST be mounted behind its own BearerAuthInterceptor. See the doc comment in nuncio.proto and the mounting code in crates/nunciod/src/grpc.rs (serve_on_listener_with_overrides). If you add a service, wrap it exactly like Mail/Filters. Your E2E must assert that an unauthenticated call to your service is rejected (mirror crates/nunciod/tests/grpc_auth_test.rs).

5. Patterns to mirror (copy these, don't invent)

  • A full API vertical (proto → daemon → CLI → E2E): the Mail vertical is the reference. service Mail in crates/nuncio-proto/proto/nuncio/v1/nuncio.proto; MailGrpcService + MailEngineOverrides + serve_on_listener_with_overrides in crates/nunciod/src/grpc.rs; connect_mail in crates/nuncio-proto/src/client.rs; handle_*/connect_mail_client in crates/nuncio-cli/src/runner.rs; the capstone crates/nunciod/tests/spine_e2e_test.rs.
  • An engine backend + transport (real protocol client + mock + trait): the Calendar engine (crates/nuncio-cal/src/{backend.rs,caldav.rs,parser.rs}) mirrors nuncio_mail::MailBackend; its wiremock test is crates/nuncio-cal/tests/wiremock_caldav_test.rs. The JMAP wiremock test crates/nuncio-mail/tests/wiremock_jmap_test.rs is the protocol-level template.
  • Store CRUD: mirror DatabaseEngine::save_email and the calendar CRUD in crates/nuncio-store/src/db.rs.
  • Changing the proto → regenerate the golden. Any change to nuncio.proto will (by design) fail nuncio-proto's contract_stability::descriptor_matches_committed_golden test. The failure message in crates/nuncio-proto/src/lib.rs prints the exact recipe: rebuild -p nuncio-proto, copy the freshly generated nuncio_v1_descriptor.bin from this build's OUT_DIR over crates/nuncio-proto/proto/nuncio/v1/descriptor.bin, re-test, and commit the new golden with your change. Keep additions additive within nuncio.v1.

6. Proto coordination (important for parallel work)

Several stories add to the same nuncio.proto + its golden. To avoid conflicts, only one proto-touching story is "in flight" at a time. Before starting a story that changes nuncio.proto, confirm with the PO that no other proto story is open. Non-proto stories (engine-only, CLI-only) can run in parallel.

7. Branch, PR, and review flow

  1. Branch from dev: story/<milestone>-<slug> (e.g. story/m1-calendar-api, story/m6-zeroize-keys). Never commit to dev or main directly.
  2. TDD where practical. Keep commits Conventional (feat(scope): …, fix(scope): …), imperative, <72-char subject, no AI attribution, no issue refs in code (a Refs #NNN in the commit message is fine).
  3. Before pushing, make sure cargo fmt --all -- --check, cargo check-all, and cargo test-all are all green. The pre-commit hook enforces this.
  4. Open a PR to dev (never to main). In the PR body: link the issue, summarize what you built, paste the gate output (fmt/clippy/test results + test counts) as evidence, and list any decisions or follow-ups. If you found a real bug outside your scope, file a new issue — do not silently fix or ignore it.
  5. The PO reviews spec compliance + code quality (and, for auth/crypto/transport, an adversarial pass). Address Critical/Important findings. The issue closes only after the review passes — never on a green build alone.

8. If you get stuck

Report honestly: what's blocking, the exact error, and what you tried. Do not weaken the auth invariant, skip the hook (--no-verify), fabricate data, or hit a live server to make something pass. An honest BLOCKED beats a green lie.

Clone this wiki locally