feat(apikeys): optional ExpiresUtc — create + verifier enforcement + sqlite v3 migration (archreview G-2)
ApiKeyRecord/ApiKeyListItem gain a nullable ExpiresUtc (NULL = never expires); ApiKeyFailure gains KeyExpired. ApiKeyVerifier rejects a key whose ExpiresUtc is at-or-before now (inclusive, injected clock), before the secret comparison. CreateKeyAsync gets an expiresUtc overload; rotate preserves existing expiry. SQLite schema bumps to v3: a nullable expires_utc column, added to fresh DBs via CREATE and to existing v1/v2 DBs via an idempotent guarded ALTER — donor v2 gateway-auth.db upgrades in place, no key invalidated. Version 0.1.3 -> 0.1.4 (not yet published; nuget push is human-gated). Consumers (HistorianGateway, mxaccessgw) bump to 0.1.4 to set/enforce expiry. 146 Auth.ApiKeys tests pass.
This commit is contained in:
@@ -136,7 +136,7 @@ each project's **code-verified current state**, and the **gaps** between. See
|
||||
|
||||
| Component | Status | Goal | Design | Implementation |
|
||||
|---|---|---|---|---|
|
||||
| Auth (login / identity / authz) | Adopted (lib `0.1.3`; all 3 apps, merged to **local default** main/master + **pushed to origin** (gitea)) | Shared `ZB.MOM.WW.Auth` lib | [`components/auth/`](components/auth/) | [`ZB.MOM.WW.Auth/`](ZB.MOM.WW.Auth/) |
|
||||
| Auth (login / identity / authz) | Adopted (lib `0.1.4`; all 3 apps, merged to **local default** main/master + **pushed to origin** (gitea)) | Shared `ZB.MOM.WW.Auth` lib | [`components/auth/`](components/auth/) | [`ZB.MOM.WW.Auth/`](ZB.MOM.WW.Auth/) |
|
||||
| UI Theme (layout / tokens / components) | Adopted (lib `0.2.0`; all 3 apps, merged to **local default** + **pushed to origin** (gitea)) | Shared `ZB.MOM.WW.Theme` RCL | [`components/ui-theme/`](components/ui-theme/) | [`ZB.MOM.WW.Theme/`](ZB.MOM.WW.Theme/) |
|
||||
| Health (readiness / liveness / active-node) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Health` lib | [`components/health/`](components/health/) | [`ZB.MOM.WW.Health/`](ZB.MOM.WW.Health/) |
|
||||
| Observability (metrics / traces / logs) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Telemetry` lib + `.Serilog` | [`components/observability/`](components/observability/) | [`ZB.MOM.WW.Telemetry/`](ZB.MOM.WW.Telemetry/) |
|
||||
@@ -164,6 +164,7 @@ MxGateway `0.1.2`, ScadaBridge `0.1.3`. Per-repo detail in [`components/auth/GAP
|
||||
`docs/plans/2026-06-02-auth-audit-normalization*.md`.
|
||||
Build/test from `ZB.MOM.WW.Auth/`: `dotnet test`. Consumer matrix: OtOpcUa → Abstractions+Ldap+AspNetCore;
|
||||
MxAccessGateway & ScadaBridge → all four (ApiKeys not used by OtOpcUa).
|
||||
**`0.1.4` (2026-07-09, archreview G-2):** optional `ApiKeyRecord.ExpiresUtc` (nullable = never-expires), `ApiKeyFailure.KeyExpired`, `ApiKeyVerifier` expiry enforcement (inclusive, injected clock), a `CreateKeyAsync(expiresUtc)` overload, and a SQLite **schema v3** additive `expires_utc` column (idempotent `ALTER`; donor v2 DBs upgrade in place, no key invalidated). Committed in scadaproj; **NOT yet published to the Gitea feed (human-gated `dotnet nuget push`)**. On publish: HistorianGateway consumes it (unblocks `apikey create --expires` + Task-10 dashboard Expires column) and mxaccessgw gains the same verifier expiry enforcement — both must bump to `0.1.4`.
|
||||
|
||||
The UI-theme component is fully populated: a normalized [`spec`](components/ui-theme/spec/SPEC.md),
|
||||
a [`design-tokens`](components/ui-theme/spec/DESIGN-TOKENS.md) reference, a
|
||||
|
||||
Reference in New Issue
Block a user