diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlDriverConfigDto.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlDriverConfigDto.cs
new file mode 100644
index 00000000..fac5ee4c
--- /dev/null
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlDriverConfigDto.cs
@@ -0,0 +1,59 @@
+namespace ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts;
+
+///
+/// The DriverConfig blob shape for a Sql driver instance (design §5.1). Deserialised by the
+/// driver factory, which applies the documented defaults for every absent (null) field and maps the result
+/// onto the driver's typed options.
+/// No connection string lives here. Only — a name resolved at
+/// Initialize from the environment / secret store (e.g. Sql__ConnectionStrings__MesStaging) — so a
+/// deployed artifact never carries database credentials.
+/// Enum-valued fields are enum-typed (not strings) so a JsonStringEnumConverter round-trips
+/// their names rather than their ordinals. The converter is applied by the factory's
+/// JsonSerializerOptions (Task 9), not by an attribute on this DTO — mirroring the driver
+/// enum-serialization trap that bit the AdminUI driver pages.
+///
+public sealed class SqlDriverConfigDto
+{
+ /// Which ADO.NET provider/dialect backs this instance. Defaults to — the only provider v1 constructs.
+ public SqlProvider Provider { get; init; } = SqlProvider.SqlServer;
+
+ ///
+ /// Name of the connection string to resolve from the environment / secret store at Initialize —
+ /// never the connection string itself.
+ ///
+ public string? ConnectionStringRef { get; init; }
+
+ /// Poll interval applied to groups that do not carry their own. Absent ⇒ the factory default.
+ public TimeSpan? DefaultPollInterval { get; init; }
+
+ ///
+ /// Per-query wall-clock deadline enforced client-side (a breach surfaces BadTimeout). Must be
+ /// greater than , which is only the server-side backstop (design §8.3).
+ ///
+ public TimeSpan? OperationTimeout { get; init; }
+
+ /// ADO.NET CommandTimeout backstop (seconds granularity server-side).
+ public TimeSpan? CommandTimeout { get; init; }
+
+ /// Cap on concurrently executing group queries — the connection-pool guard.
+ public int? MaxConcurrentGroups { get; init; }
+
+ /// When , a NULL cell publishes Bad rather than the default Uncertain.
+ public bool? NullIsBad { get; init; }
+
+ /// Master write kill-switch. v1 is read-only — writes stay disabled regardless.
+ public bool? AllowWrites { get; init; }
+
+ /// Background connectivity-probe settings. Absent ⇒ the factory default.
+ public SqlProbeDto? Probe { get; init; }
+}
+
+/// Background connectivity-probe settings inside a (design §5.1).
+public sealed class SqlProbeDto
+{
+ /// Whether the driver runs its background connectivity probe.
+ public bool? Enabled { get; init; }
+
+ /// Interval between probe attempts.
+ public TimeSpan? Interval { get; init; }
+}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlProvider.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlProvider.cs
new file mode 100644
index 00000000..67879307
--- /dev/null
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts/SqlProvider.cs
@@ -0,0 +1,39 @@
+namespace ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts;
+
+/// Which ADO.NET provider/dialect backs a Sql driver instance. v1 constructs only SqlServer.
+public enum SqlProvider
+{
+ /// Microsoft SQL Server via Microsoft.Data.SqlClient — the only provider v1 constructs.
+ SqlServer,
+
+ /// PostgreSQL (Npgsql) — reserved for P2; not constructed in v1.
+ Postgres,
+
+ /// MySQL / MariaDB — reserved; not constructed in v1.
+ MySql,
+
+ /// Generic ODBC — reserved for P2; not constructed in v1.
+ Odbc,
+
+ /// Oracle — reserved; not constructed in v1.
+ Oracle,
+}
+
+/// Tag→value mapping model. v1 ships KeyValue + WideRow; Query is deferred (design §5.4 / P3).
+public enum SqlTagModel
+{
+ ///
+ /// Key-value (EAV) table: one row per tag, selected by keyColumn = keyValue, value read from
+ /// valueColumn.
+ ///
+ KeyValue,
+
+ ///
+ /// Wide row: one row holds many signals as columns; the tag names its columnName and the row is
+ /// picked by a row selector (a whereColumn/whereValue pair, or newest-by-timestamp).
+ ///
+ WideRow,
+
+ /// Named arbitrary-SELECT query (design §5.4). Deferred to P3 — not accepted by v1's parser.
+ Query,
+}