# 3.5.0

**Release Date:** May 7, 2026

---

## ✨ New Features

### Smithy AI Assistant

#### Smithy: Full Platform Service with MCP, Multi-Agent Orchestration & CLI Bridge 🤖

**PR:** [#592](https://github.com/saif-corp/forge/pull/592)

Smithy is now a fully deployed platform service — SAIF's AI developer assistant — backed by an MCP server, multi-agent orchestration with an experts-as-tools pattern, and a CLI bridge for VS Code integration.

**Key Features:**

- ✅ **Multi-agent orchestration** — Forge docs agent + Azure DevOps agent, routed by LLM via function invocation
- ✅ **MCP server** — Streamable HTTP transport (`/mcp`) with stateful sessions and per-user conversation history in Cosmos DB
- ✅ **Bot channel** — M365 Agents SDK bot for Teams with LLM-based chat history compaction and @mention gating
- ✅ **TypeSpec spec** — OpenAPI generated from TypeSpec for APIM registration
- ✅ **CLI MCP Bridge** — `RemoteMcpBridge` BackgroundService dynamically discovers remote tools and registers them locally (e.g., `smithy_ask`) with `tools/list_changed` so VS Code picks up new tools without a restart

**Benefits:**

- 🤖 AI-powered developer assistance directly in VS Code and Teams
- 🔄 Seamless tool federation — local and remote MCP tools coexist
- 🔐 Secure by default — APIM validates Entra ID tokens; MSI for downstream calls
- 🚀 Graceful degradation — remote connection failures are non-fatal; local tools always load

---

#### Smithy: Migrated to Composable `saif-resources` Terraform Modules ♻️

**PR:** [#650](https://github.com/saif-corp/forge/pull/650)

Smithy's bespoke 18-file, ~500-line Terraform configuration is replaced with a clean 190-line `main.tf` composing the new `saif-resources` module collection.

**New `saif-resources` modules:**

- **`environment`** — resolves all shared infrastructure (TFE outputs, networking, naming) into a single `context` object
- **`identity`** — UAMI + App Registration + Key Vault secret lifecycle; emits credential app settings controlled by flags
- **`cosmosdb`** — Cosmos DB account + containers + data-plane RBAC
- **`ai-project`** — AI Foundry project + model deployments with logical deployment key mapping (e.g. `deployment_names["chat"]`)
- **`bot`** — Azure Bot Service + OAuth connections + Teams channel
- **`api`** — Web App + APIM registration + Front Door routing + auth policies

**Benefits:**

- 🚀 Teams composing new AI services can bootstrap from proven modules rather than writing bespoke HCL
- 🔄 `moved.tf` handles full state migration — no resource recreation required
- ✅ Speculative plans validated against both `app-platformdev-corporate-smithy` and `app-test-corporate-smithy` with Sentinel passing

---

### Feature Flags

#### Label-Based Feature Flag Isolation with App Configuration Refresh 🚩

**PR:** [#640](https://github.com/saif-corp/forge/pull/640)

Adds label-based isolation for Azure App Configuration feature flags so that different environments or tenants can have independent flag states within a single App Configuration store.

**Benefits:**

- 🎯 Isolate feature flag state per environment, tenant, or label without separate stores
- 🔄 Automatic configuration refresh picks up flag changes without redeployment
- ✅ Consistent flag evaluation across all running instances

---

#### Foundry: `useFeatureFlags` Hook & Developer Guide 📚

**PR:** [#629](https://github.com/saif-corp/forge/pull/629)

Adds first-class feature flag support to the Foundry frontend with a `useFeatureFlags` React hook and a companion developer guide.

**Benefits:**

- 🚀 Developers can gate UI features with a single hook call
- 📖 Comprehensive developer guide with usage examples included

---

### Templates

#### New `saif-feature-dependabot` Standalone Template 📦

**PR:** [#633](https://github.com/saif-corp/forge/pull/633)

Extracts Dependabot configuration into a composable, standalone `saif-feature-dependabot` template with per-ecosystem toggles. Dependabot config was previously duplicated across `saif-feature-api` and `saif-nuget-package`.

**Usage:**

```bash
# .NET-only project
dotnet new saif-feature-dependabot --enable_nuget true

# Full-stack project
dotnet new saif-feature-dependabot --enable_nuget true --enable_npm true

# Everything
dotnet new saif-feature-dependabot --enable_nuget true --enable_npm true --enable_docker true --enable_github_actions true
```

**Parameters:**

- `enable_nuget` (default: `true`) — include NuGet ecosystem
- `enable_npm` (default: `false`) — include npm ecosystem
- `enable_docker` (default: `false`) — include Docker ecosystem
- `enable_github_actions` (default: `false`) — include GitHub Actions ecosystem

**Benefits:**

- ✅ Single source of truth — no more copy-paste across templates
- ✅ Standalone installation for existing repos
- ✅ New ecosystems added once, available everywhere

---

### NuGet Packages

#### `DefaultAccessTokenProvider` with Smart Authentication Flow Selection 🔐

**PR:** [#607](https://github.com/saif-corp/forge/pull/607)

Adds `DefaultAccessTokenProvider` that automatically selects the correct authentication flow (OBO, client credentials, or token exchange) based on the incoming token's `idtyp` claim and tenant.

**Package:** `SAIF.Platform.Kiota.HttpClientLibrary`

**Flow selection logic:**

| Token Type | Tenant | Flow |
|---|---|---|
| User token | Corp/Entra | Token Exchange (OBO) |
| App token (`idtyp=app`) | Corp/Entra | Client Credentials |
| Any token | External/Okta | Token Exchange (RFC 8693) |

**New APIs:**

- `DefaultAccessTokenProvider` — inspects `idtyp` claim and delegates to the correct provider
- `ConfigureHttpClient(projectId)` — single-call overload that registers `DefaultAccessTokenProvider` with keyed sub-providers
- `ScopeBuilder.BuildForClientCredentials()` — produces Corp `.default` and External explicit scopes automatically
- `AuthenticationConfiguration.ClientCredentialsScopes` — separate scope set used only by client credentials flow

**Benefits:**

- 🚀 Eliminates the `AADSTS7000114` OBO failure when services receive app tokens
- 🔄 Developers configure named scopes; the platform picks the right scope set per flow
- 🎯 Drop-in simplification via the new `ConfigureHttpClient(projectId)` overload

---

#### Kiota: Expose `HttpClient` Configuration via `OnHttpClientAdded` Callback 🔧

**PR:** [#606](https://github.com/saif-corp/forge/pull/606)

Exposes the underlying `HttpClient` configuration through an `OnHttpClientAdded` callback, giving callers fine-grained control over HTTP client settings without needing to replace the entire client factory.

**Benefits:**

- 🎯 Configure timeouts, headers, or handlers per client without losing platform defaults
- 🔄 Works with existing `ConfigureHttpClient` registrations

---

### Terraform Modules

#### `saif-utilities`: Add `TeamEnvironments` to Naming Module 🏗️

**PR:** [#622](https://github.com/saif-corp/forge/pull/622)

Adds `TeamEnvironments` support to the `saif-utilities` naming module, enabling consistent environment-scoped resource names across team-level infrastructure.

**Benefits:**

- ✅ Consistent naming convention for team-scoped environment resources
- 🔄 Follows existing naming module patterns

---

## 🔧 Enhancements

- **`saif-staticsite-service`**: Replaced inline WAF policy with the `frontdoor_endpoint` module, reducing duplication and aligning with the composable module pattern (#616)

---

## 🐛 Bug Fixes

- **`saif-event-subscriber-service`**: Fixed storage account name and function app name to use `environment_short_name` as prefix, ensuring unique names across environments within Azure's 24-character naming limit (#656)
- **Auth**: Fixed `AADSTS7000114` failure when services receive app tokens from Corp/Entra — `DefaultAccessTokenProvider` now falls back to client credentials flow automatically (#607)

---

## 📚 Documentation

- **Security**: Added `CompoundRoles` section covering AND-based Okta group membership rules for external business roles (#617)

---

## ⚠️ Breaking Changes

None in this release ✅

---

## 📋 Additional Notes

- **Total commits:** 50
- **Contributors:** Emmitt Johnson, Jason Coria Corona Yue

---

### Support

- 📧 Teams Support Channel: [Support](https://teams.microsoft.com/l/channel/19%3Acb611810fb0b42b080cfff5590bdd51c%40thread.tacv2/Support?groupId=514d2dac-2d62-48ce-bf99-0fa0ce39469c&tenantId=a86cb8ed-369b-4df5-ace5-43811f6e08cf)

---
