docs: inbound API key store — shared SQL Server provider on central pairs (spec, runbook + central-pairs procedure, DBA DDL copy, topology, env inventory, CLAUDE.md, register row 108 closed with rig proof, row 109 Secrets backoff follow-up, Delmia spec §8)

Claude-Session: https://claude.ai/code/session_013L3XdmVii9i5sY4FChU8pB
This commit is contained in:
Joseph Doherty
2026-09-02 23:31:21 -04:00
parent a83cc8613d
commit f47ceb55b1
11 changed files with 1004 additions and 12 deletions
+3
View File
@@ -75,6 +75,9 @@ that is the same variable, not a separate one).
| `ScadaBridge__Security__JwtSigningKey` | Yes — `${secret:security/scadabridge/jwt-signing-key}` in `appsettings.Central.json` | `ScadaBridge:Security:JwtSigningKey` | HMAC-SHA256 signing key for the cookie-embedded session JWT. | ≥32-char secret | Yes on Central |
| `ScadaBridge__Security__Ldap__ServiceAccountPassword` | Yes — `${secret:ldap/scadabridge/service-account-password}` in `appsettings.Central.json` | `ScadaBridge:Security:Ldap:ServiceAccountPassword` | LDAP bind-account password. (Renamed from the old flat `...__LdapServiceAccountPassword`.) | the bind password | Yes on Central if LDAP bind is used |
| `ScadaBridge__InboundApi__ApiKeyPepper` | No — env/secret only (not in any shipped appsettings) | `ScadaBridge:InboundApi:ApiKeyPepper` | Per-environment pepper for the inbound API-key peppered-HMAC verifier. Hard Central startup requirement since 2026-06-03. | ≥16-char secret, unique per environment | Yes on Central |
| `ScadaBridge__InboundApi__ApiKeyStore__Provider` | Yes — `docker/docker-compose.yml` and `docker-env2/docker-compose.yml` set `SqlServer` on both centrals | `ScadaBridge:InboundApi:ApiKeyStore:Provider` | Which backend holds inbound API keys: `Sqlite` (per node, library default) or `SqlServer` (shared `zbauth` schema across a central pair — design 2026-09-02, register row 108). | `Sqlite` \| `SqlServer` (case-insensitive) | No — defaults to `Sqlite`; a clustered Central left on `Sqlite` logs a boot Warning |
| `ScadaBridge__InboundApi__ApiKeyStore__SqlServer__ConnectionString` | No — falls back to `ScadaBridge:Database:ConfigurationDb` when unset | `ScadaBridge:InboundApi:ApiKeyStore:SqlServer:ConnectionString` | Connection string for the shared `zbauth` schema. Only read when `Provider=SqlServer`. | connection string — literal or env override, **never** a `${secret:}` reference (the secrets store is itself SQL-backed) | No — only meaningful under `Provider=SqlServer` |
| `ScadaBridge__InboundApi__ApiKeyStore__ImportFromSqlitePath` | No — env/secret only | `ScadaBridge:InboundApi:ApiKeyStore:ImportFromSqlitePath` | SQLite file imported once at boot when `Provider=SqlServer`; renamed `*.imported` after a successful import. | filesystem path; defaults to the library's `SqlitePath` default | No |
| `ScadaBridge__Communication__GrpcPsk` | Yes — `${secret:SB-GRPC-PSK-site-1}` in `appsettings.Site.json` | `ScadaBridge:Communication:GrpcPsk` | **Site side** of the per-site gRPC control-plane PSK. StartupValidator refuses to boot a Site node without it; both pair nodes carry the same value. | per-site secret (e.g. `dev-grpc-psk-docker-site-a`); prod `${secret:SB-GRPC-PSK-<siteId>}` | Yes on Site |
| `ScadaBridge__Communication__SitePsks__<siteId>` | No in shipped src appsettings (central normally resolves the `SB-GRPC-PSK-<siteId>` secret); present only in the docker-compose env blocks | `ScadaBridge:Communication:SitePsks:<siteId>` | **Central side** of the same key: the value central presents when dialling that site. Must equal the site's `GrpcPsk`. Override for hosts without a master secret store. | matches the site's `GrpcPsk` | On Central, either this **or** the `SB-GRPC-PSK-<siteId>` store secret |