docs(devops): update stale mywisprai/MyWisprAI branding across 5 AKV docs
- BytelystAI → ByteLyst in titles - MyWisprAI → LysnrAI (legacy) for wispr-* secret references - Added 'legacy resource name' annotations to Azure resource names (kv-mywisprai, cosmos-mywisprai, etc. cannot be renamed) - Updated dashboard paths (admin-web moved to dashboards/) - Fixed telemetry role name: mywisprai-admin → lysnrai-admin - Updated last-updated dates to 2026-03-21 Files: AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md, AZURE_PORTAL_SETUP.md, AZURE_RESOURCE_INVENTORY.md, ENVIRONMENT_VARIABLES_AND_KEYVAULT_AUDIT.md, END_TO_END_ENCRYPTION_ROADMAP.md
This commit is contained in:
parent
5b2c6f2874
commit
8af997ba0f
@ -1,14 +1,14 @@
|
||||
# BytelystAI — Azure Key Vault & Secrets Rotation
|
||||
# ByteLyst — Azure Key Vault & Secrets Rotation
|
||||
|
||||
> **Purpose:** Centralize all secrets in Azure Key Vault and establish a repeatable rotation process.
|
||||
> **Vault:** `kv-mywisprai` in `rg-mywisprai` (East US)
|
||||
> **Last updated:** 2026-02-15
|
||||
> **Vault:** `kv-mywisprai` in `rg-mywisprai` (East US) — _legacy resource names, not yet renamed_
|
||||
> **Last updated:** 2026-03-21
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
All ByteLyst products (LysnrAI, MindLyst, legacy MyWisprAI) share a **single Key Vault**: `kv-mywisprai`. Secrets are prefixed by product.
|
||||
All ByteLyst products share a **single Key Vault**: `kv-mywisprai` (legacy name). Secrets are prefixed by product (e.g., `lysnr-*`, `mindlyst-*`).
|
||||
|
||||
### Goals
|
||||
|
||||
@ -25,31 +25,32 @@ All ByteLyst products (LysnrAI, MindLyst, legacy MyWisprAI) share a **single Key
|
||||
|
||||
## Current State
|
||||
|
||||
| Product | Prefix | Secrets in KV | Status |
|
||||
|---------|--------|---------------|--------|
|
||||
| **MindLyst** | `mindlyst-*` | 12 | Fully populated |
|
||||
| **MyWisprAI** (legacy) | `wispr-*` | 5 | Legacy desktop secrets |
|
||||
| **LysnrAI** | `lysnr-*` | 13 | ✅ Seeded (2026-02-15) |
|
||||
| Product | Prefix | Secrets in KV | Status |
|
||||
| -------------------- | ------------ | ------------- | ------------------------------------------------------------- |
|
||||
| **LysnrAI** | `lysnr-*` | 13 | ✅ Seeded (2026-02-15) |
|
||||
| **MindLyst** | `mindlyst-*` | 12 | Fully populated |
|
||||
| **LysnrAI (legacy)** | `wispr-*` | 5 | Legacy desktop secrets (pre-rebrand, superseded by `lysnr-*`) |
|
||||
|
||||
**Total secrets:** 30 (12 MindLyst + 5 MyWisprAI + 13 LysnrAI)
|
||||
**Total secrets:** 30 (13 LysnrAI + 12 MindLyst + 5 legacy)
|
||||
|
||||
### Code Integration Status
|
||||
|
||||
All components have AKV resolution implemented:
|
||||
|
||||
| Component | Integration | File |
|
||||
|-----------|------------|------|
|
||||
| platform-service | `resolveKeyVaultSecrets()` at startup | `services/platform-service/src/server.ts` |
|
||||
| extraction-service | `resolveKeyVaultSecrets()` at startup | `services/extraction-service/src/server.ts` |
|
||||
| Admin dashboard | Next.js `instrumentation.ts` hook | `admin-dashboard-web/src/instrumentation.ts` |
|
||||
| User dashboard | Next.js `instrumentation.ts` hook | `user-dashboard-web/src/instrumentation.ts` |
|
||||
| Tracker dashboard | Next.js `instrumentation.ts` hook | `tracker-dashboard-web/src/instrumentation.ts` |
|
||||
| Python backend | `SecretResolver` + pydantic `model_validator` | `backend/src/secrets/keyvault.py` |
|
||||
| Desktop app | `SecretResolver` + pydantic `model_validator` | `src/secrets/keyvault.py` |
|
||||
| Component | Integration | File |
|
||||
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- |
|
||||
| platform-service | `resolveKeyVaultSecrets()` at startup | `services/platform-service/src/server.ts` |
|
||||
| extraction-service | `resolveKeyVaultSecrets()` at startup | `services/extraction-service/src/server.ts` |
|
||||
| Admin dashboard | Next.js `instrumentation.ts` hook | `dashboards/admin-web/src/instrumentation.ts` |
|
||||
| User dashboard | Next.js `instrumentation.ts` hook | `user-dashboard-web/src/instrumentation.ts` (in LysnrAI repo) |
|
||||
| Tracker dashboard | Next.js `instrumentation.ts` hook | `dashboards/tracker-web/src/instrumentation.ts` |
|
||||
| Python backend (LysnrAI) | `SecretResolver` + pydantic `model_validator` | `backend-python/src/secrets/keyvault.py` (in LysnrAI repo) |
|
||||
| Desktop app (LysnrAI) | `SecretResolver` + pydantic `model_validator` | `src/secrets/keyvault.py` (in LysnrAI repo) |
|
||||
|
||||
### Admin Secrets Manager
|
||||
|
||||
The admin dashboard at **`/ops/secrets`** provides live CRUD access to Key Vault:
|
||||
|
||||
- List all secrets with metadata (status, expiry, last updated)
|
||||
- Read secret values (masked, with copy-to-clipboard)
|
||||
- Create new secrets
|
||||
@ -63,48 +64,38 @@ The admin dashboard at **`/ops/secrets`** provides live CRUD access to Key Vault
|
||||
|
||||
### LysnrAI — `lysnr-*` (13 secrets, code in `packages/config/src/keyvault.ts`)
|
||||
|
||||
| KV Secret Name | Env Var | Used By | Priority |
|
||||
|----------------|---------|---------|----------|
|
||||
| `lysnr-cosmos-key` | `COSMOS_KEY` | All services, dashboards | Critical |
|
||||
| `lysnr-cosmos-endpoint` | `COSMOS_ENDPOINT` | All services, dashboards | Critical |
|
||||
| `lysnr-jwt-secret` | `JWT_SECRET` | All services, dashboards | Critical |
|
||||
| `lysnr-stripe-secret-key` | `STRIPE_SECRET_KEY` | platform-service | Critical |
|
||||
| `lysnr-stripe-webhook-secret` | `STRIPE_WEBHOOK_SECRET` | platform-service | Critical |
|
||||
| `lysnr-billing-internal-key` | `BILLING_INTERNAL_KEY` | platform-service | High |
|
||||
| `lysnr-blob-connection-string` | `AZURE_BLOB_CONNECTION_STRING` | platform-service | Critical |
|
||||
| `lysnr-blob-account-key` | `AZURE_BLOB_ACCOUNT_KEY` | platform-service | Critical |
|
||||
| `lysnr-gemini-api-key` | `GEMINI_API_KEY` | extraction-service | Critical |
|
||||
| `lysnr-seed-secret` | `SEED_SECRET` | admin dashboard | Medium |
|
||||
| `lysnr-azure-speech-key` | `AZURE_SPEECH_KEY` | desktop, backend | High |
|
||||
| `lysnr-azure-openai-key` | `AZURE_OPENAI_KEY` | extraction-service | High |
|
||||
| `lysnr-azure-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | extraction-service | High |
|
||||
| KV Secret Name | Env Var | Used By | Priority |
|
||||
| ------------------------------ | ------------------------------ | ------------------------ | -------- |
|
||||
| `lysnr-cosmos-key` | `COSMOS_KEY` | All services, dashboards | Critical |
|
||||
| `lysnr-cosmos-endpoint` | `COSMOS_ENDPOINT` | All services, dashboards | Critical |
|
||||
| `lysnr-jwt-secret` | `JWT_SECRET` | All services, dashboards | Critical |
|
||||
| `lysnr-stripe-secret-key` | `STRIPE_SECRET_KEY` | platform-service | Critical |
|
||||
| `lysnr-stripe-webhook-secret` | `STRIPE_WEBHOOK_SECRET` | platform-service | Critical |
|
||||
| `lysnr-billing-internal-key` | `BILLING_INTERNAL_KEY` | platform-service | High |
|
||||
| `lysnr-blob-connection-string` | `AZURE_BLOB_CONNECTION_STRING` | platform-service | Critical |
|
||||
| `lysnr-blob-account-key` | `AZURE_BLOB_ACCOUNT_KEY` | platform-service | Critical |
|
||||
| `lysnr-gemini-api-key` | `GEMINI_API_KEY` | extraction-service | Critical |
|
||||
| `lysnr-seed-secret` | `SEED_SECRET` | admin dashboard | Medium |
|
||||
| `lysnr-azure-speech-key` | `AZURE_SPEECH_KEY` | desktop, backend | High |
|
||||
| `lysnr-azure-openai-key` | `AZURE_OPENAI_KEY` | extraction-service | High |
|
||||
| `lysnr-azure-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | extraction-service | High |
|
||||
|
||||
### MindLyst — `mindlyst-*` (12 secrets, all populated)
|
||||
|
||||
| KV Secret Name | Env Var | Notes |
|
||||
|----------------|---------|-------|
|
||||
| `mindlyst-cosmos-endpoint` | `COSMOS_ENDPOINT` | Config |
|
||||
| `mindlyst-cosmos-key` | `COSMOS_KEY` | Rotate via key1/key2 |
|
||||
| `mindlyst-cosmos-database` | `COSMOS_DATABASE` | Config (`mindlyst`) |
|
||||
| `mindlyst-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | Config |
|
||||
| `mindlyst-openai-key` | `AZURE_OPENAI_KEY` | Rotate via key1/key2 |
|
||||
| `mindlyst-openai-deployment` | `AZURE_OPENAI_DEPLOYMENT` | Config |
|
||||
| `mindlyst-openai-api-version` | `AZURE_OPENAI_API_VERSION` | Config |
|
||||
| `mindlyst-speech-key` | `AZURE_SPEECH_KEY` | Rotate via key1/key2 |
|
||||
| `mindlyst-speech-region` | `AZURE_SPEECH_REGION` | Config |
|
||||
| `mindlyst-blob-connection-string` | `AZURE_BLOB_CONNECTION_STRING` | Rotate via key1/key2 |
|
||||
| `mindlyst-notification-hub-connection-string` | `ANH_CONNECTION_STRING` | Rotate SAS keys |
|
||||
| `mindlyst-appinsights-connection-string` | `APPLICATIONINSIGHTS_CONNECTION_STRING` | Treat as sensitive |
|
||||
|
||||
### MyWisprAI (legacy) — `wispr-*` (5 secrets)
|
||||
|
||||
| KV Secret Name | Env Var |
|
||||
|----------------|---------|
|
||||
| `wispr-azure-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` |
|
||||
| `wispr-azure-openai-key` | `AZURE_OPENAI_KEY` |
|
||||
| `wispr-azure-openai-deployment` | `AZURE_OPENAI_DEPLOYMENT` |
|
||||
| `wispr-azure-speech-key` | `AZURE_SPEECH_KEY` |
|
||||
| `wispr-azure-speech-region` | `AZURE_SPEECH_REGION` |
|
||||
| KV Secret Name | Env Var | Notes |
|
||||
| --------------------------------------------- | --------------------------------------- | -------------------- |
|
||||
| `mindlyst-cosmos-endpoint` | `COSMOS_ENDPOINT` | Config |
|
||||
| `mindlyst-cosmos-key` | `COSMOS_KEY` | Rotate via key1/key2 |
|
||||
| `mindlyst-cosmos-database` | `COSMOS_DATABASE` | Config (`mindlyst`) |
|
||||
| `mindlyst-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | Config |
|
||||
| `mindlyst-openai-key` | `AZURE_OPENAI_KEY` | Rotate via key1/key2 |
|
||||
| `mindlyst-openai-deployment` | `AZURE_OPENAI_DEPLOYMENT` | Config |
|
||||
| `mindlyst-openai-api-version` | `AZURE_OPENAI_API_VERSION` | Config |
|
||||
| `mindlyst-speech-key` | `AZURE_SPEECH_KEY` | Rotate via key1/key2 |
|
||||
| `mindlyst-speech-region` | `AZURE_SPEECH_REGION` | Config |
|
||||
| `mindlyst-blob-connection-string` | `AZURE_BLOB_CONNECTION_STRING` | Rotate via key1/key2 |
|
||||
| `mindlyst-notification-hub-connection-string` | `ANH_CONNECTION_STRING` | Rotate SAS keys |
|
||||
| `mindlyst-appinsights-connection-string` | `APPLICATIONINSIGHTS_CONNECTION_STRING` | Treat as sensitive |
|
||||
|
||||
---
|
||||
|
||||
@ -112,7 +103,7 @@ The admin dashboard at **`/ops/secrets`** provides live CRUD access to Key Vault
|
||||
|
||||
### 1. Seed LysnrAI Secrets (BLOCKING)
|
||||
|
||||
All 13 `lysnr-*` secrets must be added to `kv-mywisprai`:
|
||||
All 13 `lysnr-*` secrets must be added to the Key Vault:
|
||||
|
||||
```bash
|
||||
# Option A: Use the seed script (reads from .env)
|
||||
@ -123,17 +114,17 @@ cp .env.example .env # fill in real values
|
||||
# Navigate to /ops/secrets → Add Secret for each
|
||||
|
||||
# Option C: Use az cli directly
|
||||
az keyvault secret set --vault-name kv-mywisprai --name lysnr-cosmos-key --value "<value>" -o none
|
||||
az keyvault secret set --vault-name kv-mywisprai --name lysnr-cosmos-key --value "<value>" -o none # vault name is legacy
|
||||
```
|
||||
|
||||
### 2. Rotate Leaked Keys (DEFERRED)
|
||||
|
||||
Secrets have appeared in git history. Rotate after seeding:
|
||||
|
||||
- [ ] Cosmos DB keys (`cosmos-mywisprai`) → update `mindlyst-cosmos-key` + `lysnr-cosmos-key`
|
||||
- [ ] Cosmos DB keys (`cosmos-mywisprai` — legacy name) → update `lysnr-cosmos-key` + `mindlyst-cosmos-key`
|
||||
- [ ] Storage account keys (`bytelystblobs`) → update blob connection strings
|
||||
- [ ] Azure OpenAI keys (`mywisprai-openai-sweden`) → update OpenAI key secrets
|
||||
- [ ] Speech keys (`mywisprai-speech`) → update speech key secrets
|
||||
- [ ] Azure OpenAI keys (`mywisprai-openai-sweden` — legacy name) → update OpenAI key secrets
|
||||
- [ ] Speech keys (`mywisprai-speech` — legacy name) → update speech key secrets
|
||||
- [ ] Notification Hub SAS keys → update `mindlyst-notification-hub-connection-string`
|
||||
|
||||
### 3. Enable KV Diagnostics
|
||||
@ -200,13 +191,13 @@ Supports key1/key2.
|
||||
|
||||
### Recommended Rotation Schedule
|
||||
|
||||
| Secret Type | Frequency | Method |
|
||||
|-------------|-----------|--------|
|
||||
| Cosmos DB keys | Quarterly | Azure Portal → rotate → update KV |
|
||||
| JWT secret | Quarterly | Generate new → update KV → rolling deploy |
|
||||
| Stripe keys | Annually or on breach | Stripe Dashboard → update KV |
|
||||
| API keys (Gemini, OpenAI) | Annually or on breach | Provider portal → update KV |
|
||||
| Blob storage keys | Quarterly | Azure Portal → rotate → update KV |
|
||||
| Secret Type | Frequency | Method |
|
||||
| ------------------------- | --------------------- | ----------------------------------------- |
|
||||
| Cosmos DB keys | Quarterly | Azure Portal → rotate → update KV |
|
||||
| JWT secret | Quarterly | Generate new → update KV → rolling deploy |
|
||||
| Stripe keys | Annually or on breach | Stripe Dashboard → update KV |
|
||||
| API keys (Gemini, OpenAI) | Annually or on breach | Provider portal → update KV |
|
||||
| Blob storage keys | Quarterly | Azure Portal → rotate → update KV |
|
||||
|
||||
---
|
||||
|
||||
@ -227,13 +218,13 @@ Supports key1/key2.
|
||||
|
||||
## Related Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `packages/config/src/keyvault.ts` | `resolveKeyVaultSecrets()` + `LYSNR_SECRETS` constant |
|
||||
| `scripts/seed-keyvault.sh` | Seed KV from `.env` values |
|
||||
| `docs/devops/AZURE_RESOURCE_INVENTORY.md` | Complete Azure resource inventory |
|
||||
| `docs/devops/AZURE_PORTAL_SETUP.md` | Step-by-step provisioning guide |
|
||||
| `docs/devops/ENVIRONMENT_VARIABLES_AND_KEYVAULT_AUDIT.md` | Full env var + KV gap analysis |
|
||||
| File | Purpose |
|
||||
| --------------------------------------------------------- | ----------------------------------------------------- |
|
||||
| `packages/config/src/keyvault.ts` | `resolveKeyVaultSecrets()` + `LYSNR_SECRETS` constant |
|
||||
| `scripts/seed-keyvault.sh` | Seed KV from `.env` values |
|
||||
| `docs/devops/AZURE_RESOURCE_INVENTORY.md` | Complete Azure resource inventory |
|
||||
| `docs/devops/AZURE_PORTAL_SETUP.md` | Step-by-step provisioning guide |
|
||||
| `docs/devops/ENVIRONMENT_VARIABLES_AND_KEYVAULT_AUDIT.md` | Full env var + KV gap analysis |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
# BytelystAI — Azure Portal Setup Guide (Shared Infrastructure)
|
||||
# ByteLyst — Azure Portal Setup Guide (Shared Infrastructure)
|
||||
|
||||
> **Purpose:** Step-by-step instructions to provision and manage Azure infrastructure shared between **LysnrAI** and **MindLyst** under a single resource group.
|
||||
> **Architecture:** Single RG, shared stateless services, separate databases.
|
||||
> **Time estimate:** ~20 minutes (most resources already exist from LysnrAI)
|
||||
> **Prerequisites:** An Azure account with an active subscription
|
||||
> **Last updated:** 2026-02-14
|
||||
> **Last updated:** 2026-03-21
|
||||
>
|
||||
> **Security note (staging):** This document does **not** include secret values. Store secrets in Azure Key Vault (`kv-mywisprai`) and reference them by name (see **MindLyst Environment Variables** and **Key Vault** sections). Rotation is deferred; see `docs/devops/AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md`.
|
||||
> **Security note (staging):** This document does **not** include secret values. Store secrets in Azure Key Vault (`kv-mywisprai` — legacy resource name) and reference them by name (see **MindLyst Environment Variables** and **Key Vault** sections). Rotation is deferred; see `docs/devops/AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md`.
|
||||
>
|
||||
> **Note on Azure resource names:** Many resources below still carry `mywisprai` in their names (e.g., `cosmos-mywisprai`, `kv-mywisprai`). Azure resources **cannot be renamed** after creation. The old names are purely cosmetic and work correctly.
|
||||
|
||||
---
|
||||
|
||||
@ -40,8 +42,8 @@ Both LysnrAI and MindLyst share a **single Azure resource group** with shared st
|
||||
rg-mywisprai/ (1 resource group)
|
||||
│
|
||||
├── cosmos-mywisprai (1 Cosmos DB account — already exists)
|
||||
│ ├── mywisprai (database: 10 containers — existing)
|
||||
│ └── mindlyst (database: 12 containers — MindLyst)
|
||||
│ ├── mywisprai (database: LysnrAI — legacy name, 10 containers)
|
||||
│ └── mindlyst (database: MindLyst, 12 containers)
|
||||
│
|
||||
├── bytelystblobs (1 Storage account — already exists)
|
||||
│ ├── mindlyst-voice ← NEW
|
||||
@ -54,8 +56,9 @@ rg-mywisprai/ (1 resource group)
|
||||
├── mywisprai-speech (1 Speech Service — shared, eastus)
|
||||
│
|
||||
├── kv-mywisprai (1 Key Vault — shared)
|
||||
│ ├── wispr-* (existing secrets)
|
||||
│ └── mindlyst-* (MindLyst secrets) ← NEW
|
||||
│ ├── lysnr-* (LysnrAI secrets)
|
||||
│ ├── wispr-* (LysnrAI legacy secrets, pre-rebrand)
|
||||
│ └── mindlyst-* (MindLyst secrets)
|
||||
│
|
||||
├── lysnnai (1 Notification Hub namespace)
|
||||
│ ├── notificationhub (existing hub)
|
||||
@ -68,21 +71,21 @@ rg-mywisprai/ (1 resource group)
|
||||
|
||||
### Why Share?
|
||||
|
||||
| Concern | Answer |
|
||||
|---------|--------|
|
||||
| **Cost** | Cosmos DB Serverless charges per-RU, not per-account. One account = one endpoint, one key pair, simpler rotation |
|
||||
| **Management** | 1 RG to monitor, 1 cost dashboard, 1 health check |
|
||||
| **Data isolation** | Separate databases within Cosmos = full container-level isolation. Queries can't cross databases |
|
||||
| **Teardown safety** | Delete the `mindlyst` database → LysnrAI data untouched |
|
||||
| **Stateless services** | OpenAI & Speech are stateless — same key serves both apps, no data leakage |
|
||||
| Concern | Answer |
|
||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| **Cost** | Cosmos DB Serverless charges per-RU, not per-account. One account = one endpoint, one key pair, simpler rotation |
|
||||
| **Management** | 1 RG to monitor, 1 cost dashboard, 1 health check |
|
||||
| **Data isolation** | Separate databases within Cosmos = full container-level isolation. Queries can't cross databases |
|
||||
| **Teardown safety** | Delete the `mindlyst` database → LysnrAI data untouched |
|
||||
| **Stateless services** | OpenAI & Speech are stateless — same key serves both apps, no data leakage |
|
||||
|
||||
### What Must Stay Separate
|
||||
|
||||
| Resource | Why |
|
||||
|----------|-----|
|
||||
| **Notification Hub hubs** | Each app has its own APNs certificate and FCM server key |
|
||||
| **Stripe accounts** | Different products, pricing tiers, and webhook endpoints (external, not Azure) |
|
||||
| **Cosmos databases** | Each app gets its own database with its own set of containers |
|
||||
| Resource | Why |
|
||||
| ------------------------- | ------------------------------------------------------------------------------ |
|
||||
| **Notification Hub hubs** | Each app has its own APNs certificate and FCM server key |
|
||||
| **Stripe accounts** | Different products, pricing tiers, and webhook endpoints (external, not Azure) |
|
||||
| **Cosmos databases** | Each app gets its own database with its own set of containers |
|
||||
|
||||
---
|
||||
|
||||
@ -90,20 +93,20 @@ rg-mywisprai/ (1 resource group)
|
||||
|
||||
These resources are **already provisioned** and will be reused by MindLyst:
|
||||
|
||||
| Resource | Azure Name | Region | SKU | Status |
|
||||
|----------|-----------|--------|-----|--------|
|
||||
| **Resource Group** | `rg-mywisprai` | `eastus` | — | Exists |
|
||||
| **Cosmos DB** | `cosmos-mywisprai` | `westus2` | Serverless, NoSQL | Exists — DBs: `mywisprai` (10 containers), `mindlyst` (12 containers) |
|
||||
| **Blob Storage** | `bytelystblobs` | `westus2` | StorageV2, RAGRS | Exists |
|
||||
| **Azure OpenAI** | `mywisprai-openai-sweden` | `swedencentral` | S0 | Exists — deployment: `gpt-4o-mini` |
|
||||
| **Speech Service** | `mywisprai-speech` | `eastus` | F0 | Exists |
|
||||
| **Key Vault** | `kv-mywisprai` | `eastus` | Standard | Exists |
|
||||
| **Notification Hub (namespace)** | `lysnnai` | `eastus` | Free | Exists (hubs: `notificationhub`, `mindlyst-hub`) |
|
||||
| **Application Insights** | `bytelyst-appinsights` | `eastus` | Classic | Exists |
|
||||
| Resource | Azure Name | Region | SKU | Status |
|
||||
| -------------------------------- | ------------------------- | --------------- | ----------------- | ------------------------------------------------------------------------------ |
|
||||
| **Resource Group** | `rg-mywisprai` | `eastus` | — | Exists |
|
||||
| **Cosmos DB** | `cosmos-mywisprai` | `westus2` | Serverless, NoSQL | Exists — DBs: `mywisprai` (LysnrAI, 10 containers), `mindlyst` (12 containers) |
|
||||
| **Blob Storage** | `bytelystblobs` | `westus2` | StorageV2, RAGRS | Exists |
|
||||
| **Azure OpenAI** | `mywisprai-openai-sweden` | `swedencentral` | S0 | Exists — deployment: `gpt-4o-mini` |
|
||||
| **Speech Service** | `mywisprai-speech` | `eastus` | F0 | Exists |
|
||||
| **Key Vault** | `kv-mywisprai` | `eastus` | Standard | Exists |
|
||||
| **Notification Hub (namespace)** | `lysnnai` | `eastus` | Free | Exists (hubs: `notificationhub`, `mindlyst-hub`) |
|
||||
| **Application Insights** | `bytelyst-appinsights` | `eastus` | Classic | Exists |
|
||||
|
||||
### Cosmos DB: Existing LysnrAI database containers (staging)
|
||||
|
||||
Database: `mywisprai` (existing)
|
||||
Database: `mywisprai` (legacy name — this is the LysnrAI database)
|
||||
|
||||
- `api_tokens`
|
||||
- `audit_log`
|
||||
@ -137,7 +140,7 @@ MindLyst secrets (canonical):
|
||||
- `mindlyst-notification-hub-connection-string`
|
||||
- `mindlyst-appinsights-connection-string`
|
||||
|
||||
LysnrAI secrets (existing):
|
||||
LysnrAI secrets (legacy `wispr-*` prefix, pre-rebrand — superseded by `lysnr-*`):
|
||||
|
||||
- `wispr-azure-openai-deployment`
|
||||
- `wispr-azure-openai-endpoint`
|
||||
@ -157,14 +160,14 @@ az keyvault secret list --vault-name kv-mywisprai --query "[].name" -o tsv
|
||||
|
||||
Only these additions are needed — no new accounts to create:
|
||||
|
||||
| Action | Where | What |
|
||||
|--------|-------|------|
|
||||
| **Rename RG (optional)** | Resource Group | Keep `rg-mywisprai` for now. Only move resources if you want a cleaner name. |
|
||||
| **Add database** | Cosmos DB (`cosmos-mywisprai`) | New database `mindlyst` with 12 containers |
|
||||
| **Add blob containers** | Blob Storage (`bytelystblobs`) | 3 new containers: `mindlyst-voice`, `mindlyst-images`, `mindlyst-exports` |
|
||||
| **Add secrets** | Key Vault (`kv-mywisprai`) | 12 secrets with `mindlyst-` prefix (keys + config) |
|
||||
| **Add hub** | Notification Hub namespace (`lysnnai`) | New hub `mindlyst-hub` |
|
||||
| **Create App Insights** | New resource | `bytelyst-appinsights` (shared telemetry) |
|
||||
| Action | Where | What |
|
||||
| ------------------------ | -------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| **Rename RG (optional)** | Resource Group | Keep `rg-mywisprai` for now. Only move resources if you want a cleaner name. |
|
||||
| **Add database** | Cosmos DB (`cosmos-mywisprai`) | New database `mindlyst` with 12 containers |
|
||||
| **Add blob containers** | Blob Storage (`bytelystblobs`) | 3 new containers: `mindlyst-voice`, `mindlyst-images`, `mindlyst-exports` |
|
||||
| **Add secrets** | Key Vault (`kv-mywisprai`) | 12 secrets with `mindlyst-` prefix (keys + config) |
|
||||
| **Add hub** | Notification Hub namespace (`lysnnai`) | New hub `mindlyst-hub` |
|
||||
| **Create App Insights** | New resource | `bytelyst-appinsights` (shared telemetry) |
|
||||
|
||||
### Current Staging State (Completed)
|
||||
|
||||
@ -221,22 +224,23 @@ You should now see both `mywisprai` and `mindlyst` databases in the tree.
|
||||
|
||||
For each container below, right-click the **`mindlyst`** database (or click the `…` menu) → **New Container**:
|
||||
|
||||
| # | Container Name | Partition Key | Purpose |
|
||||
|---|----------------|--------------|---------|
|
||||
| 1 | `users` | `/id` | User accounts and profiles |
|
||||
| 2 | `brains` | `/userId` | User brain configurations (War Room, Home Base, Money Guard, etc.) |
|
||||
| 3 | `brain_templates` | `/id` | Brain Pack gallery templates |
|
||||
| 4 | `memory_items` | `/userId` | All captured memories (text, voice, image, link, email) |
|
||||
| 5 | `actions` | `/memoryItemId` | AI-suggested actions from triage |
|
||||
| 6 | `entities` | `/memoryItemId` | Extracted entities (people, dates, places, amounts) |
|
||||
| 7 | `reflections` | `/userId` | Weekly reflection reports and insights |
|
||||
| 8 | `share_cards` | `/userId` | Generated share cards for social sharing |
|
||||
| 9 | `daily_briefs` | `/userId` | Morning and evening brief content |
|
||||
| 10 | `streaks` | `/userId` | Capture streak tracking and gamification |
|
||||
| 11 | `notification_log` | `/userId` | Push notification delivery log and scheduling |
|
||||
| 12 | `brain_insights` | `/userId` | Cross-brain insight discoveries |
|
||||
| # | Container Name | Partition Key | Purpose |
|
||||
| --- | ------------------ | --------------- | ------------------------------------------------------------------ |
|
||||
| 1 | `users` | `/id` | User accounts and profiles |
|
||||
| 2 | `brains` | `/userId` | User brain configurations (War Room, Home Base, Money Guard, etc.) |
|
||||
| 3 | `brain_templates` | `/id` | Brain Pack gallery templates |
|
||||
| 4 | `memory_items` | `/userId` | All captured memories (text, voice, image, link, email) |
|
||||
| 5 | `actions` | `/memoryItemId` | AI-suggested actions from triage |
|
||||
| 6 | `entities` | `/memoryItemId` | Extracted entities (people, dates, places, amounts) |
|
||||
| 7 | `reflections` | `/userId` | Weekly reflection reports and insights |
|
||||
| 8 | `share_cards` | `/userId` | Generated share cards for social sharing |
|
||||
| 9 | `daily_briefs` | `/userId` | Morning and evening brief content |
|
||||
| 10 | `streaks` | `/userId` | Capture streak tracking and gamification |
|
||||
| 11 | `notification_log` | `/userId` | Push notification delivery log and scheduling |
|
||||
| 12 | `brain_insights` | `/userId` | Cross-brain insight discoveries |
|
||||
|
||||
**For each container:**
|
||||
|
||||
1. Click **New Container**
|
||||
2. **Existing Database:** select `mindlyst` (do NOT create a new database)
|
||||
3. Enter the **Container id** from the table
|
||||
@ -268,13 +272,14 @@ Cosmos connection details are stored in Key Vault:
|
||||
2. Go to **Data storage** → **Containers** (left sidebar)
|
||||
3. Click **+ Container** for each:
|
||||
|
||||
| Container Name | Access Level | Purpose |
|
||||
|----------------|-------------|---------|
|
||||
| `mindlyst-voice` | **Private** | Voice capture recordings (WAV/PCM from STT pipeline) |
|
||||
| `mindlyst-images` | **Private** | Captured photos, screenshots, and OCR source images |
|
||||
| `mindlyst-exports` | **Private** | User data exports (JSON), weekly reflection PDFs |
|
||||
| Container Name | Access Level | Purpose |
|
||||
| ------------------ | ------------ | ---------------------------------------------------- |
|
||||
| `mindlyst-voice` | **Private** | Voice capture recordings (WAV/PCM from STT pipeline) |
|
||||
| `mindlyst-images` | **Private** | Captured photos, screenshots, and OCR source images |
|
||||
| `mindlyst-exports` | **Private** | User data exports (JSON), weekly reflection PDFs |
|
||||
|
||||
For each:
|
||||
|
||||
1. Click **+ Container**
|
||||
2. Enter the **Name** (must be lowercase, no underscores — use hyphens)
|
||||
3. **Anonymous access level:** leave as **Private (no anonymous access)**
|
||||
@ -284,10 +289,10 @@ For each:
|
||||
|
||||
You should now see these MindLyst containers in `bytelystblobs` (plus any other app containers you already had):
|
||||
|
||||
| Container | App |
|
||||
|-----------|-----|
|
||||
| `mindlyst-voice` | MindLyst |
|
||||
| `mindlyst-images` | MindLyst |
|
||||
| Container | App |
|
||||
| ------------------ | -------- |
|
||||
| `mindlyst-voice` | MindLyst |
|
||||
| `mindlyst-images` | MindLyst |
|
||||
| `mindlyst-exports` | MindLyst |
|
||||
|
||||
### Connection details (from Key Vault)
|
||||
@ -345,20 +350,20 @@ Speech connection details are stored in Key Vault:
|
||||
|
||||
MindLyst secrets (canonical):
|
||||
|
||||
| Key Vault secret name | Env var | Notes |
|
||||
|---|---|---|
|
||||
| `mindlyst-cosmos-endpoint` | `COSMOS_ENDPOINT` | Config (ok to store) |
|
||||
| `mindlyst-cosmos-key` | `COSMOS_KEY` | Secret |
|
||||
| `mindlyst-cosmos-database` | `COSMOS_DATABASE` | Config (`mindlyst`) |
|
||||
| `mindlyst-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | Config |
|
||||
| `mindlyst-openai-key` | `AZURE_OPENAI_KEY` | Secret |
|
||||
| `mindlyst-openai-deployment` | `AZURE_OPENAI_DEPLOYMENT` | Config |
|
||||
| `mindlyst-openai-api-version` | `AZURE_OPENAI_API_VERSION` | Config |
|
||||
| `mindlyst-speech-key` | `AZURE_SPEECH_KEY` | Secret |
|
||||
| `mindlyst-speech-region` | `AZURE_SPEECH_REGION` | Config |
|
||||
| `mindlyst-blob-connection-string` | `AZURE_BLOB_CONNECTION_STRING` | Secret (prefer SAS later) |
|
||||
| `mindlyst-notification-hub-connection-string` | `ANH_CONNECTION_STRING` | Secret |
|
||||
| `mindlyst-appinsights-connection-string` | `APPLICATIONINSIGHTS_CONNECTION_STRING` | Treat as sensitive |
|
||||
| Key Vault secret name | Env var | Notes |
|
||||
| --------------------------------------------- | --------------------------------------- | ------------------------- |
|
||||
| `mindlyst-cosmos-endpoint` | `COSMOS_ENDPOINT` | Config (ok to store) |
|
||||
| `mindlyst-cosmos-key` | `COSMOS_KEY` | Secret |
|
||||
| `mindlyst-cosmos-database` | `COSMOS_DATABASE` | Config (`mindlyst`) |
|
||||
| `mindlyst-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | Config |
|
||||
| `mindlyst-openai-key` | `AZURE_OPENAI_KEY` | Secret |
|
||||
| `mindlyst-openai-deployment` | `AZURE_OPENAI_DEPLOYMENT` | Config |
|
||||
| `mindlyst-openai-api-version` | `AZURE_OPENAI_API_VERSION` | Config |
|
||||
| `mindlyst-speech-key` | `AZURE_SPEECH_KEY` | Secret |
|
||||
| `mindlyst-speech-region` | `AZURE_SPEECH_REGION` | Config |
|
||||
| `mindlyst-blob-connection-string` | `AZURE_BLOB_CONNECTION_STRING` | Secret (prefer SAS later) |
|
||||
| `mindlyst-notification-hub-connection-string` | `ANH_CONNECTION_STRING` | Secret |
|
||||
| `mindlyst-appinsights-connection-string` | `APPLICATIONINSIGHTS_CONNECTION_STRING` | Treat as sensitive |
|
||||
|
||||
List what’s currently in the vault:
|
||||
|
||||
@ -368,13 +373,13 @@ az keyvault secret list --vault-name kv-mywisprai --query "[].name" -o tsv
|
||||
|
||||
### Existing LysnrAI secrets (for reference)
|
||||
|
||||
| Secret Name | Notes |
|
||||
|-------------|-------|
|
||||
| `wispr-azure-openai-deployment` | Existing OpenAI deployment name |
|
||||
| `wispr-azure-openai-endpoint` | Existing OpenAI endpoint |
|
||||
| `wispr-azure-openai-key` | Existing OpenAI key |
|
||||
| `wispr-azure-speech-key` | Existing Speech key |
|
||||
| `wispr-azure-speech-region` | Existing Speech region |
|
||||
| Secret Name | Notes |
|
||||
| ------------------------------- | ---------------------------------------------- |
|
||||
| `wispr-azure-openai-deployment` | Legacy (pre-rebrand) — superseded by `lysnr-*` |
|
||||
| `wispr-azure-openai-endpoint` | Legacy (pre-rebrand) |
|
||||
| `wispr-azure-openai-key` | Legacy (pre-rebrand) |
|
||||
| `wispr-azure-speech-key` | Legacy (pre-rebrand) |
|
||||
| `wispr-azure-speech-region` | Legacy (pre-rebrand) |
|
||||
|
||||
---
|
||||
|
||||
@ -435,6 +440,7 @@ Non-secret config:
|
||||
### Create (if not exists)
|
||||
|
||||
Option A: Workspace-based (recommended)
|
||||
|
||||
1. Search **"Application Insights"** → click **Create**
|
||||
2. Fill in:
|
||||
- **Resource group:** `rg-mywisprai`
|
||||
@ -460,10 +466,10 @@ In your application code, add a custom property to every trace:
|
||||
|
||||
```typescript
|
||||
// MindLyst
|
||||
telemetryClient.context.tags["ai.cloud.role"] = "mindlyst-web";
|
||||
telemetryClient.context.tags['ai.cloud.role'] = 'mindlyst-web';
|
||||
|
||||
// LysnrAI
|
||||
telemetryClient.context.tags["ai.cloud.role"] = "mywisprai-admin";
|
||||
telemetryClient.context.tags['ai.cloud.role'] = 'lysnrai-admin';
|
||||
```
|
||||
|
||||
Then filter in the Azure Portal: **Application Insights → Logs → `where cloud_RoleName == "mindlyst-web"`**
|
||||
@ -549,16 +555,16 @@ EOF
|
||||
|
||||
After completing all steps, verify:
|
||||
|
||||
| # | Check | How |
|
||||
|---|-------|-----|
|
||||
| 1 | **Cosmos DB: `mindlyst` database** | Data Explorer → expand `cosmos-mywisprai` → `mindlyst` → 12 containers visible |
|
||||
| 2 | **Cosmos DB: `mywisprai` untouched** | Data Explorer → `mywisprai` database still has its existing containers |
|
||||
| 3 | **Blob: 3 new containers** | Storage → `bytelystblobs` → Containers → `mindlyst-voice`, `mindlyst-images`, `mindlyst-exports` |
|
||||
| 4 | **Blob: other containers intact (if any)** | Same page → any pre-existing containers should still be present |
|
||||
| 5 | **OpenAI deployment** | Azure OpenAI Studio → Deployments → `gpt-4o-mini` listed |
|
||||
| 6 | **Speech Service keys** | Speech resource → Keys and Endpoint → keys visible |
|
||||
| 7 | **Key Vault: MindLyst secrets** | Key Vault → Secrets → `mindlyst-*` entries visible |
|
||||
| 8 | **MindLyst web connects** | Run `cd mindlyst-native/web && npm run dev` → triage/brain-chat should use Azure OpenAI (not mock) |
|
||||
| # | Check | How |
|
||||
| --- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
||||
| 1 | **Cosmos DB: `mindlyst` database** | Data Explorer → expand `cosmos-mywisprai` → `mindlyst` → 12 containers visible |
|
||||
| 2 | **Cosmos DB: `mywisprai` (LysnrAI) untouched** | Data Explorer → `mywisprai` database still has its existing containers |
|
||||
| 3 | **Blob: 3 new containers** | Storage → `bytelystblobs` → Containers → `mindlyst-voice`, `mindlyst-images`, `mindlyst-exports` |
|
||||
| 4 | **Blob: other containers intact (if any)** | Same page → any pre-existing containers should still be present |
|
||||
| 5 | **OpenAI deployment** | Azure OpenAI Studio → Deployments → `gpt-4o-mini` listed |
|
||||
| 6 | **Speech Service keys** | Speech resource → Keys and Endpoint → keys visible |
|
||||
| 7 | **Key Vault: MindLyst secrets** | Key Vault → Secrets → `mindlyst-*` entries visible |
|
||||
| 8 | **MindLyst web connects** | Run `cd mindlyst-native/web && npm run dev` → triage/brain-chat should use Azure OpenAI (not mock) |
|
||||
|
||||
---
|
||||
|
||||
@ -566,16 +572,16 @@ After completing all steps, verify:
|
||||
|
||||
### Combined Cost (LysnrAI + MindLyst, MVP / Low Usage)
|
||||
|
||||
| Service | Pricing | LysnrAI | MindLyst | Combined |
|
||||
|---------|---------|---------|----------|----------|
|
||||
| Cosmos DB (Serverless) | $0.25/M RU + $0.25/GB | ~$2 | ~$2 | ~$4 |
|
||||
| Blob Storage (LRS) | $0.018/GB | ~$0.10 | ~$0.10 | ~$0.20 |
|
||||
| Azure OpenAI (GPT-4o-mini) | $0.15/M input + $0.60/M output | ~$5 | ~$5 | ~$10 |
|
||||
| Speech (F0 free) | 5h STT free | $0 | $0 | $0 |
|
||||
| Key Vault | $0.03/10K ops | ~$0.03 | ~$0.03 | ~$0.06 |
|
||||
| App Insights | 5GB/month free | $0 | $0 | $0 |
|
||||
| Notification Hub (Free) | 1M pushes/month free | $0 | $0 | $0 |
|
||||
| **Total** | | | | **~$5–15/month** |
|
||||
| Service | Pricing | LysnrAI | MindLyst | Combined |
|
||||
| -------------------------- | ------------------------------ | ------- | -------- | ---------------- |
|
||||
| Cosmos DB (Serverless) | $0.25/M RU + $0.25/GB | ~$2 | ~$2 | ~$4 |
|
||||
| Blob Storage (LRS) | $0.018/GB | ~$0.10 | ~$0.10 | ~$0.20 |
|
||||
| Azure OpenAI (GPT-4o-mini) | $0.15/M input + $0.60/M output | ~$5 | ~$5 | ~$10 |
|
||||
| Speech (F0 free) | 5h STT free | $0 | $0 | $0 |
|
||||
| Key Vault | $0.03/10K ops | ~$0.03 | ~$0.03 | ~$0.06 |
|
||||
| App Insights | 5GB/month free | $0 | $0 | $0 |
|
||||
| Notification Hub (Free) | 1M pushes/month free | $0 | $0 | $0 |
|
||||
| **Total** | | | | **~$5–15/month** |
|
||||
|
||||
### Cost Savings from Sharing
|
||||
|
||||
@ -589,16 +595,16 @@ After completing all steps, verify:
|
||||
|
||||
## Resource Naming Convention
|
||||
|
||||
| Azure Resource | Current Name | Ideal Name | Notes |
|
||||
|---------------|-------------|------------|-------|
|
||||
| Resource Group | `rg-mywisprai` | `rg-bytelyst` | Move resources to new RG (Step 1) |
|
||||
| Cosmos DB Account | `cosmos-mywisprai` | `cosmos-bytelyst` | Can't rename — keep as-is |
|
||||
| Blob Storage | `bytelystblobs` | `bytelystblobs` | Already brand-neutral |
|
||||
| Azure OpenAI | `mywisprai-openai-sweden` | — | Can't rename — keep as-is |
|
||||
| Speech Service | `mywisprai-speech` | — | Can't rename — keep as-is |
|
||||
| Key Vault | `kv-mywisprai` | `kv-bytelyst` | Can't rename — keep as-is |
|
||||
| Notification Hub NS | `lysnnai` | `bytelyst-hub-ns` | Consider creating new NS later if desired |
|
||||
| App Insights | `bytelyst-appinsights` | — | Can recreate if you want workspace-based mode |
|
||||
| Azure Resource | Current Name | Ideal Name | Notes |
|
||||
| ------------------- | ------------------------- | ----------------- | --------------------------------------------- |
|
||||
| Resource Group | `rg-mywisprai` | `rg-bytelyst` | Move resources to new RG (Step 1) |
|
||||
| Cosmos DB Account | `cosmos-mywisprai` | `cosmos-bytelyst` | Can't rename — keep as-is |
|
||||
| Blob Storage | `bytelystblobs` | `bytelystblobs` | Already brand-neutral |
|
||||
| Azure OpenAI | `mywisprai-openai-sweden` | — | Can't rename — keep as-is |
|
||||
| Speech Service | `mywisprai-speech` | — | Can't rename — keep as-is |
|
||||
| Key Vault | `kv-mywisprai` | `kv-bytelyst` | Can't rename — keep as-is |
|
||||
| Notification Hub NS | `lysnnai` | `bytelyst-hub-ns` | Consider creating new NS later if desired |
|
||||
| App Insights | `bytelyst-appinsights` | — | Can recreate if you want workspace-based mode |
|
||||
|
||||
> **Azure resources cannot be renamed after creation.** The old names (`cosmos-mywisprai`, `mywisprai-*`, etc.) still work perfectly — they're just cosmetic. Only the RG can be "renamed" by moving resources to a new one.
|
||||
|
||||
@ -614,7 +620,7 @@ After completing all steps, verify:
|
||||
set -euo pipefail
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# BytelystAI — Azure Resource Setup Script
|
||||
# ByteLyst — Azure Resource Setup Script
|
||||
# Creates MindLyst deltas inside an existing shared resource group
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
||||
@ -860,19 +866,19 @@ az deployment sub create \
|
||||
|
||||
Use this mapping to understand how the current staging resource names relate to Bicep params. In a **different account**, you must choose new globally-unique names for most of these.
|
||||
|
||||
| Bicep parameter | Current staging value | Notes |
|
||||
|---|---|---|
|
||||
| `resourceGroupName` | `rg-mywisprai` | In a new subscription, choose a new RG name (example: `rg-bytelyst-staging`) |
|
||||
| `cosmosAccountName` | `cosmos-mywisprai` | Globally unique; must change in another subscription |
|
||||
| `storageAccountName` | `bytelystblobs` | Globally unique; must change in another subscription |
|
||||
| `openAiAccountName` | `mywisprai-openai-sweden` | Globally unique; must change in another subscription |
|
||||
| `speechAccountName` | `mywisprai-speech` | Globally unique; must change in another subscription |
|
||||
| `keyVaultName` | `kv-mywisprai` | Globally unique; must change in another subscription |
|
||||
| `notificationHubNamespaceName` | `lysnnai` | Globally unique; must change in another subscription |
|
||||
| `mindlystHubName` | `mindlyst-hub` | Not globally unique (scoped to the namespace) |
|
||||
| `appInsightsName` | `bytelyst-appinsights` | Must be unique within the RG |
|
||||
| `createMywispraiDatabase` | N/A | Creates an empty `mywisprai` database placeholder (no containers) |
|
||||
| `deployerObjectId` | N/A | If set, Bicep also creates Key Vault secrets (`mindlyst-*`) |
|
||||
| Bicep parameter | Current staging value | Notes |
|
||||
| ------------------------------ | ------------------------- | ---------------------------------------------------------------------------- |
|
||||
| `resourceGroupName` | `rg-mywisprai` | In a new subscription, choose a new RG name (example: `rg-bytelyst-staging`) |
|
||||
| `cosmosAccountName` | `cosmos-mywisprai` | Globally unique; must change in another subscription |
|
||||
| `storageAccountName` | `bytelystblobs` | Globally unique; must change in another subscription |
|
||||
| `openAiAccountName` | `mywisprai-openai-sweden` | Globally unique; must change in another subscription |
|
||||
| `speechAccountName` | `mywisprai-speech` | Globally unique; must change in another subscription |
|
||||
| `keyVaultName` | `kv-mywisprai` | Globally unique; must change in another subscription |
|
||||
| `notificationHubNamespaceName` | `lysnnai` | Globally unique; must change in another subscription |
|
||||
| `mindlystHubName` | `mindlyst-hub` | Not globally unique (scoped to the namespace) |
|
||||
| `appInsightsName` | `bytelyst-appinsights` | Must be unique within the RG |
|
||||
| `createMywispraiDatabase` | N/A | Creates an empty `mywisprai` database placeholder (LysnrAI, no containers) |
|
||||
| `deployerObjectId` | N/A | If set, Bicep also creates Key Vault secrets (`mindlyst-*`) |
|
||||
|
||||
---
|
||||
|
||||
@ -892,6 +898,7 @@ Phase 0.3 (Azure Infrastructure):
|
||||
```
|
||||
|
||||
**Next steps after provisioning:**
|
||||
|
||||
1. (Done) MindLyst web: Enable Azure OpenAI triage + brain-chat (`OPENAI_PROVIDER=azure` + `AZURE_OPENAI_*`)
|
||||
2. (Done) MindLyst web: Cosmos persistence for `/api/memory` and `/api/brains` (`COSMOS_*`)
|
||||
3. Wire additional MindLyst API routes to Cosmos as needed (reflections, briefs, notifications, etc.)
|
||||
@ -903,14 +910,14 @@ Phase 0.3 (Azure Infrastructure):
|
||||
|
||||
## Quick Reference: Portal URLs
|
||||
|
||||
| Resource | Direct Link |
|
||||
|----------|-------------|
|
||||
| Resource Group | `portal.azure.com → Resource groups → rg-mywisprai` |
|
||||
| Cosmos DB Data Explorer | `portal.azure.com → cosmos-mywisprai → Data Explorer` |
|
||||
| Blob Containers | `portal.azure.com → bytelystblobs → Containers` |
|
||||
| OpenAI Studio | `oai.azure.com` → select `mywisprai-openai-sweden` |
|
||||
| Speech Keys | `portal.azure.com → mywisprai-speech → Keys and Endpoint` |
|
||||
| Key Vault Secrets | `portal.azure.com → kv-mywisprai → Secrets` |
|
||||
| Resource | Direct Link |
|
||||
| ----------------------- | --------------------------------------------------------- |
|
||||
| Resource Group | `portal.azure.com → Resource groups → rg-mywisprai` |
|
||||
| Cosmos DB Data Explorer | `portal.azure.com → cosmos-mywisprai → Data Explorer` |
|
||||
| Blob Containers | `portal.azure.com → bytelystblobs → Containers` |
|
||||
| OpenAI Studio | `oai.azure.com` → select `mywisprai-openai-sweden` |
|
||||
| Speech Keys | `portal.azure.com → mywisprai-speech → Keys and Endpoint` |
|
||||
| Key Vault Secrets | `portal.azure.com → kv-mywisprai → Secrets` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -1,31 +1,33 @@
|
||||
# Azure Resource Inventory
|
||||
|
||||
> **Last Updated:** 2026-02-14
|
||||
> **Purpose:** Complete inventory of Azure resources for ByteLyst AI products
|
||||
> **Last Updated:** 2026-03-21
|
||||
> **Purpose:** Complete inventory of Azure resources for ByteLyst products
|
||||
>
|
||||
> **Note:** Many resources carry `mywisprai` in their names (pre-rebrand). Azure resources cannot be renamed after creation. These names are cosmetic and work correctly.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Subscription Details
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Subscription Name** | Azure subscription 1 |
|
||||
| **Subscription ID** | `0e0ceaea-2677-4097-9401-1102707db826` |
|
||||
| **Tenant** | eScube |
|
||||
| **Tenant Domain** | saravanakumardblive.onmicrosoft.com |
|
||||
| **Tenant ID** | `ab33246e-c9c9-4cb9-9a87-3616bb4920f0` |
|
||||
| **Account** | saravanakumardb@live.com |
|
||||
| **Environment** | AzureCloud |
|
||||
| **State** | Enabled |
|
||||
| Property | Value |
|
||||
| --------------------- | -------------------------------------- |
|
||||
| **Subscription Name** | Azure subscription 1 |
|
||||
| **Subscription ID** | `0e0ceaea-2677-4097-9401-1102707db826` |
|
||||
| **Tenant** | eScube |
|
||||
| **Tenant Domain** | saravanakumardblive.onmicrosoft.com |
|
||||
| **Tenant ID** | `ab33246e-c9c9-4cb9-9a87-3616bb4920f0` |
|
||||
| **Account** | saravanakumardb@live.com |
|
||||
| **Environment** | AzureCloud |
|
||||
| **State** | Enabled |
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Resource Groups
|
||||
|
||||
| Resource Group | Location | Status | Managed By | Type |
|
||||
|---------------|----------|---------|------------|------|
|
||||
| **rg-mywisprai** | East US | Succeeded | - | Primary resource group |
|
||||
| **ai_bytelyst-appinsights_533a81a0-d1e6-4b01-935a-67dd49a218da_managed** | East US | Succeeded | Application Insights | Auto-managed |
|
||||
| Resource Group | Location | Status | Managed By | Type |
|
||||
| ------------------------------------------------------------------------ | -------- | --------- | -------------------- | ---------------------- |
|
||||
| **rg-mywisprai** | East US | Succeeded | - | Primary resource group |
|
||||
| **ai_bytelyst-appinsights_533a81a0-d1e6-4b01-935a-67dd49a218da_managed** | East US | Succeeded | Application Insights | Auto-managed |
|
||||
|
||||
---
|
||||
|
||||
@ -36,26 +38,28 @@
|
||||
#### Resource Group: `rg-mywisprai` (East US)
|
||||
|
||||
##### 🗄️ **Cosmos DB** - Database Account
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Name** | cosmos-mywisprai |
|
||||
| **Type** | Microsoft.DocumentDb/databaseAccounts |
|
||||
| **Location** | West US 2 |
|
||||
| **Kind** | GlobalDocumentDB (SQL API) |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-09 |
|
||||
| **Workload Type** | Development/Testing |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.DocumentDb/databaseAccounts/cosmos-mywisprai` |
|
||||
|
||||
| Property | Value |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | cosmos-mywisprai |
|
||||
| **Type** | Microsoft.DocumentDb/databaseAccounts |
|
||||
| **Location** | West US 2 |
|
||||
| **Kind** | GlobalDocumentDB (SQL API) |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-09 |
|
||||
| **Workload Type** | Development/Testing |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.DocumentDb/databaseAccounts/cosmos-mywisprai` |
|
||||
|
||||
**📦 Databases & Containers:**
|
||||
|
||||
| Database | Containers | Purpose |
|
||||
|----------|-----------|---------|
|
||||
| **mindlyst** | • streaks<br>• users<br>• brain_insights<br>• brain_templates<br>• daily_briefs<br>• memory_items<br>• notification_log<br>• brains<br>• actions<br>• entities<br>• share_cards<br>• reflections | MindLyst product data |
|
||||
| **lysnrai** | • subscriptions<br>• notification_prefs<br>• licenses<br>• tracker_votes<br>• feature_flags<br>• payments<br>• tracker_items<br>• audit_log<br>• invitation_codes<br>• devices<br>• usage_daily<br>• tracker_comments<br>• referrals<br>• plans<br>• users | LysnrAI product + platform services |
|
||||
| **mywisprai** | • licenses<br>• api_tokens<br>• transcripts<br>• audit_log<br>• subscriptions<br>• usage_daily<br>• users<br>• settings<br>• payments<br>• devices | MyWisprAI product data |
|
||||
| Database | Containers | Purpose |
|
||||
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
|
||||
| **mindlyst** | • streaks<br>• users<br>• brain_insights<br>• brain_templates<br>• daily_briefs<br>• memory_items<br>• notification_log<br>• brains<br>• actions<br>• entities<br>• share_cards<br>• reflections | MindLyst product data |
|
||||
| **lysnrai** | • subscriptions<br>• notification_prefs<br>• licenses<br>• tracker_votes<br>• feature_flags<br>• payments<br>• tracker_items<br>• audit_log<br>• invitation_codes<br>• devices<br>• usage_daily<br>• tracker_comments<br>• referrals<br>• plans<br>• users | LysnrAI product + platform services |
|
||||
| **mywisprai** | • licenses<br>• api_tokens<br>• transcripts<br>• audit_log<br>• subscriptions<br>• usage_daily<br>• users<br>• settings<br>• payments<br>• devices | LysnrAI legacy data (pre-rebrand database name) |
|
||||
|
||||
**🔑 Key Environment Variables:**
|
||||
|
||||
```bash
|
||||
COSMOS_ENDPOINT=https://cosmos-mywisprai.documents.azure.com:443/
|
||||
COSMOS_DATABASE=lysnrai # or mindlyst/mywisprai depending on product
|
||||
@ -64,20 +68,22 @@ COSMOS_DATABASE=lysnrai # or mindlyst/mywisprai depending on product
|
||||
---
|
||||
|
||||
##### 💾 **Storage Account** - Blob Storage
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Name** | bytelystblobs |
|
||||
| **Type** | Microsoft.Storage/storageAccounts |
|
||||
| **Location** | West US 2 (Primary) |
|
||||
| **Secondary Location** | West Central US |
|
||||
| **Kind** | StorageV2 |
|
||||
| **SKU** | Standard_RAGRS (Geo-redundant) |
|
||||
| **Access Tier** | Cool |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-12 |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.Storage/storageAccounts/bytelystblobs` |
|
||||
|
||||
| Property | Value |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | bytelystblobs |
|
||||
| **Type** | Microsoft.Storage/storageAccounts |
|
||||
| **Location** | West US 2 (Primary) |
|
||||
| **Secondary Location** | West Central US |
|
||||
| **Kind** | StorageV2 |
|
||||
| **SKU** | Standard_RAGRS (Geo-redundant) |
|
||||
| **Access Tier** | Cool |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-12 |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.Storage/storageAccounts/bytelystblobs` |
|
||||
|
||||
**🔑 Key Environment Variables:**
|
||||
|
||||
```bash
|
||||
AZURE_BLOB_ACCOUNT_NAME=bytelystblobs
|
||||
AZURE_BLOB_CONNECTION_STRING=<from-portal>
|
||||
@ -86,45 +92,50 @@ AZURE_BLOB_CONNECTION_STRING=<from-portal>
|
||||
---
|
||||
|
||||
##### 🔐 **Key Vault**
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Name** | kv-mywisprai |
|
||||
| **Type** | Microsoft.KeyVault/vaults |
|
||||
| **Location** | East US |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-07 |
|
||||
|
||||
| Property | Value |
|
||||
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | kv-mywisprai |
|
||||
| **Type** | Microsoft.KeyVault/vaults |
|
||||
| **Location** | East US |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-07 |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.KeyVault/vaults/kv-mywisprai` |
|
||||
|
||||
**🔑 Key Environment Variables:**
|
||||
|
||||
```bash
|
||||
AZURE_KEYVAULT_URL=https://kv-mywisprai.vault.azure.net/
|
||||
```
|
||||
|
||||
**📝 Usage in Code:**
|
||||
|
||||
- See: `packages/config/src/keyvault.ts`
|
||||
- See: `scripts/seed-keyvault.sh`
|
||||
|
||||
---
|
||||
|
||||
##### 🧠 **Azure OpenAI Service**
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Name** | mywisprai-openai-sweden |
|
||||
| **Type** | Microsoft.CognitiveServices/accounts |
|
||||
| **Kind** | OpenAI |
|
||||
| **Location** | Sweden Central |
|
||||
| **SKU** | S0 (Standard) |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-07 |
|
||||
|
||||
| Property | Value |
|
||||
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | mywisprai-openai-sweden |
|
||||
| **Type** | Microsoft.CognitiveServices/accounts |
|
||||
| **Kind** | OpenAI |
|
||||
| **Location** | Sweden Central |
|
||||
| **SKU** | S0 (Standard) |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-07 |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.CognitiveServices/accounts/mywisprai-openai-sweden` |
|
||||
|
||||
**🚀 Model Deployments:**
|
||||
|
||||
| Deployment Name | Model | Version | Capacity |
|
||||
|----------------|-------|---------|----------|
|
||||
| gpt-4o-mini | gpt-4o-mini | 2024-07-18 | 1 TPM |
|
||||
| Deployment Name | Model | Version | Capacity |
|
||||
| --------------- | ----------- | ---------- | -------- |
|
||||
| gpt-4o-mini | gpt-4o-mini | 2024-07-18 | 1 TPM |
|
||||
|
||||
**🔑 Key Environment Variables:**
|
||||
|
||||
```bash
|
||||
AZURE_OPENAI_ENDPOINT=https://mywisprai-openai-sweden.openai.azure.com/
|
||||
AZURE_OPENAI_API_KEY=<from-keyvault-or-portal>
|
||||
@ -134,18 +145,20 @@ AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4o-mini
|
||||
---
|
||||
|
||||
##### 🎤 **Speech Services**
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Name** | mywisprai-speech |
|
||||
| **Type** | Microsoft.CognitiveServices/accounts |
|
||||
| **Kind** | SpeechServices |
|
||||
| **Location** | East US |
|
||||
| **SKU** | F0 (Free Tier) |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-07 |
|
||||
|
||||
| Property | Value |
|
||||
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | mywisprai-speech |
|
||||
| **Type** | Microsoft.CognitiveServices/accounts |
|
||||
| **Kind** | SpeechServices |
|
||||
| **Location** | East US |
|
||||
| **SKU** | F0 (Free Tier) |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-07 |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.CognitiveServices/accounts/mywisprai-speech` |
|
||||
|
||||
**🔑 Key Environment Variables:**
|
||||
|
||||
```bash
|
||||
AZURE_SPEECH_KEY=<from-portal>
|
||||
AZURE_SPEECH_REGION=eastus
|
||||
@ -154,24 +167,26 @@ AZURE_SPEECH_REGION=eastus
|
||||
---
|
||||
|
||||
##### 🔔 **Notification Hubs** - Push Notification Service
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Namespace** | lysnnai |
|
||||
| **Type** | Microsoft.NotificationHubs/namespaces |
|
||||
| **Location** | East US |
|
||||
| **SKU** | Free |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-12 |
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Namespace** | lysnnai |
|
||||
| **Type** | Microsoft.NotificationHubs/namespaces |
|
||||
| **Location** | East US |
|
||||
| **SKU** | Free |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-12 |
|
||||
| **Namespace ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.NotificationHubs/namespaces/lysnnai` |
|
||||
|
||||
**📱 Notification Hubs:**
|
||||
|
||||
| Hub Name | Purpose | Created |
|
||||
|----------|---------|---------|
|
||||
| **notificationhub** | General notifications | 2026-02-12 |
|
||||
| **mindlyst-hub** | MindLyst product notifications | 2026-02-13 |
|
||||
| Hub Name | Purpose | Created |
|
||||
| ------------------- | ------------------------------ | ---------- |
|
||||
| **notificationhub** | General notifications | 2026-02-12 |
|
||||
| **mindlyst-hub** | MindLyst product notifications | 2026-02-13 |
|
||||
|
||||
**🔑 Key Environment Variables:**
|
||||
|
||||
```bash
|
||||
AZURE_NH_CONNECTION_STRING=<from-portal>
|
||||
AZURE_NH_HUB_NAME=mindlyst-hub # or notificationhub
|
||||
@ -180,20 +195,23 @@ AZURE_NH_HUB_NAME=mindlyst-hub # or notificationhub
|
||||
---
|
||||
|
||||
##### 📊 **Application Insights** - Monitoring & Telemetry
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Name** | bytelyst-appinsights |
|
||||
| **Type** | Microsoft.Insights/components |
|
||||
| **Kind** | web |
|
||||
| **Location** | East US |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-13 |
|
||||
|
||||
| Property | Value |
|
||||
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | bytelyst-appinsights |
|
||||
| **Type** | Microsoft.Insights/components |
|
||||
| **Kind** | web |
|
||||
| **Location** | East US |
|
||||
| **Status** | Succeeded |
|
||||
| **Created** | 2026-02-13 |
|
||||
| **Resource ID** | `/subscriptions/0e0ceaea-2677-4097-9401-1102707db826/resourceGroups/rg-mywisprai/providers/Microsoft.Insights/components/bytelyst-appinsights` |
|
||||
|
||||
**🔔 Action Groups:**
|
||||
|
||||
- **Application Insights Smart Detection** (Global)
|
||||
|
||||
**🔑 Key Environment Variables:**
|
||||
|
||||
```bash
|
||||
APPLICATIONINSIGHTS_CONNECTION_STRING=<from-portal>
|
||||
APPINSIGHTS_INSTRUMENTATIONKEY=<from-portal>
|
||||
@ -203,18 +221,18 @@ APPINSIGHTS_INSTRUMENTATIONKEY=<from-portal>
|
||||
|
||||
## 📦 Resource Summary by Type
|
||||
|
||||
| Resource Type | Count | Names |
|
||||
|--------------|-------|-------|
|
||||
| **Cosmos DB Accounts** | 1 | cosmos-mywisprai |
|
||||
| **Cosmos DB Databases** | 3 | mindlyst, lysnrai, mywisprai |
|
||||
| **Storage Accounts** | 1 | bytelystblobs |
|
||||
| **Key Vaults** | 1 | kv-mywisprai |
|
||||
| **Cognitive Services (OpenAI)** | 1 | mywisprai-openai-sweden |
|
||||
| **Cognitive Services (Speech)** | 1 | mywisprai-speech |
|
||||
| **Notification Hub Namespaces** | 1 | lysnnai |
|
||||
| **Notification Hubs** | 2 | notificationhub, mindlyst-hub |
|
||||
| **Application Insights** | 1 | bytelyst-appinsights |
|
||||
| **Action Groups** | 1 | Application Insights Smart Detection |
|
||||
| Resource Type | Count | Names |
|
||||
| ------------------------------- | ----- | ------------------------------------- |
|
||||
| **Cosmos DB Accounts** | 1 | cosmos-mywisprai |
|
||||
| **Cosmos DB Databases** | 3 | mindlyst, lysnrai, mywisprai (legacy) |
|
||||
| **Storage Accounts** | 1 | bytelystblobs |
|
||||
| **Key Vaults** | 1 | kv-mywisprai |
|
||||
| **Cognitive Services (OpenAI)** | 1 | mywisprai-openai-sweden |
|
||||
| **Cognitive Services (Speech)** | 1 | mywisprai-speech |
|
||||
| **Notification Hub Namespaces** | 1 | lysnnai |
|
||||
| **Notification Hubs** | 2 | notificationhub, mindlyst-hub |
|
||||
| **Application Insights** | 1 | bytelyst-appinsights |
|
||||
| **Action Groups** | 1 | Application Insights Smart Detection |
|
||||
|
||||
**Total Resources:** 13 (excluding auto-managed resource groups)
|
||||
|
||||
@ -223,6 +241,7 @@ APPINSIGHTS_INSTRUMENTATIONKEY=<from-portal>
|
||||
## 🔑 Critical Environment Variables Summary
|
||||
|
||||
### Required Across All Services:
|
||||
|
||||
```bash
|
||||
# Cosmos DB
|
||||
COSMOS_ENDPOINT=https://cosmos-mywisprai.documents.azure.com:443/
|
||||
@ -259,29 +278,32 @@ APPINSIGHTS_INSTRUMENTATIONKEY=<from-portal>
|
||||
|
||||
## 📍 Geographic Distribution
|
||||
|
||||
| Region | Resources |
|
||||
|--------|-----------|
|
||||
| **East US** | Speech Services, Key Vault, Notification Hubs, Application Insights |
|
||||
| **West US 2** | Cosmos DB (primary), Blob Storage (primary) |
|
||||
| **Sweden Central** | Azure OpenAI |
|
||||
| **West Central US** | Blob Storage (secondary/geo-redundant) |
|
||||
| **Global** | Action Groups |
|
||||
| Region | Resources |
|
||||
| ------------------- | ------------------------------------------------------------------- |
|
||||
| **East US** | Speech Services, Key Vault, Notification Hubs, Application Insights |
|
||||
| **West US 2** | Cosmos DB (primary), Blob Storage (primary) |
|
||||
| **Sweden Central** | Azure OpenAI |
|
||||
| **West Central US** | Blob Storage (secondary/geo-redundant) |
|
||||
| **Global** | Action Groups |
|
||||
|
||||
---
|
||||
|
||||
## 💰 Cost Optimization Notes
|
||||
|
||||
### Free Tier Resources:
|
||||
|
||||
- ✅ Speech Services (F0)
|
||||
- ✅ Notification Hubs (Free)
|
||||
|
||||
### Paid Resources:
|
||||
|
||||
- 💵 Cosmos DB (Development/Testing workload)
|
||||
- 💵 Blob Storage (Standard_RAGRS, Cool tier)
|
||||
- 💵 Azure OpenAI (S0 - pay per use)
|
||||
- 💵 Application Insights (pay per GB ingested)
|
||||
|
||||
### Recommendations:
|
||||
|
||||
1. Monitor Cosmos DB RU consumption (Development/Testing mode has limits)
|
||||
2. Blob Storage is on Cool tier (good for infrequent access)
|
||||
3. Geo-redundant storage (RAGRS) adds cost but provides disaster recovery
|
||||
@ -291,47 +313,53 @@ APPINSIGHTS_INSTRUMENTATIONKEY=<from-portal>
|
||||
|
||||
## 🔗 Related Documentation
|
||||
|
||||
| Document | Location |
|
||||
|----------|----------|
|
||||
| Azure Portal Setup | `docs/devops/AZURE_PORTAL_SETUP.md` |
|
||||
| Key Vault & Secrets Rotation | `docs/devops/AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md` |
|
||||
| Environment & KV Audit | `docs/devops/ENVIRONMENT_VARIABLES_AND_KEYVAULT_AUDIT.md` |
|
||||
| Cosmos DB Package | `packages/cosmos/` |
|
||||
| Environment Variables Template | `.env.example` |
|
||||
| Key Vault Integration | `packages/config/src/keyvault.ts` |
|
||||
| Admin Secrets Manager | Admin dashboard → `/ops/secrets` (live CRUD for KV) |
|
||||
| Document | Location |
|
||||
| ------------------------------ | --------------------------------------------------------- |
|
||||
| Azure Portal Setup | `docs/devops/AZURE_PORTAL_SETUP.md` |
|
||||
| Key Vault & Secrets Rotation | `docs/devops/AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md` |
|
||||
| Environment & KV Audit | `docs/devops/ENVIRONMENT_VARIABLES_AND_KEYVAULT_AUDIT.md` |
|
||||
| Cosmos DB Package | `packages/cosmos/` |
|
||||
| Environment Variables Template | `.env.example` |
|
||||
| Key Vault Integration | `packages/config/src/keyvault.ts` |
|
||||
| Admin Secrets Manager | Admin dashboard → `/ops/secrets` (live CRUD for KV) |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Commands
|
||||
|
||||
### List all resources:
|
||||
|
||||
```bash
|
||||
az resource list --output table
|
||||
```
|
||||
|
||||
### Get Cosmos DB connection string:
|
||||
|
||||
```bash
|
||||
az cosmosdb keys list --name cosmos-mywisprai --resource-group rg-mywisprai --type connection-strings
|
||||
```
|
||||
|
||||
### Get Storage Account keys:
|
||||
|
||||
```bash
|
||||
az storage account keys list --account-name bytelystblobs --resource-group rg-mywisprai
|
||||
```
|
||||
|
||||
### Get Key Vault secrets:
|
||||
|
||||
```bash
|
||||
az keyvault secret list --vault-name kv-mywisprai --output table
|
||||
```
|
||||
|
||||
### Get OpenAI endpoint and keys:
|
||||
|
||||
```bash
|
||||
az cognitiveservices account show --name mywisprai-openai-sweden --resource-group rg-mywisprai
|
||||
az cognitiveservices account keys list --name mywisprai-openai-sweden --resource-group rg-mywisprai
|
||||
```
|
||||
|
||||
### List OpenAI deployments:
|
||||
|
||||
```bash
|
||||
az cognitiveservices account deployment list --name mywisprai-openai-sweden --resource-group rg-mywisprai --output table
|
||||
```
|
||||
|
||||
@ -43,7 +43,7 @@ Week 1-2 Week 3-4 Week 5-6 Week 7-8 Week 9-10 Week 11-14
|
||||
|
||||
#### 1.1 Azure Key Vault Infrastructure
|
||||
|
||||
- [ ] **1.1.1** Enable RBAC mode on `kv-mywisprai` vault (`enableRbacAuthorization=true`)
|
||||
- [ ] **1.1.1** Enable RBAC mode on `kv-mywisprai` vault (legacy name) (`enableRbacAuthorization=true`)
|
||||
- Assign `Key Vault Crypto Officer` to deployer user
|
||||
- Assign `Key Vault Crypto User` to service managed identities (when deployed)
|
||||
- **File:** Azure Portal / `az keyvault update`
|
||||
@ -64,7 +64,7 @@ Week 1-2 Week 3-4 Week 5-6 Week 7-8 Week 9-10 Week 11-14
|
||||
- [ ] **1.1.3** Add new env vars to `.env.example` and AKV secrets doc
|
||||
|
||||
```
|
||||
AZURE_KEYVAULT_URL=https://kv-mywisprai.vault.azure.net
|
||||
AZURE_KEYVAULT_URL=https://kv-mywisprai.vault.azure.net # legacy vault name
|
||||
FIELD_ENCRYPT_KEY_PROVIDER=akv # 'akv' | 'env' | 'memory'
|
||||
FIELD_ENCRYPT_MEK_NAME=lysnr-mek # product-specific
|
||||
```
|
||||
@ -461,7 +461,7 @@ Week 1-2 Week 3-4 Week 5-6 Week 7-8 Week 9-10 Week 11-14
|
||||
- [ ] **6.1.1** Create `bytelyst-blob-mek` RSA key in AKV
|
||||
- [ ] **6.1.2** Configure `bytelystblobs` storage account to use CMK from AKV
|
||||
- Azure Portal → Storage account → Encryption → Customer-managed keys
|
||||
- Select `bytelyst-blob-mek` from `kv-mywisprai`
|
||||
- Select `bytelyst-blob-mek` from `kv-mywisprai` (legacy vault name)
|
||||
- [ ] **6.1.3** Verify all blob operations still work (upload, download, SAS tokens)
|
||||
- [ ] **6.1.4** Update `AZURE_RESOURCE_INVENTORY.md`
|
||||
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
# Environment Variables & Azure Key Vault Audit
|
||||
|
||||
> **Last Updated:** 2026-02-15
|
||||
> **Last Updated:** 2026-03-21
|
||||
> **Purpose:** Complete audit of environment variables, Azure Key Vault secrets, and gap analysis
|
||||
>
|
||||
> **Note:** Azure resource names like `kv-mywisprai` are legacy (pre-rebrand). They cannot be renamed.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Executive Summary
|
||||
|
||||
### Current Status:
|
||||
|
||||
1. ✅ **All 13 LysnrAI secrets** seeded into Azure Key Vault (completed 2026-02-15)
|
||||
2. ✅ **MindLyst secrets** fully populated (12 secrets)
|
||||
3. ✅ **MyWisprAI secrets** populated (5 legacy `wispr-*` secrets)
|
||||
3. ✅ **LysnrAI legacy secrets** populated (5 `wispr-*` secrets, pre-rebrand)
|
||||
4. ⚠️ **Next action:** Rotate keys exposed in git history (see `AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md`)
|
||||
|
||||
---
|
||||
@ -18,28 +21,29 @@
|
||||
## 📊 Key Vault Current State
|
||||
|
||||
### Azure Key Vault: `kv-mywisprai`
|
||||
|
||||
**Location:** East US
|
||||
**Total Secrets:** 17
|
||||
|
||||
| Secret Name | Product | Purpose | Created | Status |
|
||||
|-------------|---------|---------|---------|--------|
|
||||
| `mindlyst-appinsights-connection-string` | MindLyst | Application Insights telemetry | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-blob-connection-string` | MindLyst | Blob Storage access | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-cosmos-database` | MindLyst | Cosmos DB database name | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-cosmos-endpoint` | MindLyst | Cosmos DB endpoint | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-cosmos-key` | MindLyst | Cosmos DB primary key | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-notification-hub-connection-string` | MindLyst | Push notifications | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-api-version` | MindLyst | OpenAI API version | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-deployment` | MindLyst | OpenAI deployment name | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-endpoint` | MindLyst | Azure OpenAI endpoint | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-key` | MindLyst | Azure OpenAI key | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-speech-key` | MindLyst | Azure Speech Services key | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-speech-region` | MindLyst | Azure Speech region | 2026-02-14 | ✅ Active |
|
||||
| `wispr-azure-openai-deployment` | MyWisprAI | OpenAI deployment name | 2026-02-07 | ✅ Active |
|
||||
| `wispr-azure-openai-endpoint` | MyWisprAI | Azure OpenAI endpoint | 2026-02-07 | ✅ Active |
|
||||
| `wispr-azure-openai-key` | MyWisprAI | Azure OpenAI key | 2026-02-07 | ✅ Active |
|
||||
| `wispr-azure-speech-key` | MyWisprAI | Azure Speech Services key | 2026-02-07 | ✅ Active |
|
||||
| `wispr-azure-speech-region` | MyWisprAI | Azure Speech region | 2026-02-07 | ✅ Active |
|
||||
| Secret Name | Product | Purpose | Created | Status |
|
||||
| --------------------------------------------- | ---------------- | ------------------------------ | ---------- | ----------------------------------- |
|
||||
| `mindlyst-appinsights-connection-string` | MindLyst | Application Insights telemetry | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-blob-connection-string` | MindLyst | Blob Storage access | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-cosmos-database` | MindLyst | Cosmos DB database name | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-cosmos-endpoint` | MindLyst | Cosmos DB endpoint | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-cosmos-key` | MindLyst | Cosmos DB primary key | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-notification-hub-connection-string` | MindLyst | Push notifications | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-api-version` | MindLyst | OpenAI API version | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-deployment` | MindLyst | OpenAI deployment name | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-endpoint` | MindLyst | Azure OpenAI endpoint | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-openai-key` | MindLyst | Azure OpenAI key | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-speech-key` | MindLyst | Azure Speech Services key | 2026-02-14 | ✅ Active |
|
||||
| `mindlyst-speech-region` | MindLyst | Azure Speech region | 2026-02-14 | ✅ Active |
|
||||
| `wispr-azure-openai-deployment` | LysnrAI (legacy) | OpenAI deployment name | 2026-02-07 | ✅ Active (superseded by `lysnr-*`) |
|
||||
| `wispr-azure-openai-endpoint` | LysnrAI (legacy) | Azure OpenAI endpoint | 2026-02-07 | ✅ Active (superseded by `lysnr-*`) |
|
||||
| `wispr-azure-openai-key` | LysnrAI (legacy) | Azure OpenAI key | 2026-02-07 | ✅ Active (superseded by `lysnr-*`) |
|
||||
| `wispr-azure-speech-key` | LysnrAI (legacy) | Azure Speech Services key | 2026-02-07 | ✅ Active (superseded by `lysnr-*`) |
|
||||
| `wispr-azure-speech-region` | LysnrAI (legacy) | Azure Speech region | 2026-02-07 | ✅ Active (superseded by `lysnr-*`) |
|
||||
|
||||
---
|
||||
|
||||
@ -49,21 +53,21 @@
|
||||
|
||||
The `LYSNR_SECRETS` constant defines these mappings:
|
||||
|
||||
| Key Vault Secret Name | Environment Variable | Status in KV | Priority |
|
||||
|-----------------------|---------------------|--------------|----------|
|
||||
| `lysnr-cosmos-key` | `COSMOS_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-cosmos-endpoint` | `COSMOS_ENDPOINT` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-jwt-secret` | `JWT_SECRET` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-stripe-secret-key` | `STRIPE_SECRET_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-stripe-webhook-secret` | `STRIPE_WEBHOOK_SECRET` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-billing-internal-key` | `BILLING_INTERNAL_KEY` | ✅ **Seeded** | 🟠 High |
|
||||
| Key Vault Secret Name | Environment Variable | Status in KV | Priority |
|
||||
| ------------------------------ | ------------------------------ | ------------- | ----------- |
|
||||
| `lysnr-cosmos-key` | `COSMOS_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-cosmos-endpoint` | `COSMOS_ENDPOINT` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-jwt-secret` | `JWT_SECRET` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-stripe-secret-key` | `STRIPE_SECRET_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-stripe-webhook-secret` | `STRIPE_WEBHOOK_SECRET` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-billing-internal-key` | `BILLING_INTERNAL_KEY` | ✅ **Seeded** | 🟠 High |
|
||||
| `lysnr-blob-connection-string` | `AZURE_BLOB_CONNECTION_STRING` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-blob-account-key` | `AZURE_BLOB_ACCOUNT_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-gemini-api-key` | `GEMINI_API_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-seed-secret` | `SEED_SECRET` | ✅ **Seeded** | 🟡 Medium |
|
||||
| `lysnr-azure-speech-key` | `AZURE_SPEECH_KEY` | ✅ **Seeded** | 🟠 High |
|
||||
| `lysnr-azure-openai-key` | `AZURE_OPENAI_KEY` | ✅ **Seeded** | 🟠 High |
|
||||
| `lysnr-azure-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | ✅ **Seeded** | 🟠 High |
|
||||
| `lysnr-blob-account-key` | `AZURE_BLOB_ACCOUNT_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-gemini-api-key` | `GEMINI_API_KEY` | ✅ **Seeded** | 🔴 Critical |
|
||||
| `lysnr-seed-secret` | `SEED_SECRET` | ✅ **Seeded** | 🟡 Medium |
|
||||
| `lysnr-azure-speech-key` | `AZURE_SPEECH_KEY` | ✅ **Seeded** | 🟠 High |
|
||||
| `lysnr-azure-openai-key` | `AZURE_OPENAI_KEY` | ✅ **Seeded** | 🟠 High |
|
||||
| `lysnr-azure-openai-endpoint` | `AZURE_OPENAI_ENDPOINT` | ✅ **Seeded** | 🟠 High |
|
||||
|
||||
**Total Expected:** 13 secrets
|
||||
**Total Seeded:** 13 secrets (100%) ✅ — Completed 2026-02-15
|
||||
@ -75,40 +79,44 @@ The `LYSNR_SECRETS` constant defines these mappings:
|
||||
### Core Platform Variables (from `.env.example`)
|
||||
|
||||
#### 🔐 Azure Key Vault
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `AZURE_KEYVAULT_URL` | Optional | - | All services | N/A |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| -------------------- | -------- | ------- | ------------ | ------ |
|
||||
| `AZURE_KEYVAULT_URL` | Optional | - | All services | N/A |
|
||||
|
||||
**Purpose:** Enable Key Vault secret resolution. Falls back to env vars if not set.
|
||||
|
||||
---
|
||||
|
||||
#### 🗄️ Azure Cosmos DB
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `COSMOS_ENDPOINT` | ✅ Yes | - | All services | ❌ No (lysnr) |
|
||||
| `COSMOS_KEY` | ✅ Yes | - | All services | ❌ No (lysnr) |
|
||||
| `COSMOS_DATABASE` | No | `lysnrai` | All services | N/A |
|
||||
|
||||
**Purpose:** Database connection for all products (lysnrai, mindlyst, mywisprai databases).
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| ----------------- | -------- | --------- | ------------ | ------------- |
|
||||
| `COSMOS_ENDPOINT` | ✅ Yes | - | All services | ❌ No (lysnr) |
|
||||
| `COSMOS_KEY` | ✅ Yes | - | All services | ❌ No (lysnr) |
|
||||
| `COSMOS_DATABASE` | No | `lysnrai` | All services | N/A |
|
||||
|
||||
**Purpose:** Database connection for all products (lysnrai, mindlyst, mywisprai/legacy databases).
|
||||
|
||||
---
|
||||
|
||||
#### 🔑 Authentication & Security
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `JWT_SECRET` | ✅ Yes | - | platform-service, extraction-service | ❌ No |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| ------------ | -------- | ------- | ------------------------------------ | ------ |
|
||||
| `JWT_SECRET` | ✅ Yes | - | platform-service, extraction-service | ❌ No |
|
||||
|
||||
**Purpose:** JWT token signing and verification across all services.
|
||||
|
||||
---
|
||||
|
||||
#### 💾 Azure Blob Storage
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `AZURE_BLOB_CONNECTION_STRING` | Optional | - | platform-service | ❌ No |
|
||||
| `AZURE_BLOB_ACCOUNT_NAME` | Optional | `bytelystblobs` | platform-service | N/A |
|
||||
| `AZURE_BLOB_ACCOUNT_KEY` | Optional | - | platform-service | ❌ No |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| ------------------------------ | -------- | --------------- | ---------------- | ------ |
|
||||
| `AZURE_BLOB_CONNECTION_STRING` | Optional | - | platform-service | ❌ No |
|
||||
| `AZURE_BLOB_ACCOUNT_NAME` | Optional | `bytelystblobs` | platform-service | N/A |
|
||||
| `AZURE_BLOB_ACCOUNT_KEY` | Optional | - | platform-service | ❌ No |
|
||||
|
||||
**Purpose:** File uploads, avatar storage, document storage.
|
||||
**Note:** Only needed for platform-service blob module.
|
||||
@ -116,13 +124,14 @@ The `LYSNR_SECRETS` constant defines these mappings:
|
||||
---
|
||||
|
||||
#### 💳 Stripe (Billing & Subscriptions)
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `STRIPE_SECRET_KEY` | Optional | - | platform-service | ❌ No |
|
||||
| `STRIPE_WEBHOOK_SECRET` | Optional | - | platform-service | ❌ No |
|
||||
| `STRIPE_PRICE_PRO` | Optional | - | platform-service | N/A |
|
||||
| `STRIPE_PRICE_ENTERPRISE` | Optional | - | platform-service | N/A |
|
||||
| `BILLING_INTERNAL_KEY` | Optional | - | platform-service | ❌ No |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| ------------------------- | -------- | ------- | ---------------- | ------ |
|
||||
| `STRIPE_SECRET_KEY` | Optional | - | platform-service | ❌ No |
|
||||
| `STRIPE_WEBHOOK_SECRET` | Optional | - | platform-service | ❌ No |
|
||||
| `STRIPE_PRICE_PRO` | Optional | - | platform-service | N/A |
|
||||
| `STRIPE_PRICE_ENTERPRISE` | Optional | - | platform-service | N/A |
|
||||
| `BILLING_INTERNAL_KEY` | Optional | - | platform-service | ❌ No |
|
||||
|
||||
**Purpose:** Subscription management, payment processing, webhook validation.
|
||||
**Status:** ❌ **Required for production but completely missing from Key Vault**
|
||||
@ -130,11 +139,12 @@ The `LYSNR_SECRETS` constant defines these mappings:
|
||||
---
|
||||
|
||||
#### 🤖 AI Services - Extraction
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `GEMINI_API_KEY` | ✅ Yes | - | extraction-service (Python sidecar) | ❌ No |
|
||||
| `PYTHON_SIDECAR_URL` | No | `http://localhost:4006` | extraction-service | N/A |
|
||||
| `DEFAULT_MODEL_ID` | No | `gemini-2.5-flash` | extraction-service | N/A |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| -------------------- | -------- | ----------------------- | ----------------------------------- | ------ |
|
||||
| `GEMINI_API_KEY` | ✅ Yes | - | extraction-service (Python sidecar) | ❌ No |
|
||||
| `PYTHON_SIDECAR_URL` | No | `http://localhost:4006` | extraction-service | N/A |
|
||||
| `DEFAULT_MODEL_ID` | No | `gemini-2.5-flash` | extraction-service | N/A |
|
||||
|
||||
**Purpose:** Text extraction, content analysis, AI-powered features.
|
||||
**Status:** ❌ **Critical for extraction service functionality**
|
||||
@ -142,11 +152,12 @@ The `LYSNR_SECRETS` constant defines these mappings:
|
||||
---
|
||||
|
||||
#### 🧠 Azure OpenAI (Optional)
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `AZURE_OPENAI_KEY` | Optional | - | extraction-service | ❌ No (lysnr) |
|
||||
| `AZURE_OPENAI_ENDPOINT` | Optional | - | extraction-service | ❌ No (lysnr) |
|
||||
| `AZURE_OPENAI_DEPLOYMENT_NAME` | Optional | - | extraction-service | N/A |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| ------------------------------ | -------- | ------- | ------------------ | ------------- |
|
||||
| `AZURE_OPENAI_KEY` | Optional | - | extraction-service | ❌ No (lysnr) |
|
||||
| `AZURE_OPENAI_ENDPOINT` | Optional | - | extraction-service | ❌ No (lysnr) |
|
||||
| `AZURE_OPENAI_DEPLOYMENT_NAME` | Optional | - | extraction-service | N/A |
|
||||
|
||||
**Purpose:** Alternative to Gemini for text extraction.
|
||||
**Existing:** ✅ Available for `wispr` and `mindlyst` products in Key Vault.
|
||||
@ -154,10 +165,11 @@ The `LYSNR_SECRETS` constant defines these mappings:
|
||||
---
|
||||
|
||||
#### 🎤 Azure Speech Services
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `AZURE_SPEECH_KEY` | Optional | - | LysnrAI product | ❌ No (lysnr) |
|
||||
| `AZURE_SPEECH_REGION` | Optional | `eastus` | LysnrAI product | N/A |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| --------------------- | -------- | -------- | --------------- | ------------- |
|
||||
| `AZURE_SPEECH_KEY` | Optional | - | LysnrAI product | ❌ No (lysnr) |
|
||||
| `AZURE_SPEECH_REGION` | Optional | `eastus` | LysnrAI product | N/A |
|
||||
|
||||
**Purpose:** Speech-to-text, text-to-speech for voice AI features.
|
||||
**Existing:** ✅ Available for `wispr` and `mindlyst` products in Key Vault.
|
||||
@ -165,24 +177,26 @@ The `LYSNR_SECRETS` constant defines these mappings:
|
||||
---
|
||||
|
||||
#### 🚀 Service Configuration
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `PORT` | No | varies | All services | N/A |
|
||||
| `HOST` | No | `0.0.0.0` | All services | N/A |
|
||||
| `NODE_ENV` | No | `development` | All services | N/A |
|
||||
| `SERVICE_NAME` | No | auto | All services | N/A |
|
||||
| `CORS_ORIGIN` | No | `*` (dev) | All services | N/A |
|
||||
| `DEFAULT_PRODUCT_ID` | No | `lysnrai` | All services | N/A |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| -------------------- | -------- | ------------- | ------------ | ------ |
|
||||
| `PORT` | No | varies | All services | N/A |
|
||||
| `HOST` | No | `0.0.0.0` | All services | N/A |
|
||||
| `NODE_ENV` | No | `development` | All services | N/A |
|
||||
| `SERVICE_NAME` | No | auto | All services | N/A |
|
||||
| `CORS_ORIGIN` | No | `*` (dev) | All services | N/A |
|
||||
| `DEFAULT_PRODUCT_ID` | No | `lysnrai` | All services | N/A |
|
||||
|
||||
**Purpose:** Runtime configuration, not secrets.
|
||||
|
||||
---
|
||||
|
||||
#### 📊 Application Insights (Monitoring)
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `APPLICATIONINSIGHTS_CONNECTION_STRING` | Optional | - | All services (future) | ✅ Yes (mindlyst) |
|
||||
| `APPINSIGHTS_INSTRUMENTATIONKEY` | Optional | - | All services (future) | N/A |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| --------------------------------------- | -------- | ------- | --------------------- | ----------------- |
|
||||
| `APPLICATIONINSIGHTS_CONNECTION_STRING` | Optional | - | All services (future) | ✅ Yes (mindlyst) |
|
||||
| `APPINSIGHTS_INSTRUMENTATIONKEY` | Optional | - | All services (future) | N/A |
|
||||
|
||||
**Purpose:** Telemetry, logging, monitoring.
|
||||
**Note:** Only MindLyst has this configured currently.
|
||||
@ -190,10 +204,11 @@ The `LYSNR_SECRETS` constant defines these mappings:
|
||||
---
|
||||
|
||||
#### 🔔 Notification Hubs (Mobile Push)
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
|----------|----------|---------|---------|--------|
|
||||
| `AZURE_NH_CONNECTION_STRING` | Optional | - | platform-service (future) | ✅ Yes (mindlyst) |
|
||||
| `AZURE_NH_HUB_NAME` | Optional | - | platform-service (future) | N/A |
|
||||
|
||||
| Variable | Required | Default | Used By | In KV? |
|
||||
| ---------------------------- | -------- | ------- | ------------------------- | ----------------- |
|
||||
| `AZURE_NH_CONNECTION_STRING` | Optional | - | platform-service (future) | ✅ Yes (mindlyst) |
|
||||
| `AZURE_NH_HUB_NAME` | Optional | - | platform-service (future) | N/A |
|
||||
|
||||
**Purpose:** Push notifications for mobile apps.
|
||||
**Note:** Only MindLyst has this configured currently.
|
||||
@ -280,9 +295,11 @@ These secrets are **required** for LysnrAI services to function and are **comple
|
||||
## 📦 Product-Specific Secret Patterns
|
||||
|
||||
### MindLyst Product (12 secrets) ✅
|
||||
|
||||
**Prefix:** `mindlyst-*`
|
||||
**Status:** Fully populated
|
||||
**Secrets:**
|
||||
|
||||
- Cosmos DB (endpoint, key, database)
|
||||
- Blob Storage (connection string)
|
||||
- Azure OpenAI (endpoint, key, deployment, api-version)
|
||||
@ -290,16 +307,19 @@ These secrets are **required** for LysnrAI services to function and are **comple
|
||||
- Notification Hub (connection string)
|
||||
- Application Insights (connection string)
|
||||
|
||||
### MyWisprAI Product (5 secrets) ⚠️
|
||||
**Prefix:** `wispr-*`
|
||||
**Status:** Partially populated (legacy — pre-rebrand desktop app secrets)
|
||||
### LysnrAI Legacy (5 secrets) ⚠️
|
||||
|
||||
**Prefix:** `wispr-*` (pre-rebrand)
|
||||
**Status:** Populated but superseded by `lysnr-*` secrets
|
||||
**Secrets:**
|
||||
|
||||
- Azure OpenAI (endpoint, key, deployment)
|
||||
- Azure Speech (key, region)
|
||||
|
||||
**Note:** These are legacy secrets from the original MyWisprAI product. LysnrAI services use `lysnr-*` prefixed secrets instead.
|
||||
**Note:** These are legacy secrets from before the myWisprAI → LysnrAI rebrand. Active LysnrAI services use `lysnr-*` prefixed secrets instead.
|
||||
|
||||
### LysnrAI Product (0 secrets) ❌
|
||||
|
||||
**Prefix:** `lysnr-*`
|
||||
**Status:** Completely missing
|
||||
**Expected:** 13 secrets
|
||||
@ -368,10 +388,10 @@ pnpm --filter @lysnrai/platform-service dev
|
||||
|
||||
### Step 4: Verify Each Service
|
||||
|
||||
| Service | Port | Test Endpoint | Expected Status |
|
||||
|---------|------|---------------|-----------------|
|
||||
| platform-service | 4003 | GET /health | 200 OK |
|
||||
| extraction-service | 4005 | GET /health | 200 OK |
|
||||
| Service | Port | Test Endpoint | Expected Status |
|
||||
| ------------------ | ---- | ------------- | --------------- |
|
||||
| platform-service | 4003 | GET /health | 200 OK |
|
||||
| extraction-service | 4005 | GET /health | 200 OK |
|
||||
|
||||
### Step 5: Production Checklist
|
||||
|
||||
@ -390,15 +410,16 @@ pnpm --filter @lysnrai/platform-service dev
|
||||
|
||||
### Recommended Rotation Schedule:
|
||||
|
||||
| Secret Type | Rotation Frequency | Method |
|
||||
|-------------|-------------------|--------|
|
||||
| Cosmos DB keys | Quarterly | Azure Portal → rotate keys → update KV |
|
||||
| JWT secret | Quarterly | Generate new → update KV → rolling deploy |
|
||||
| Stripe keys | Annually or on breach | Stripe Dashboard → update KV |
|
||||
| API keys (Gemini, OpenAI) | Annually or on breach | Provider portal → update KV |
|
||||
| Blob storage keys | Quarterly | Azure Portal → rotate keys → update KV |
|
||||
| Secret Type | Rotation Frequency | Method |
|
||||
| ------------------------- | --------------------- | ----------------------------------------- |
|
||||
| Cosmos DB keys | Quarterly | Azure Portal → rotate keys → update KV |
|
||||
| JWT secret | Quarterly | Generate new → update KV → rolling deploy |
|
||||
| Stripe keys | Annually or on breach | Stripe Dashboard → update KV |
|
||||
| API keys (Gemini, OpenAI) | Annually or on breach | Provider portal → update KV |
|
||||
| Blob storage keys | Quarterly | Azure Portal → rotate keys → update KV |
|
||||
|
||||
### Rotation Procedure:
|
||||
|
||||
1. Generate new secret in Azure Portal / provider
|
||||
2. Update Key Vault with new value
|
||||
3. Services auto-fetch new secret on next restart (or use Key Vault rotation event)
|
||||
@ -409,40 +430,43 @@ pnpm --filter @lysnrai/platform-service dev
|
||||
|
||||
## 🔗 Related Files & Documentation
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `packages/config/src/keyvault.ts` | Key Vault integration code (`resolveKeyVaultSecrets` + `LYSNR_SECRETS`) |
|
||||
| `scripts/seed-keyvault.sh` | Script to populate Key Vault from `.env` values |
|
||||
| `.env.example` | Template for required environment variables |
|
||||
| `services/platform-service/src/server.ts` | Platform service — resolves KV secrets at startup |
|
||||
| `services/extraction-service/src/server.ts` | Extraction service — resolves KV secrets at startup |
|
||||
| `admin-dashboard-web/src/instrumentation.ts` | Admin dashboard — resolves KV secrets via Next.js hook |
|
||||
| `user-dashboard-web/src/instrumentation.ts` | User dashboard — resolves KV secrets via Next.js hook |
|
||||
| `tracker-dashboard-web/src/instrumentation.ts` | Tracker dashboard — resolves KV secrets via Next.js hook |
|
||||
| `backend/src/secrets/keyvault.py` | Python backend SecretResolver |
|
||||
| `src/secrets/keyvault.py` | Desktop app SecretResolver |
|
||||
| `docs/devops/AZURE_PORTAL_SETUP.md` | Azure portal configuration guide |
|
||||
| `docs/devops/AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md` | Key Vault setup + rotation runbooks |
|
||||
| `docs/devops/AZURE_RESOURCE_INVENTORY.md` | Complete Azure resource inventory |
|
||||
| File | Purpose |
|
||||
| ----------------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `packages/config/src/keyvault.ts` | Key Vault integration code (`resolveKeyVaultSecrets` + `LYSNR_SECRETS`) |
|
||||
| `scripts/seed-keyvault.sh` | Script to populate Key Vault from `.env` values |
|
||||
| `.env.example` | Template for required environment variables |
|
||||
| `services/platform-service/src/server.ts` | Platform service — resolves KV secrets at startup |
|
||||
| `services/extraction-service/src/server.ts` | Extraction service — resolves KV secrets at startup |
|
||||
| `admin-dashboard-web/src/instrumentation.ts` | Admin dashboard — resolves KV secrets via Next.js hook |
|
||||
| `user-dashboard-web/src/instrumentation.ts` | User dashboard — resolves KV secrets via Next.js hook |
|
||||
| `tracker-dashboard-web/src/instrumentation.ts` | Tracker dashboard — resolves KV secrets via Next.js hook |
|
||||
| `backend/src/secrets/keyvault.py` | Python backend SecretResolver |
|
||||
| `src/secrets/keyvault.py` | Desktop app SecretResolver |
|
||||
| `docs/devops/AZURE_PORTAL_SETUP.md` | Azure portal configuration guide |
|
||||
| `docs/devops/AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md` | Key Vault setup + rotation runbooks |
|
||||
| `docs/devops/AZURE_RESOURCE_INVENTORY.md` | Complete Azure resource inventory |
|
||||
|
||||
---
|
||||
|
||||
## 📊 Summary Statistics
|
||||
|
||||
### Environment Variables:
|
||||
|
||||
- **Total Unique Variables:** 35+
|
||||
- **Required for Core Functionality:** 6
|
||||
- **Optional/Feature-Specific:** 29+
|
||||
|
||||
### Key Vault Secrets:
|
||||
|
||||
- **Total Secrets in KV:** 30
|
||||
- **MindLyst Secrets:** 12 ✅
|
||||
- **MyWisprAI Secrets:** 5 ⚠️ (legacy `wispr-*` prefix)
|
||||
- **LysnrAI Legacy Secrets:** 5 ⚠️ (legacy `wispr-*` prefix, pre-rebrand)
|
||||
- **LysnrAI Secrets:** 13 ✅ (`lysnr-*` prefix)
|
||||
- **Expected LysnrAI Secrets:** 13
|
||||
- **Coverage Gap:** 0%
|
||||
|
||||
### Priority Actions:
|
||||
|
||||
- ✅ All 13 `lysnr-*` secrets seeded (2026-02-15)
|
||||
- ⚠️ **Next:** Rotate keys that were exposed in git history (see `AZURE_KEY_VAULT_AND_SECRETS_ROTATION.md`)
|
||||
|
||||
@ -465,6 +489,7 @@ ERROR: HTTPSConnection(host='kv-mywisprai.vault.azure.net', port=443): Failed to
|
||||
As a result, the generated `kv_azure.txt` currently contains `null` values for every `lysnr-*` secret. Once DNS/routing to the vault is available again, rerun the same command to emit the actual values and use the file as a snapshot for comparison.
|
||||
|
||||
📁 `kv_azure.txt` (post-run):
|
||||
|
||||
```
|
||||
lysnr-azure-openai-endpoint=null
|
||||
lysnr-azure-openai-key=null
|
||||
@ -524,25 +549,26 @@ node -e "process.env.AZURE_KEYVAULT_URL && console.log('✅ KV enabled') || cons
|
||||
|
||||
Scanned git history across `learning_voice_ai_agent` to recover actual secret values for the 13 missing `lysnr-*` secrets.
|
||||
|
||||
| # | KV Secret Name | Source | Status |
|
||||
|---|----------------|--------|--------|
|
||||
| 1 | `lysnr-cosmos-endpoint` | `.env` commits | ✅ Recovered |
|
||||
| 2 | `lysnr-cosmos-key` | `.env` commits | ✅ Recovered |
|
||||
| 3 | `lysnr-jwt-secret` | `.env` commits | ✅ Recovered |
|
||||
| 4 | `lysnr-stripe-secret-key` | `.env` commits | ✅ Recovered (sk_test_*) |
|
||||
| 5 | `lysnr-stripe-webhook-secret` | `.env` commits | ✅ Recovered (whsec_*) |
|
||||
| 6 | `lysnr-billing-internal-key` | `.env` commits | ✅ Recovered |
|
||||
| 7 | `lysnr-blob-connection-string` | `.env` commits | ✅ Recovered |
|
||||
| 8 | `lysnr-blob-account-key` | `.env` commits | ✅ Recovered |
|
||||
| 9 | `lysnr-gemini-api-key` | Provided manually | ✅ Recovered |
|
||||
| 10 | `lysnr-seed-secret` | `.env` commits | ✅ Recovered |
|
||||
| 11 | `lysnr-azure-speech-key` | `.env` commits | ✅ Recovered |
|
||||
| 12 | `lysnr-azure-openai-key` | `.env` commits | ✅ Recovered |
|
||||
| 13 | `lysnr-azure-openai-endpoint` | `.env` commits | ✅ Recovered |
|
||||
| # | KV Secret Name | Source | Status |
|
||||
| --- | ------------------------------ | ----------------- | ------------------------- |
|
||||
| 1 | `lysnr-cosmos-endpoint` | `.env` commits | ✅ Recovered |
|
||||
| 2 | `lysnr-cosmos-key` | `.env` commits | ✅ Recovered |
|
||||
| 3 | `lysnr-jwt-secret` | `.env` commits | ✅ Recovered |
|
||||
| 4 | `lysnr-stripe-secret-key` | `.env` commits | ✅ Recovered (sk*test*\*) |
|
||||
| 5 | `lysnr-stripe-webhook-secret` | `.env` commits | ✅ Recovered (whsec\_\*) |
|
||||
| 6 | `lysnr-billing-internal-key` | `.env` commits | ✅ Recovered |
|
||||
| 7 | `lysnr-blob-connection-string` | `.env` commits | ✅ Recovered |
|
||||
| 8 | `lysnr-blob-account-key` | `.env` commits | ✅ Recovered |
|
||||
| 9 | `lysnr-gemini-api-key` | Provided manually | ✅ Recovered |
|
||||
| 10 | `lysnr-seed-secret` | `.env` commits | ✅ Recovered |
|
||||
| 11 | `lysnr-azure-speech-key` | `.env` commits | ✅ Recovered |
|
||||
| 12 | `lysnr-azure-openai-key` | `.env` commits | ✅ Recovered |
|
||||
| 13 | `lysnr-azure-openai-endpoint` | `.env` commits | ✅ Recovered |
|
||||
|
||||
**Result:** 13/13 recovered. Seed script written to `kv.txt` (gitignored, temporary).
|
||||
|
||||
**To seed:**
|
||||
|
||||
```bash
|
||||
az login
|
||||
bash kv.txt
|
||||
@ -555,5 +581,5 @@ rm kv.txt
|
||||
|
||||
**Generated by:** Environment audit automation
|
||||
**Maintained by:** ByteLyst DevOps Team
|
||||
**Next Audit:** After LysnrAI `lysnr-*` secrets are seeded into `kv-mywisprai`
|
||||
**Next Audit:** After key rotation for secrets exposed in git history
|
||||
**Admin UI:** Secrets Manager at admin dashboard → `/ops/secrets`
|
||||
|
||||
Loading…
Reference in New Issue
Block a user