# 3.8.3

**Release Date:** August 7, 2026

---

## 🐛 Bug Fixes

### Terraform Modules

#### Stop Passing Null Network Rule Arguments To The Storage Account Module 🔗

**Module:** `saif-resources/modules/storage`

Fixes a `terraform plan` failure that blocked every application enabling blob storage:

```text
Error: Invalid function argument

  on .terraform/modules/…/modules/storageaccount/variables.tf line 240,
  in variable "network_rules_default_action":
  condition = contains(["Allow", "Deny"], var.network_rules_default_action)

  var.network_rules_default_action is null

Invalid value for "value" parameter: argument must not be null.

Error: Iteration over null value

  on .terraform/modules/…/modules/storageaccount/variables.tf line 252,
  in variable "network_rules_bypass":

  var.network_rules_bypass is null

A null value cannot be used as the collection in a 'for' expression.
```

The module passed `network_rules_default_action` and `network_rules_bypass` conditionally, sending an explicit `null` whenever `network_rules_enabled` was `false`. That looks harmless, but a Terraform `variable` block is `nullable = true` by default, and a value explicitly passed as `null` is **not** replaced by the variable's `default`. The upstream `validation` blocks therefore ran against `null` and failed before the plan could proceed.

This surfaced on every consumer rather than a misconfigured app: `saif-api-service` never sets `network_rules_enabled`, so it fell through to its `false` default and always sent the null pair.

The fix passes concrete values unconditionally — `"Deny"` and `["AzureServices"]`. That is safe because the upstream module already gates the entire block behind `dynamic "network_rules" { for_each = var.network_rules_enabled ? [1] : [] }`, so when network rules are disabled the values are simply never rendered into the resource. A comment now marks the arguments to stop the conditional being reintroduced.

No state migration is needed, and the plan output is unchanged for accounts that already had network rules disabled.

> **Note**
> Storage accounts provisioned by `saif-api-service` still run with `private_endpoint_enabled = false` and no network rules, unlike the web app and Cosmos DB resources alongside them. That gap is tracked separately in [#1003](https://github.com/saif-corp/forge/issues/1003) and is unchanged by this release.

#### Resolve The Blob Storage Connection String From The Module Output 🔗

**Module:** `saif-api-service`

Fixes an application setting that deployed successfully but crashed the app at startup. The setting was hand-built as `ConnectionStrings_BlobStorage` with a single underscore. .NET only translates a **double** underscore into the `:` hierarchy separator, so the value never became `ConnectionStrings:BlobStorage` and `AddAzureBlobClient` found no connection string.

Rather than correct the literal, the module now consumes the storage module's own `app_settings` output, which emits a correctly formed `ConnectionStrings__<name>` key and keeps the two in step automatically.

That output derives its key from `connection_string_name`, which defaults to `storage` in `saif-resources/modules/storage`. Left at the default it would have produced `ConnectionStrings__storage` — a valid setting that still would not match a client resolving `blobstorage`. The module call now pins `connection_string_name = "blobstorage"` explicitly, with a comment tying it to the client registration.

Key casing was never a factor: .NET configuration keys are case-insensitive, so `BlobStorage` and `blobstorage` resolve identically. Only the separator and the name mattered.

The blob storage guide and the `aspire-blobstorage` Foundry example were updated to document the corrected key.

---

## 🔄 Breaking Changes

None in this release ✅

---

## 📋 Additional Notes

- Total commits: 2
- Files changed: 5

---

### 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)

---
