You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SimulatedNetworkListenerOptions can now be supplied to ListenLocalAsync/ListenNetworkAsync to carry parameters, including a newly introduced way to carry a user-supplied certificate for encrypted connections and an IP address for binding.
Copy file name to clipboardExpand all lines: CLAUDE.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -123,7 +123,7 @@ Field rosters live in the source XML docs; this captures only identity + load-be
123
123
124
124
-**`Simulation`** = server / instance.
125
125
Holds `SystemHeapTables`, the `Databases` dict, and `ServerCollationName` (`init`-only; defaults `SQL_Latin1_General_CP1_CI_AS`; mirrors `model.collation` — install-time seed for every new `Database`, both the lazy `"simulated"` seed and collation-less bacpac imports; `init` reflects real immutability).
Holds `Schemas`, `CompatibilityLevel`, `CollationName`, the rowversion counter (`@@DBTS`), the MVCC version store, and the principal/permission/extended-property/full-text/DDL-trigger surfaces.
129
129
`Databases` is seeded at construction with all four system databases — `master` / `tempdb` / `model` / `msdb` (so `USE <systemdb>` / `master.sys.*` / `master.dbo.<proc>` / SSMS's `msdb.dbo.syspolicy_system_health_state` all resolve without an import); the first `CreateDbConnection()` lazily seeds `DefaultDatabaseName` (`"simulated"`) when no *user* database is present, and all four system databases are excluded from the initial-database fallback (`Simulation.SystemDatabaseNames`) so a fresh connection still lands on `simulated`.
@@ -270,7 +270,7 @@ Each entry below is a trigger: read the linked file on demand when working in th
Copy file name to clipboardExpand all lines: docs/claude/backlog.md
+1-2Lines changed: 1 addition & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,8 +37,7 @@ Remaining phases, roughly in value order:
37
37
Candidate follow-on legs within tool scope: Visual Studio's SQL Server Object Explorer (DacFx-driven, a different query dialect from SMO) and LINQPad.
38
38
-**SMO API sweep campaign** — `.vs/smo-sweep` (gitignored local harness) walks SMO's full reachable read surface against the self-hosted simulator and, identically, against the live reference, draining every `Property.Value` and `Script()`-ing every `IScriptable`; modes `sweep` / `sweep --live` / `diff` → sorted JSON reports + `reports/triage.md`; workflow = sweep both sides → triage → fix bundles → graduated `Tests.Smo` tests → re-sweep.
39
39
Open items from the latest triage: (a) `DBCC SHOW_STATISTICS … WITH STATS_STREAM` (SMO `Statistic.Stream`) stays `NotSupportedException` — it wants the raw serialized statistics-histogram blob, which the simulator has no faithful source for; (b) the unmodeled runtime/OS surfaces SMO reaches as absent objects (backup history `msdb.dbo.backupset`, `sys.dm_tran_persistent_version_store_stats`, file-space/IO DMVs, `sys.dm_os_process_memory`, `master.dbo.sysprocesses`, `FILEPROPERTY`, registry/OS xps) — surfaced as `PropertyCannotBeRetrievedException` / defaults, the legitimate-gap category.
40
-
-**Smaller fidelity items**: user-supplied `X509Certificate2` (a CA-trusted certificate instead of the ephemeral self-signed one; strict-mode clients can already pin the exposed `SimulatedNetworkListener.ServerCertificate`) and per-interface bind-address selection — add-on-demand public-surface expansions.
41
-
Open residuals of shipped wire features (details in [`tds-endpoint.md`](tds-endpoint.md)): cancel/attention reaction is bounded by the in-flight statement's materialization, not interruptible inside a single statement's row loop; MARS never raises Msg 8628/8651 and fully materializes each session's response under the execution gate.
40
+
-**Open residuals of shipped wire features** (details in [`tds-endpoint.md`](tds-endpoint.md)): cancel/attention reaction is bounded by the in-flight statement's materialization, not interruptible inside a single statement's row loop; MARS never raises Msg 8628/8651 and fully materializes each session's response under the execution gate.
42
41
-**Chunked `OFFSET/FETCH` paging: per-page constant factor, complexity class matches real** (probed 2026-07-18, plans + timings): real SQL Server also redoes the work on every page — `Top(OFFSET…)` over an ordered index scan reading offset+fetch rows when an index supplies the order, or a full scan + `Sort(TOP offset+fetch)` re-sorted per page when not; no cross-query sorted-result caching exists on either side, so "sort once, serve many pages" is rejected (it would invent behavior real doesn't have).
43
42
The residual is constant-factor only: the simulator materializes (and for non-index order, sorts) all n rows per page regardless of offset where real's indexed plan touches only offset+fetch (measured at 150k rows / fetch 100 / offset 140k: sim ~41 ms vs real ~13 ms indexed, ~116 ms vs ~22 ms unindexed — real's sort is also 16-way parallel).
44
43
Possible lever if paged drains ever matter: recognize index-supplied order in the `OFFSET/FETCH` path (real's plan shape) to skip the sort and bound the scan.
Copy file name to clipboardExpand all lines: docs/claude/tds-endpoint.md
+4-1Lines changed: 4 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,15 +4,18 @@
4
4
Returns `Task<SimulatedNetworkListener>`; `port: 0` binds an OS-assigned ephemeral port (read `Port`), the right shape for parallel tests.
5
5
Port-in-use surfaces as the raw `SocketException`.
6
6
The listener binds IPv4 loopback plus best-effort IPv6 loopback on the same port.
7
+
Both listen methods also take a **`SimulatedNetworkListenerOptions`** overload (`Port`, default 1433 matching the int overloads; `BindAddress`; `ServerCertificate`, default null = generate ephemeral): a supplied certificate must carry a private key (`ArgumentException` otherwise) and **stays owned by the caller — the listener never disposes it** — so one certificate serves many listeners (created once at suite setup, its public part exported once for strict-mode pinning instead of per-listener temp files).
8
+
`BindAddress` narrows `ListenNetworkAsync` from all interfaces to exactly one address — its family decides the socket family and **no best-effort other-family sibling is bound** — while `ListenLocalAsync` rejects a non-null value with `ArgumentException` (honoring it would put the loopback method's accept-anyone-until-`CREATE LOGIN` credential model on a network interface).
7
9
**`ListenNetworkAsync`** is the all-interfaces sibling (`IPAddress.Any` + best-effort `IPv6Any`, same core): it throws `InvalidOperationException` at call time when no logins are registered — the loopback listener's accept-anyone-until-`CREATE LOGIN` model must never face a network — and its XML docs carry the honest caveat that authentication is the *only* enforcement (no authorization model; every login has unrestricted access; the self-signed cert doesn't authenticate the server).
8
10
Oracle: `NetworkListenerTests`.
9
11
10
-
Connection-string requirements: `TrustServerCertificate=true` (the endpoint presents an ephemeral in-memory self-signed cert generated per listener) and credentials per the enforcement rule below (any credentials when no logins exist).
12
+
Connection-string requirements: `TrustServerCertificate=true` (the endpoint presents an ephemeral in-memory self-signed cert generated per listener, unless the options overload supplied one — a CA-trusted supplied certificate makes the flag unnecessary) and credentials per the enforcement rule below (any credentials when no logins exist).
11
13
Default/`Mandatory`/`Optional` all negotiate to full encryption via `ENCRYPT_REQ`.
12
14
A client that cannot do TLS at all (`ENCRYPT_NOT_SUP`) is disconnected after the prelogin response — there is no plaintext mode.
13
15
14
16
**`Encrypt=Strict` (TDS 8.0) ships**: the client opens with a bare TLS ClientHello negotiating ALPN `tds/8.0`, and every TDS packet — prelogin included — flows inside the TLS channel; the session routes on the first wire byte (TLS handshake record `0x16` vs cleartext PRELOGIN `0x12`).
15
17
SqlClient **ignores `TrustServerCertificate` in strict mode** and always validates the certificate (chain + hostname), so a strict client must pin instead: export `SimulatedNetworkListener.ServerCertificate` (the presented certificate, public part only) to a file and reference it with the connection string's `ServerCertificate` keyword (empirically confirmed against SqlClient 7.0.2 — `TrustServerCertificate=True` alone fails strict with `UntrustedRoot` + hostname mismatch).
18
+
Supplying one certificate through `SimulatedNetworkListenerOptions` makes the pin file a create-once artifact shared by every listener (the shape `StrictEncryptionTests` uses: one class-level certificate, its public part written to a fixed-name file in the OS temp directory).
16
19
The strict TLS handshake is not version-pinned (TLS 1.3 negotiates; raw records make NewSessionTicket harmless), and LOGINACK echoes TDS version `0x08000000` when LOGIN7 requested it.
17
20
MARS and `SqlBulkCopy` ride the strict channel unchanged.
0 commit comments