ai-model-vault 4.2.0

Universal cross-platform XDG-compliant secure vault for AI model formats (Neural and Neurosymbolic)
Documentation
# Cloud Storage Guide

Push and pull vault models to AWS S3 or Azure Blob Storage.

---

## Contents

- [Security model]#security-model
- [Build]#build
- [Command surface]#command-surface
- [AWS S3]#aws-s3
- [Azure Blob Storage]#azure-blob-storage
- [Google Cloud Storage]#google-cloud-storage
- [Library usage]#library-usage
- [Troubleshooting]#troubleshooting

---

## Security model

Read this before pointing `aim` at a bucket.

**`aim cloud push` uploads the decrypted model.** The vault encrypts models
at rest on your local disk, but `push` reads the model back out through the
normal read path — which decrypts and decompresses — and uploads that. The
object that lands in your bucket is the plaintext model file.

Consequences:

| Threat                              | Protected?                                       |
| ----------------------------------- | ------------------------------------------------ |
| Network interception                | Yes — TLS, enforced by both SDKs                  |
| Local disk theft                    | Yes — AES-256-GCM vault encryption                |
| Bucket read by cloud provider / IAM | **No** — unless you enable server-side encryption |
| Misconfigured public bucket         | **No** — the object is readable as-is             |

So: treat the destination bucket as trusted storage. Enable SSE-KMS (S3) or
customer-managed keys (Azure), keep the bucket private, and scope IAM to the
principals that already have vault access. `aim cloud push` prints this
warning at runtime.

An earlier revision of this document claimed uploads were encrypted
client-side and that "cloud providers never see your plaintext models."
That was wrong. If you sized your bucket controls against that claim,
revisit them.

---

## Build

Cloud backends are optional features:

```bash
cargo build --release --features s3       # AWS S3
cargo build --release --features azure    # Azure Blob Storage
cargo build --release --features cloud    # both
```

There is no `gcs` feature — see [Google Cloud Storage](#google-cloud-storage).

A binary built without the relevant feature still accepts the commands; it
prints `⚠️  S3 support not enabled in this build` and exits without doing
anything.

---

## Command surface

Four subcommands under `aim cloud`. There is no persistent "remote"
configuration — the provider and bucket are passed per invocation, and
credentials come from the environment.

```bash
aim cloud push   <MODEL> --provider <s3|azure> --bucket <NAME> [--version N]
aim cloud pull   <MODEL> --provider <s3|azure> --bucket <NAME> --remote-path <KEY>
aim cloud list   --provider <s3|azure> --bucket <NAME> [--prefix <PATH>]
aim cloud config --provider <s3|azure|gcs> [--show]
```

`push` takes the model name positionally and derives the remote key as
`<model>/<format>/v<version>.vault`. Without `--version` it pushes the
latest. `pull` needs the full `--remote-path` key — it does not derive it —
and stores the downloaded bytes as a *new version* in the local vault, so
pulling a model you already have appends rather than replaces.

Both `push` and `pull` prompt for the vault passphrase.

---

## AWS S3

### IAM policy

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::my-model-bucket",
        "arn:aws:s3:::my-model-bucket/*"
      ]
    }
  ]
}
```

`aim` never calls `DeleteObject`; omit it.

### Credentials

Resolved by the standard AWS SDK chain — environment variables, `~/.aws/config`,
SSO, or an instance/task role. No `aim`-specific configuration.

```bash
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_REGION="us-east-1"          # defaults to us-east-1 if unset
```

Note that the backend reads `AWS_REGION`, not `AWS_DEFAULT_REGION`.

Check what is visible to `aim`:

```bash
aim cloud config --provider s3 --show
```

### Usage

```bash
# Push the latest version of gpt-3
aim cloud push gpt-3 --provider s3 --bucket my-model-bucket

# Push a specific version
aim cloud push gpt-3 --version 4 --provider s3 --bucket my-model-bucket

# See what is there
aim cloud list --provider s3 --bucket my-model-bucket --prefix gpt-3/

# Pull it back by full key
aim cloud pull gpt-3 \
    --provider s3 \
    --bucket my-model-bucket \
    --remote-path gpt-3/safetensors/v4.vault
```

### Server-side encryption

Given the security model above, set a bucket default:

```bash
aws s3api put-bucket-encryption \
    --bucket my-model-bucket \
    --server-side-encryption-configuration '{
      "Rules": [{
        "ApplyServerSideEncryptionByDefault": {
          "SSEAlgorithm": "aws:kms",
          "KMSMasterKeyID": "alias/model-vault"
        },
        "BucketKeyEnabled": true
      }]
    }'
```

---

## Azure Blob Storage

Backed by the Azure SDK for Rust v1 (`azure_storage_blob`).

### Credentials

**`AZURE_STORAGE_KEY` is not supported.** The v1 SDK provides no shared-key
credential. If it is set without a SAS token, `aim` fails with an explicit
error rather than silently ignoring it.

Two supported paths, both alongside `AZURE_STORAGE_ACCOUNT`:

**SAS token** — authenticates via the URL itself:

```bash
export AZURE_STORAGE_ACCOUNT="myaccount"
export AZURE_STORAGE_SAS_TOKEN="$(az storage container generate-sas \
    --account-name myaccount --name models \
    --permissions rwdl --expiry 2030-01-01 --output tsv)"
```

**Entra ID** — service principal, managed identity, or `az login`:

```bash
export AZURE_STORAGE_ACCOUNT="myaccount"
export AZURE_TENANT_ID="..."
export AZURE_CLIENT_ID="..."
export AZURE_CLIENT_SECRET="..."
```

Managed identity and developer sign-in are picked up automatically when the
explicit service-principal triple is absent.

```bash
aim cloud config --provider azure --show
```

### Usage

`--bucket` is the container name.

```bash
aim cloud push llama-7b --provider azure --bucket models
aim cloud list --provider azure --bucket models
aim cloud pull llama-7b \
    --provider azure --bucket models \
    --remote-path llama-7b/gguf/v1.vault
```

---

## Google Cloud Storage

**Not available.** GCS support was removed, and there is no `gcs` cargo
feature to enable. The `cloud-storage` crate it depended on carries
unmaintained transitive dependencies (`ring` 0.16, `dotenv`, `instant`).

`aim cloud <cmd> --provider gcs` is accepted by the argument parser and
prints a notice explaining this. Use S3 or Azure.

---

## Library usage

The storage backends are usable directly, and unlike the CLI path you control
what bytes you hand them:

```rust
use ai_model_vault::storage::StorageConfig;

# async fn run() -> ai_model_vault::Result<()> {
let backend = StorageConfig::S3 {
    bucket: "my-model-bucket".to_string(),
    region: "us-east-1".to_string(),
    prefix: Some("production".to_string()),
}
.create_backend()
.await?;

backend.upload("gpt-3/checkpoint-1000", &encrypted_bytes).await?;
let fetched = backend.download("gpt-3/checkpoint-1000").await?;
let keys = backend.list().await?;
# Ok(())
# }
```

`prefix` is honoured by `list`; the CLI always passes `None` for push and
pull and builds the full key itself.

---

## Troubleshooting

**`⚠️  S3 support not enabled in this build`** — rebuild with `--features s3`.

**`AZURE_STORAGE_ACCOUNT env var not set`** — required for every Azure
operation, including `list`.

**`AZURE_STORAGE_KEY (shared key) is no longer supported`** — mint a SAS from
that key, or switch to Entra ID. See above.

**`Unsupported provider: ...`** — only `s3`, `azure`, and `gcs` parse; only
the first two do anything.

**Pull created a duplicate version** — expected. `pull` calls `store_model`,
which appends a new version rather than reconciling with an existing one.

**Region mismatch on S3** — the backend reads `AWS_REGION` and falls back to
`us-east-1`. `AWS_DEFAULT_REGION` is not consulted.

---

See [src/storage.rs](https://github.com/nervosys/AIModelVault/blob/master/src/storage.rs)
and [src/cli/handlers/cloud.rs](https://github.com/nervosys/AIModelVault/blob/master/src/cli/handlers/cloud.rs).