9b30bdeb7a
SqlDriver implements IDriver / ITagDiscovery / IReadable / ISubscribable / IHostConnectivityProbe / IAsyncDisposable over the landed SqlPollReader, mirroring ModbusDriver. IWritable is deliberately absent: v1 is read-only structurally, and every discovered variable is SecurityClass=ViewOnly. The shell classifies poll outcomes because nothing below it does. The reader honours IReadable literally — it throws only when the database is unreachable and Bad-codes everything else — so a frozen database returns all-BadTimeout snapshots through a perfectly successful PollGroupEngine tick. Without ObservePollOutcome the driver would report Healthy while every value was Bad. Connection-class codes (BadTimeout / BadCommunicationError) degrade health and report the host Stopped; authoring-class codes (unresolvable RawPath, absent row, type mismatch) change nothing, so a tag typo never reports the database down. It deliberately does NOT synthesise an exception to earn engine backoff: the engine's exception path publishes nothing, which would cost clients the Bad quality the reader went out of its way to produce. Initialize builds the authored RawPath table first (pure, cannot fail; a malformed TagConfig is logged and skipped) then verifies liveness over one open-use-dispose connection bounded by wall clock as well as by token (the R2-01 lesson) — failure records Faulted and rethrows so DriverInstanceActor retries. The connection string is never logged: a credential-free server/database Endpoint is the only rendering that reaches a log, LastError, or the host status. DriverTypeNames.Sql is NOT added here — DriverTypeNamesGuardTests asserts bidirectional parity with registered factories, so the constant must land with the factory (Task 11). SqlDriver.DriverTypeName carries the string until then. Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW