Skip to content
Merged
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
28 changes: 15 additions & 13 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ federated control between mesh participants.

## Module Interfaces

`docs/interfaces.md` is the source of truth for public module ownership,
interfaces, dataflow, and lifecycle boundaries.

- Read it before nontrivial code or design work.
- Update it with public API, responsibility, dataflow, or lifecycle changes;
skip private helper or file-layout churn.
`context/interfaces/` contains one interface contract per Rust source file. Map
source paths mechanically: `src/foo.rs` -> `context/interfaces/src/foo.md`, and
`src/foo/mod.rs` -> `context/interfaces/src/foo/mod.md`.

- Read only the per-module interface docs relevant to the task.
- Update the relevant `context/interfaces/**/*.md` file when public API,
responsibility, dataflow, or lifecycle changes; skip private helper or
file-layout churn.
- Interface changes are design changes. Ask before making them unless the user
explicitly requested the change.
- When updating `docs/interfaces.md`, minimize churn: preserve existing section
order and headings unless the architecture actually moved; prefer narrow edits
to affected module sections over broad terminology rewrites; do not clean up
adjacent stale wording opportunistically. If adding a new module, insert only
the new section at the most local sensible position; do not move existing
sections to make the narrative cleaner.
- If code and `interfaces.md` disagree and the doc seems wrong, stop and ask.
- When updating interface docs, minimize churn: preserve existing section order
and headings unless the architecture actually moved; prefer narrow edits to
affected module files over broad terminology rewrites; do not clean up adjacent
stale wording opportunistically. If adding a new module, add only the new
matching interface file; do not move existing sections to make the narrative
cleaner.
- If code and interface docs disagree and the docs seem wrong, stop and ask.

Prefer deep modules: small, stable public APIs that hide lifecycle, policy, and
state needed to preserve their invariants. Avoid conceptual cycles, leaky
Expand Down
43 changes: 43 additions & 0 deletions context/interfaces/src/admin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# `src/admin.rs`


## Responsible for
- Serving the local Unix-socket admin API.
- Providing a client used by CLI commands.
- Dispatching admin commands to daemon state and modules.

## Public interface
```rust
/// Local admin RPC server.
pub(crate) struct AdminServer;

impl AdminServer {
/// Bind the admin Unix socket, creating parents and removing stale sockets.
pub(crate) fn bind(socket_path: Option<PathBuf>) -> anyhow::Result<Self>;

/// Run the admin server until cancelled, then clean up the socket.
pub(crate) async fn run(
self,
grpc: GrpcService,
adhoc: adhoc::Handle,
cancel: CancellationToken,
) -> anyhow::Result<()>;
}

/// Client for issuing local admin RPCs.
pub(crate) struct AdminClient;

impl AdminClient {
/// Create a client for the configured or default admin socket.
pub(crate) fn new(socket_path: Option<PathBuf>) -> Self;

/// Return a client for ad-hoc admin RPCs.
pub(crate) async fn adhoc_admin_service_client(&self) -> anyhow::Result<AdhocAdminServiceClient<Channel>>;

/// Fetch a structured debug/status dump from the daemon.
pub(crate) async fn debug_dump(&self) -> anyhow::Result<StateDump>;

/// Submit one unsigned endorsement intent to the daemon for local signing.
pub(crate) async fn endorse(&self, endorsement: endor::Base) -> anyhow::Result<()>;
}
```
14 changes: 14 additions & 0 deletions context/interfaces/src/assert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# `src/assert.rs`


## Responsible for
- Marking programmer-error invariants where panic is intentional.

## Public interface
```rust
/// Extension trait for assertion-style unwrapping.
pub trait UnwrapAssert {
type Output;
fn assert(self) -> Self::Output;
}
```
34 changes: 34 additions & 0 deletions context/interfaces/src/authorization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# `src/authorization.rs`


## Responsible for
- Describing authorization policy between source and destination identities.
- Encoding and decoding authorization policy data.

The trust engine derives concrete authorization views from these policies.

## Public interface
```rust
/// Authorization policy statement.
pub struct Authz {
/// Source IMIDs that can initiate connections.
pub source_imids: BTreeSet<Imid>,

/// Source name patterns that can initiate connections.
pub source_patterns: BTreeSet<NamePattern>,

/// Destination IMIDs that can receive connections.
pub destination_imids: BTreeSet<Imid>,

/// Destination name patterns that can receive connections.
pub destination_patterns: BTreeSet<NamePattern>,
}

impl Authz {
/// Create a new empty authorization policy.
pub fn new() -> Self;
}

impl TryFrom<proto::Authz> for Authz;
impl From<Authz> for proto::Authz;
```
11 changes: 11 additions & 0 deletions context/interfaces/src/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `src/cli.rs`


## Responsible for
- Parsing CLI arguments and dispatching commands.

## Public interface
```rust
/// Run the top-level Intermesh CLI.
pub async fn run() -> anyhow::Result<()>;
```
11 changes: 11 additions & 0 deletions context/interfaces/src/cmd_status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `src/cmd_status.rs`


## Responsible for
- Formatting human-readable status output.

## Public interface
```rust
/// Print the current human-readable daemon status.
pub async fn run(socket_path: Option<PathBuf>, watch: bool) -> anyhow::Result<()>;
```
50 changes: 50 additions & 0 deletions context/interfaces/src/connect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# `src/connect.rs`


## Responsible for
- Building Intermesh mTLS clients and server streams.
- Attaching verified peer identity to tonic connection metadata.

## Public interface
```rust
/// mTLS client for connecting to Intermesh peers.
pub(crate) struct IntermeshClient;

impl IntermeshClient {
/// Build a client using the local keypair, verifier, and trust engine.
pub(crate) fn new(
keypair: &ImidKeypair,
verifier: Arc<IntermeshVerifier>,
trust_engine: Arc<TrustEngine>,
) -> Self;

/// Add a single-use IP hint for bootstrapping an unknown IMID.
pub(crate) fn with_bootstrap_hint(self, imid: Imid, ip: IpAddr) -> Self;

/// Connect to either `<imid>.imid` or a mesh name.
pub(crate) async fn connect(&mut self, host: &str, port: u16) -> anyhow::Result<ClientTlsStream<TcpStream>>;

/// Resolve a mesh name through the trust engine and connect to its IMID.
pub(crate) async fn connect_name(&mut self, name: &Name, port: u16) -> anyhow::Result<ClientTlsStream<TcpStream>>;

}

impl Service<Uri> for IntermeshClient;

/// Create a stream of accepted Intermesh mTLS server connections.
pub(crate) fn intermesh_server_stream(
keypair: &ImidKeypair,
verifier: Arc<IntermeshVerifier>,
listener: TcpListener,
) -> impl Stream<Item = Result<IntermeshTlsStream, io::Error>>;

/// Peer identity metadata attached to accepted connections.
pub(crate) struct IntermeshConnectInfo {
pub(crate) peer: Imid,
}

/// Server-side mTLS stream with verified peer identity.
pub(crate) struct IntermeshTlsStream;

impl Connected for IntermeshTlsStream;
```
39 changes: 39 additions & 0 deletions context/interfaces/src/constraint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# `src/constraint.rs`


## Responsible for
- Describing a group of endorsements that are permitted.
- Encoding and decoding delegated authority data.

The trust engine owns the actual authorization checks against constraints.

## Public interface
```rust
/// Describes which endorsements an authority may issue.
pub struct Constraint {
/// IMIDs that may issue matching endorsements.
pub endorser_imids: BTreeSet<Imid>,

/// Name patterns whose assigned IMIDs may issue matching endorsements.
pub endorser_patterns: BTreeSet<NamePattern>,

/// IMIDs that matching endorsements may target.
pub target_imids: BTreeSet<Imid>,

/// Name patterns whose assigned IMIDs matching endorsements may target.
pub target_patterns: BTreeSet<NamePattern>,

/// Whether matching endorsements may target any IMID.
pub any_target: bool,

/// Names that matching endorsements may assign.
pub permitted_patterns: BTreeSet<NamePattern>,

/// IP addresses that matching endorsements may assign.
pub permitted_subnets: BTreeSet<IpNet>,

/// Whether matching endorsements may delegate further authority.
pub authority: bool,
}

```
20 changes: 20 additions & 0 deletions context/interfaces/src/daemon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# `src/daemon.rs`


## Responsible for
- Process startup and shutdown.
- Starting admin and gossip servers.
- Starting background loops.
- Performing final state save.

## Public interface
```rust
/// gRPC service context shared by tonic service implementations.
pub(crate) struct GrpcService;

/// Run the daemon until shutdown, including servers and background loops.
pub(crate) async fn run(
state: state::State,
on_ready: Option<Command>,
) -> anyhow::Result<()>;
```
30 changes: 30 additions & 0 deletions context/interfaces/src/dsl/mod.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# `src/dsl/mod.rs`


## Responsible for
- Parsing human-readable endorsement facts into `endor::Base`.
- Parsing human-readable constraint expressions into `constraint::Constraint`.
- Formatting endorsements, constraints, and authorization policy for CLI/status
output.

## Public interface
```rust
/// Parse one or more human-written endorsement facts.
pub fn parse_endorsements(s: &str) -> anyhow::Result<Vec<endor::Base>>;

/// Parse a human-written delegation constraint.
pub fn parse_constraint(s: &str) -> anyhow::Result<Constraint>;

/// Format one endorsement fact for CLI or status output.
pub fn format_endorsement(base: &endor::Base) -> String;

/// Format a list of endorsement facts for CLI or status output.
pub fn format_endorsements(endorsements: &[endor::Base]) -> String;

/// Format one delegation constraint for CLI or status output.
pub fn format_constraint(constraint: &Constraint) -> String;

/// Format one authorization policy for CLI or status output.
pub fn format_authz(authz: &Authz) -> String;

```
10 changes: 10 additions & 0 deletions context/interfaces/src/endor/mod.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# `src/endor/mod.rs`


## Responsible for
- Exposing endorsement fact and signed-message types.

## Public interface
```rust
pub(crate) use types::{Base, Endor};
```
73 changes: 73 additions & 0 deletions context/interfaces/src/endor/types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# `src/endor/types.rs`


## Responsible for
- Representing unsigned endorsement bases and verified signed endorsements.
- Signing local endorsements and verifying external endorsement protos.
- Encoding and decoding endorsement protobuf/base64 representations.

## Public interface
```rust
/// Unsigned semantic endorsement.
pub struct Base {
/// IMID that signs this endorsement.
pub endorser: Imid,

/// IMIDs receiving the endorsed properties.
pub target_imids: BTreeSet<Imid>,

/// Name patterns whose assigned IMIDs receive the endorsed properties.
pub target_patterns: BTreeSet<NamePattern>,

/// IP addresses assigned by this endorsement.
pub ips: BTreeSet<IpAddr>,

/// Names assigned by this endorsement.
pub names: BTreeSet<Name>,

/// Authority delegated by this endorsement.
pub constraints: BTreeSet<Constraint>,

/// Authorization policy asserted by this endorsement.
pub authz: BTreeSet<Authz>,
}

impl Base {
/// Create an empty endorsement base for local signing.
pub(crate) fn new(endorser: Imid) -> Self;

/// Sign this base with the local keypair.
pub(crate) fn sign(&self, keypair: &ImidKeypair) -> Endor;
}

/// Opaque signed endorsement, constructed by verification or local signing.
pub struct Endor;

impl Endor {
/// Return the unsigned fact carried by this endorsement.
pub fn base(&self) -> &Base;

/// Return the endorsement issue timestamp.
pub fn issued(&self) -> u64;

/// Return the endorsement expiration timestamp.
pub fn expires(&self) -> u64;

/// Return read-only signature bytes for this endorsement.
pub fn signature_bytes(&self) -> &[u8];

/// Encode the signed endorsement for storage or CLI display.
pub fn to_base64(&self) -> String;

/// Decode and verify a stored signed endorsement.
pub fn from_base64(b64: &str) -> anyhow::Result<Self>;

/// Convert all valid protobuf endorsements, dropping invalid entries.
pub(crate) fn valid_from_protos(protos: Vec<proto::Endorsement>) -> Vec<Self>;
}

impl TryFrom<proto::EndorsementData> for Base;
impl From<&Base> for proto::EndorsementData;
impl TryFrom<proto::Endorsement> for Endor;
impl From<Endor> for proto::Endorsement;
```
Loading
Loading