Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ This file provides guidance for AI coding agents working in the

## Project Overview

**NCX Infra Controller (NICo)** is an API-based microservice written in Rust
that provides site-local, zero-trust, bare-metal lifecycle management with
DPU-enforced isolation. It automates the complexity of the bare-metal lifecycle
to fast-track building next-generation AI Cloud offerings.
**NVIDIA Infra Controller (NICo)** is an API-based microservice written in Rust
and Golang that provides site-local, zero-trust, bare-metal lifecycle
management with DPU-enforced isolation. It automates the complexity of the
bare-metal lifecycle to fast-track building next-generation AI Cloud offerings.

> **Status:** Experimental/Preview. APIs, configurations, and features may
> change without notice between releases.
Expand Down Expand Up @@ -45,6 +45,7 @@ infra-controller/
├── lints/ # Custom Clippy lints (carbide-lints crate)
├── include/ # Shared Makefile fragments
├── .github/ # GitHub Actions workflows and templates
├── rest-api/ # Golang-based REST API
├── Cargo.toml # Workspace dependency management
├── Makefile.toml # Primary build/task automation
├── Makefile-build.toml # Build-specific tasks
Expand All @@ -53,6 +54,7 @@ infra-controller/

## Technology Stack

### gRPC API and components:
- **Language:** Rust (edition 2024, toolchain pinned in `rust-toolchain.toml`)
- **Async runtime:** Tokio
- **gRPC framework:** Tonic (with TLS via Rustls/aws_lc_rs)
Expand All @@ -62,6 +64,9 @@ infra-controller/
- **Build tool:** `cargo-make` (TOML task runner)
- **API definitions:** Protocol Buffers (protobuf)

### REST API and components
- **Language (REST API):** Golang 1.26.x

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## Build, Test, and Lint Commands

All task automation uses `cargo-make`. Install it with:
Expand Down Expand Up @@ -159,17 +164,6 @@ verification expectations.
See [`STYLE_GUIDE.md`](STYLE_GUIDE.md) for detailed Rust coding conventions.
Make sure to review it to ensure changes meet the expected style of the codebase.

### Avoid stringly-typed values

When a value has a known, finite set of possibilities, model it with an enum (or
a struct of enums) and derive its string form via `Display`/`FromStr` — do not
pass it around as a bare `String` or `&str` literal. Stringly-typed values are
easy to misspell (`NICO-` vs `NICOO-`), silently break log filters and alerts,
and can't be exhaustively checked by the compiler. See
[`ErrorCode`](crates/api-model/src/errors.rs) for the pattern: typed
`ErrorSystem`/`ErrorSubsystem` parts plus a `code`, rendered to the wire string
in one place. Reserve raw strings for genuinely open-ended values.

### Instrumentation: logs and metrics

The decision rule:
Expand Down
71 changes: 71 additions & 0 deletions STYLE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -695,3 +695,74 @@ fn prefer() {
fails().ok();
}
```

### Avoid stringly-typed values

When a value has a known, finite set of possibilities, model it with an enum
(or a struct of enums) and implement traits `Display` and `FromStr` — do not
pass it around as a bare `String` or `&str` literal. Stringly-typed values are
Comment thread
coderabbitai[bot] marked this conversation as resolved.
easy to misspell (`NICO-` vs `NICOO-`), silently break log filters and alerts,
and can't be exhaustively checked by the compiler. See
[`ErrorCode`](crates/api-model/src/errors.rs) for the pattern: typed
`ErrorSystem`/`ErrorSubsystem` parts plus a `code`, rendered to the wire string
in one place. Reserve raw strings for genuinely open-ended values.

### Prefer methods over free functions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this.


When a function operates primarily on a specific type, define it as a method on that type rather than a free-standing function. This keeps related behavior co-located with the type, makes it easier to discover via autocomplete, and reads more naturally at the call site.

```rust
// Avoid — free function that operates on a specific type
fn machine_display_name(machine: &Machine) -> String {
format!("{} ({})", machine.hostname, machine.id)
}

fn is_machine_ready(machine: &Machine) -> bool {
machine.state == MachineState::Ready && machine.health.is_ok()
}

// Prefer — methods on the type itself
impl Machine {
fn display_name(&self) -> String {
format!("{} ({})", self.hostname, self.id)
}

fn is_ready(&self) -> bool {
self.state == MachineState::Ready && self.health.is_ok()
}
}
```

This applies to enums as well:

```rust
// Avoid
fn is_terminal_state(state: &MachineState) -> bool {
matches!(state, MachineState::Failed | MachineState::Decommissioned)
}

fn state_label(state: &MachineState) -> &'static str {
match state {
MachineState::Ready => "ready",
MachineState::Failed => "failed",
MachineState::Decommissioned => "decommissioned",
}
}

// Prefer
impl MachineState {
fn is_terminal(&self) -> bool {
matches!(self, Self::Failed | Self::Decommissioned)
}

fn label(&self) -> &'static str {
match self {
Self::Ready => "ready",
Self::Failed => "failed",
Self::Decommissioned => "decommissioned",
}
}
}
```

Free functions are still appropriate when the logic genuinely spans multiple unrelated types, belongs in a module rather than a single type, or is a utility with no natural owner.
Loading