Files
lmxopcua/archreview/plans/R3-05-acl-hot-path-expiry-plan.md.tasks.json
T

103 lines
3.7 KiB
JSON

{
"planPath": "archreview/plans/R3-05-acl-hot-path-expiry-plan.md",
"lastUpdated": "2026-08-20",
"tasks": [
{
"id": "T1",
"subject": "Register TimeProvider in DI (shared by authorizer, key store and revalidation timer) + ApiKeyOptions.StoreTimeoutMs/StoreCacheSeconds + AclOptions.RevalidationIntervalSeconds (03/S18, 03/S19)",
"status": "done",
"blockedBy": []
},
{
"id": "T2",
"subject": "BoundedApiKeyStore: hard per-call deadline on the key store under the SessionManager lock, fail-closed (03/S18)",
"status": "done",
"blockedBy": [
"T1"
]
},
{
"id": "T3",
"subject": "BoundedApiKeyStore: short TTL read-through cache + falsification control (a revoked key is denied once the TTL has passed)",
"status": "done",
"blockedBy": [
"T2"
]
},
{
"id": "T4",
"subject": "otopcua.opcua.apikey_store.bounded counter (outcome=timeout|cache_hit) + MeterListener assertions",
"status": "done",
"blockedBy": [
"T3"
]
},
{
"id": "T5",
"subject": "Wire BoundedApiKeyStore on admin/fused nodes in Program.cs + registration guard test; correct the authenticator's 'no network I/O at all' remark",
"status": "done",
"blockedBy": [
"T4"
]
},
{
"id": "T6",
"subject": "AclRevalidationTimer (pure, TimeProvider-driven, non-throwing tick) + unit tests (03/S19)",
"status": "done",
"blockedBy": [
"T1"
]
},
{
"id": "T7",
"subject": "Node-manager expiry tests (FakeTimeProvider advanced past ExpiresUtc, no deploy) + correct the ':316-328' only-trigger xmldoc",
"status": "done",
"blockedBy": [
"T1"
]
},
{
"id": "T8",
"subject": "Wire the revalidation timer into OtOpcUaServerHostedService (create after StartAsync, dispose FIRST in StopAsync) + ordering test",
"status": "done",
"blockedBy": [
"T6",
"T7"
]
},
{
"id": "T9",
"subject": "Over-the-wire AclKeyExpiryEnforcementTests: key-carrying session, clock advanced past expiry, item goes BadUserAccessDenied with no deploy (+ negative control)",
"status": "done",
"blockedBy": [
"T8"
]
},
{
"id": "T10",
"subject": "Docs: docs/security.md store table + revocation bullets, and the CLAUDE.md 'asymmetric revocation' sentence (activation vs already-open session)",
"status": "done",
"blockedBy": [
"T5",
"T8"
]
},
{
"id": "T11",
"subject": "LIVE GATE: docker-dev with OTOPCUA_ACL_ENABLED=true \u2014 subscription goes BadUserAccessDenied within one interval of ExpiresUtc with no deploy (+ long-expiry negative control, + bounded-store leg)",
"status": "done",
"blockedBy": [
"T5",
"T9"
],
"note": "S19 expiry leg PASS in the first gate (BadUserAccessDenied 0.09 s after ExpiresUtc, no deploy; negative control clean). S18 bounded-store leg FAILED in the first gate (42.9 s hang, 57 s subscription stall \u2014 cooperative token) and PASSED on the 2026-08-20 re-gate after f665e8b8: keyed connect denied in 2.42 s with SQL paused, Warning logged at the deadline (5 s before unpause), open subscription max gap 1.00 s, timeout counter 1, no-activation control clean, no unobserved exception after unpause. See plan 'Live gate result (2026-08-20, S18 re-gate)'."
},
{
"id": "T12",
"subject": "File residuals R1 (event monitored items revalidated by nothing) and R2 (expired key retains roles while Security:Acl:Enabled=false)",
"status": "done",
"blockedBy": []
}
]
}