# Aspire Configuration Example

Demonstrates Aspire publish-time configuration generation for security and infrastructure settings.

## 📋 Overview

This example shows how to:

- Define security permissions and business roles in C# code
- Configure upstream API dependencies with required permissions
- Generate YAML configuration files during `aspire publish`

## 🏗️ Architecture

```mermaid
flowchart TB
    subgraph AppHost["AspireConfig.AppHost"]
        direction TB
        Auth["Auth/<br/>Permissions.cs<br/>BusinessRoles.cs"]
        Config["AppHost.cs<br/>AddSaifEnvironment()"]
    end

    subgraph Resources["Resource Model"]
        SaifEnv["SaifEnvironmentResource"]
        Security["SecurityResource<br/>(child)"]
        Upstream["UpstreamApiResource"]
        SaifEnv --> Security
    end

    subgraph Publish["aspire publish"]
        Generator["SecurityResource<br/>Pipeline Step"]
    end

    subgraph Output["Generated YAML"]
        API["infra/api/config.yml"]
        Corp["infra/auth/corp/config.yml"]
        ExtUser["infra/auth/ext/user/<br/>business-role-app-role.yml"]
        ExtApp["infra/auth/ext/app/<br/>authorized-apps.yml"]
    end

    AppHost --> Resources
    Security --> Generator
    Upstream --> Generator
    Generator --> Output
```

## 🧩 Components

| File                    | Description                            |
| ----------------------- | -------------------------------------- |
| `Auth/Permissions.cs`   | Defines app roles and scopes           |
| `Auth/BusinessRoles.cs` | Groups permissions into business roles |
| `AppHost.cs`            | Configures security for publish        |

## 🔑 Key Features

- **Composite Resource Pattern** - `SaifEnvironmentResource` aggregates child resources like `SecurityResource`
- **Compile-Time Safety** - Invalid configurations fail at build time
- **IntelliSense Support** - Discover permissions and roles while coding
- **Type-Safe Permissions** - `AppRole` vs `Scope` enforced by compiler
- **Dual Identity Support** - Corporate (Entra) and external (Okta) users

## 📂 Project Structure

```
foundry/dotnet/aspire-config/
├── AspireConfig.sln
├── src/
│   ├── AspireConfig.AppHost/
│   │   ├── Auth/
│   │   │   ├── Permissions.cs        # App roles and scopes
│   │   │   └── BusinessRoles.cs      # Business role definitions
│   │   ├── AppHost.cs                # Security configuration
│   │   └── ResourceBuilders/         # Generated API builder
│   ├── AspireConfig/                 # API project
│   ├── AspireConfig.UnitTests/
│   └── AspireConfig.IntegrationTests/
└── infra/                            # Infrastructure config
```

## 🚀 Getting Started

### Prerequisites

- .NET 10.0 SDK
- Aspire 13.x

### Running the Example

```bash
cd foundry/dotnet/aspire-config
dotnet run --project src/AspireConfig.AppHost
```

### Publishing Configuration

To generate the security YAML files:

```bash
dotnet run --project src/AspireConfig.AppHost -- publish
```

## 📝 Code Walkthrough

### 1. Define Permissions

```csharp
// Auth/Permissions.cs
public static class Permissions
{
    // App roles exposed by this API
    public static readonly AppRole ClaimsRead = new("Claims.Read", "Read Claims");
    public static readonly AppRole ClaimsWrite = new("Claims.Write", "Write Claims");

    // Scopes for upstream API calls
    public static readonly Scope OrdersRead = new("Orders.Read", "Read Orders");
}
```

### 2. Define Business Roles

```csharp
// Auth/BusinessRoles.cs
public static class BusinessRoles
{
    public static readonly BusinessRole ClaimsAdjuster = new("Claims Adjuster");
    public static readonly BusinessRole InjuredWorker = new("Injured Worker");
}
```

### 3. Define App Role Assignments

```csharp
// Auth/AppRoleAssignments.cs
public static class AppRoleAssignments
{
    public static readonly AppRoleAssignment ClaimsAdjuster = new(
        BusinessRoles.ClaimsAdjuster,
        [Permissions.ClaimsRead, Permissions.ClaimsWrite]);

    public static readonly AppRoleAssignment InjuredWorker = new(
        BusinessRoles.InjuredWorker,
        [Permissions.ClaimsRead]);
}
```

### 4. Configure in AppHost

```csharp
// AppHost.cs
builder.AddSecurity()
    .WithCorporateAssignment(AppRoleAssignments.ClaimsAdjuster)   // Entra users
    .WithExternalAssignment(AppRoleAssignments.InjuredWorker);    // Okta users

builder.AddUpstreamApi("it-api-proc-orders")
    .WithScope(Permissions.OrdersRead);
```

## 📄 Generated Output

### `infra/api/config.yml`

```yaml
app_roles:
  - value: Claims.Read
    display_name: Read Claims
  - value: Claims.Write
    display_name: Write Claims
scopes: []
```

### `infra/auth/corp/config.yml`

```yaml
business_roles:
  - name: Claims Adjuster
    app_roles:
      - Claims.Read
      - Claims.Write
authorized_apps:
  - project_id: it-api-proc-orders
    scopes:
      - Orders.Read
```

## 🔗 Related Documentation

- [Aspire Security Configuration Guide](../guides/security/configuration/aspire-security-configuration.md)
- [Business Roles](../guides/security/configuration/business-roles.md)
- [User Permissions](../guides/security/configuration/user-permissions.md)

## 📍 Source Code

**Location:** [`foundry/dotnet/aspire-config/`](https://dev.azure.com/SAIFCorporation/Platform/_git/forge?path=/foundry/dotnet/aspire-config)
