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
112 changes: 92 additions & 20 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ members = [
"crates/buzz-deletion",
"crates/buzz-workflow",
"crates/buzz-media",
"crates/buzz-azure-storage",
"crates/buzz-cli",
"crates/buzz-pairing-cli",
"crates/buzz-sdk",
Expand Down Expand Up @@ -143,6 +144,7 @@ buzz-search = { path = "crates/buzz-search" }
buzz-audit = { path = "crates/buzz-audit" }
buzz-workflow = { path = "crates/buzz-workflow" }
buzz-media = { path = "crates/buzz-media" }
buzz-azure-storage = { path = "crates/buzz-azure-storage" }
buzz-sdk = { path = "crates/buzz-sdk" }
buzz-ws-client = { path = "crates/buzz-ws-client" }
buzz-relay-mesh = { path = "crates/buzz-relay-mesh" }
Expand Down
19 changes: 19 additions & 0 deletions crates/buzz-azure-storage/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "buzz-azure-storage"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Azure Blob Storage adapter and conformance surface for Buzz"

[dependencies]
bytes = "1"
futures-core = "0.3"
futures-util = "0.3"
object_store = { version = "0.14.1", default-features = false, features = ["azure", "tokio"] }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["fs"] }

[dev-dependencies]
uuid = { workspace = true }
49 changes: 49 additions & 0 deletions crates/buzz-azure-storage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Buzz Azure Storage Adapter

This crate is the Azure Blob Storage proof for Buzz's media and git storage
contracts. It intentionally keeps Azure-specific code outside the current S3
paths until the backend passes the required concurrency semantics.

The conformance test covers:

- atomic create-only writes (`If-None-Match: *`),
- ETag compare-and-swap updates (`If-Match`),
- one winner under concurrent create and update races,
- GET body and ETag consistency,
- range reads, streaming reads, HEAD, paginated listing, and idempotent delete,
- bounded multipart file upload with a range-verified large object.

Production clients use Azure's credential environment. On AKS, configure
workload identity with `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and
`AZURE_FEDERATED_TOKEN_FILE`; no storage account key is required.

## Local validation

Run Azurite's blob service on port 10000, create a container named
`buzz-conformance`, and then run:

```shell
BUZZ_AZURITE_TEST=1 cargo test -p buzz-azure-storage --test azurite_conformance
```

## Private Azure validation

Run the same test from an AKS workload-identity Pod that can resolve the private
Blob endpoint. Scope `Storage Blob Data Contributor` to only the disposable
conformance container, then set:

```shell
BUZZ_AZURE_TEST=1 \
BUZZ_AZURE_STORAGE_ACCOUNT=<account> \
BUZZ_AZURE_CONFORMANCE_CONTAINER=buzz-conformance \
cargo test -p buzz-azure-storage --test azurite_conformance
```

The test uses no account key, writes under a unique `probe/<uuid>` prefix, and
deletes that prefix after a successful run. Version restore and soft-delete
recovery are control-plane validations and remain separate from this data-plane
adapter contract.

Azurite is test-only. Production should use a dedicated Buzz storage account,
private endpoint, private DNS zone, workload identity, soft delete, versioning,
and a lifecycle policy.
Loading