# MxAccessGateway — secrets current state

Descriptive baseline (code-verified) of how `mxaccessgw` handles secrets **today**, before
adopting `ZB.MOM.WW.Secrets`. Paths are relative to `~/Desktop/MxAccessGateway`.

## Where each secret lives today

| Secret | Location today | At-rest protection |
|---|---|---|
| gRPC inbound API keys | Peppered HMAC-SHA256 hashes in SQLite `gateway-auth.db` (`MxGateway:Authentication:SqlitePath`, `…Server/appsettings.json:17`) via `ZB.MOM.WW.Auth.ApiKeys` (`…/Security/Authentication/AuthStoreServiceCollectionExtensions.cs:70`) | Hashed (not reversible); plaintext key never stored |
| API-key **pepper** | Read by config-key **name** `MxGateway:ApiKeyPepper`; value supplied out-of-band (env `MxGateway__ApiKeyPepper`), intentionally **not** in appsettings (`AuthStoreServiceCollectionExtensions.cs:36,54-55`) | Runtime-supplied; no dedicated env reader (default config binding); flagged open item SEC-10 |
| LDAP dashboard bind password | **Plaintext** `appsettings.json:29` `ServiceAccountPassword: "serviceaccount123"`; also a hardcoded default in `Configuration/LdapOptions.cs:61` | None |
| Galaxy-repository SQL connection string | **Plaintext** `appsettings.json:76` (currently `Integrated Security=True`, but the field is a raw connstr that would carry `Password=` in plaintext) | None (redacted for **display** only, `Dashboard/DashboardConnectionStringDisplay.cs:10-24`) |
| TLS PFX | Generated/persisted with a **null password**, ACL-protected on disk (`Security/Tls/SelfSignedCertificateProvider.cs:153,193`) | Filesystem ACL, no password |
| MXAccess/Wonderware creds | **Not stored** — pass-through runtime gRPC request payload forwarded to COM (`Worker/MxAccess/MxAccessCommandExecutor.cs:318-325`) | N/A |

## Encryption-at-rest today

- **None** for the secrets above. The only Data Protection use is short-lived SignalR hub
  bearer tokens (`Dashboard/HubTokenService.cs:43-46`) — and Data Protection is **never
  explicitly configured** (no `AddDataProtection`/`PersistKeysTo`/`ProtectKeysWith`/
  `SetApplicationName` anywhere), so the key ring falls back to the ASP.NET default. Not
  applied to any credential.

## Config expansion today

- **None.** Stock `WebApplication.CreateBuilder` chain (`GatewayApplication.cs:60`); no
  `${...}` expansion, no custom config post-processing before options binding. Secrets are
  read verbatim from resolved config values.

## Adoption plan (toward SPEC)

1. **Highest value first:** move the plaintext **LDAP `ServiceAccountPassword`** and the
   **Galaxy connection-string password** behind `${secret:ldap/mxgateway/bind}` /
   `${secret:sql/mxgateway/galaxy}` — pre-host `SecretReferenceExpander` before the existing
   `GatewayOptionsValidator` runs. Delete the hardcoded plaintext defaults in `LdapOptions`.
2. **Pepper:** the pepper is already runtime-supplied by design — optionally source it via
   `${secret:apikey-pepper/mxgateway}` to close SEC-10's "no dedicated env reader" gap while
   keeping it out of appsettings.
3. **Master key:** env provider (`ZB_SECRETS_MASTER_KEY`) for the Windows/NSSM deployment,
   or DPAPI provider (Windows box) if a machine-bound key is preferred.
4. **UI:** mount `/admin/secrets` in the existing Blazor dashboard; map the gateway's
   `Administrator` role onto `secrets:manage`/`secrets:reveal`.
5. **Keep bespoke:** the peppered-HMAC API-key store (already best-practice — hashed, not
   encrypted-reversible) and the ACL-protected passwordless TLS PFX stay as-is; MXAccess
   pass-through creds are out of scope (never stored).
