diff --git a/DotnetCore.sln b/DotnetCore.sln
index 4a8def12..e70da71d 100644
--- a/DotnetCore.sln
+++ b/DotnetCore.sln
@@ -72,9 +72,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "telemetry", "telemetry", "{
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LaunchDarkly.ServerSdk.Telemetry", "pkgs\telemetry\src\LaunchDarkly.ServerSdk.Telemetry.csproj", "{DE321396-6459-4C02-AF61-1A2677A7CB65}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sandbox", "sandbox", "{822D49A6-1DF2-49BB-A3C0-15821ED718D6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnet-server-sandbox", "sandbox\dotnet-server-sandbox\dotnet-server-sandbox.csproj", "{A10B580F-D937-4EA8-8CF8-4F130FBF6C16}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "repo-docs", "repo-docs", "{1A854A11-54BE-4978-B4FF-0A2AE2488C2A}"
+ ProjectSection(SolutionItems) = preProject
+ README.md = README.md
+ SECURITY.md = SECURITY.md
+ CONTRIBUTING.md = CONTRIBUTING.md
+ LICENSE = LICENSE
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ DebugLocalReferences|Any CPU = DebugLocalReferences|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
@@ -107,87 +120,134 @@ Global
{EF541D97-2C23-4FB8-BD87-ADFDF0FF83F3} = {0007CF48-139C-43C6-8A3A-2A2D1474F197}
{561F6F3D-09C5-470A-83AC-F0E97BAD609B} = {EF541D97-2C23-4FB8-BD87-ADFDF0FF83F3}
{DE321396-6459-4C02-AF61-1A2677A7CB65} = {FF3153CA-F727-4666-BA1E-5459BE34FBAB}
+ {A10B580F-D937-4EA8-8CF8-4F130FBF6C16} = {822D49A6-1DF2-49BB-A3C0-15821ED718D6}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D61D2EC-8D04-46E9-9E1B-1E029341F318}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {2D61D2EC-8D04-46E9-9E1B-1E029341F318}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB9C772D-00D1-47CD-940E-7D802D4FB59A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {DB9C772D-00D1-47CD-940E-7D802D4FB59A}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{D1DF71E8-6037-4E35-813A-07F5A27153C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1DF71E8-6037-4E35-813A-07F5A27153C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1DF71E8-6037-4E35-813A-07F5A27153C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1DF71E8-6037-4E35-813A-07F5A27153C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1DF71E8-6037-4E35-813A-07F5A27153C2}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1DF71E8-6037-4E35-813A-07F5A27153C2}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{A2733CF1-672F-41A8-8DF8-7340BF953457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2733CF1-672F-41A8-8DF8-7340BF953457}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2733CF1-672F-41A8-8DF8-7340BF953457}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2733CF1-672F-41A8-8DF8-7340BF953457}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A2733CF1-672F-41A8-8DF8-7340BF953457}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {A2733CF1-672F-41A8-8DF8-7340BF953457}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {F91A1EFE-5411-4100-A2D1-7C8D72090F05}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F91A1EFE-5411-4100-A2D1-7C8D72090F05}.Release|Any CPU.Build.0 = Release|Any CPU
{14026C03-B639-459C-8E23-B99E2FB68C10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14026C03-B639-459C-8E23-B99E2FB68C10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14026C03-B639-459C-8E23-B99E2FB68C10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14026C03-B639-459C-8E23-B99E2FB68C10}.Release|Any CPU.Build.0 = Release|Any CPU
+ {14026C03-B639-459C-8E23-B99E2FB68C10}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {14026C03-B639-459C-8E23-B99E2FB68C10}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {73F7605E-9D64-4719-9DBB-77DFD5E06BE5}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{1D41FF94-B814-4FF3-A565-518DC9759140}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D41FF94-B814-4FF3-A565-518DC9759140}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1D41FF94-B814-4FF3-A565-518DC9759140}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {1D41FF94-B814-4FF3-A565-518DC9759140}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{1D41FF94-B814-4FF3-A565-518DC9759140}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D41FF94-B814-4FF3-A565-518DC9759140}.Release|Any CPU.Build.0 = Release|Any CPU
{540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{540B751E-41AE-4D7C-9715-57BA5C97DAD7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {540B751E-41AE-4D7C-9715-57BA5C97DAD7}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {A543C2DE-42AB-4E2F-85DC-F6BEC77E7695}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{06C06727-7A8F-417E-9164-5C70AD96A94F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06C06727-7A8F-417E-9164-5C70AD96A94F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {06C06727-7A8F-417E-9164-5C70AD96A94F}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {06C06727-7A8F-417E-9164-5C70AD96A94F}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{06C06727-7A8F-417E-9164-5C70AD96A94F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06C06727-7A8F-417E-9164-5C70AD96A94F}.Release|Any CPU.Build.0 = Release|Any CPU
{537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.Release|Any CPU.Build.0 = Release|Any CPU
+ {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {537C0A25-938B-4B6D-B7BA-ED16DC0F5B11}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC8B417E-30D6-4654-BB6A-0BC9433CDE8C}.Release|Any CPU.Build.0 = Release|Any CPU
{DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC897FFA-36AA-4863-B23F-0ECEF5D17839}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {DC897FFA-36AA-4863-B23F-0ECEF5D17839}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6FFC943-F464-4E36-B07D-EB16D5DF6D32}.Release|Any CPU.Build.0 = Release|Any CPU
{8C027074-CF8D-437F-9CE8-0F8180E496AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C027074-CF8D-437F-9CE8-0F8180E496AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C027074-CF8D-437F-9CE8-0F8180E496AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C027074-CF8D-437F-9CE8-0F8180E496AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C027074-CF8D-437F-9CE8-0F8180E496AA}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C027074-CF8D-437F-9CE8-0F8180E496AA}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{ED864025-2BDC-4AED-8A53-FAB852772132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED864025-2BDC-4AED-8A53-FAB852772132}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED864025-2BDC-4AED-8A53-FAB852772132}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED864025-2BDC-4AED-8A53-FAB852772132}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ED864025-2BDC-4AED-8A53-FAB852772132}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {ED864025-2BDC-4AED-8A53-FAB852772132}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.DebugLocalReferences|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C9BDA1A-6AB3-4B52-8CBB-6B702FABC292}.DebugLocalReferences|Any CPU.Build.0 = Debug|Any CPU
{561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {561F6F3D-09C5-470A-83AC-F0E97BAD609B}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{561F6F3D-09C5-470A-83AC-F0E97BAD609B}.Release|Any CPU.Build.0 = Release|Any CPU
{DE321396-6459-4C02-AF61-1A2677A7CB65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE321396-6459-4C02-AF61-1A2677A7CB65}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DE321396-6459-4C02-AF61-1A2677A7CB65}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {DE321396-6459-4C02-AF61-1A2677A7CB65}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
{DE321396-6459-4C02-AF61-1A2677A7CB65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE321396-6459-4C02-AF61-1A2677A7CB65}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.DebugLocalReferences|Any CPU.ActiveCfg = DebugLocalReferences|Any CPU
+ {A10B580F-D937-4EA8-8CF8-4F130FBF6C16}.DebugLocalReferences|Any CPU.Build.0 = DebugLocalReferences|Any CPU
EndGlobalSection
EndGlobal
diff --git a/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj b/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj
index b0180227..0ebac19b 100644
--- a/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj
+++ b/pkgs/dotnet-server-sdk-consul/src/LaunchDarkly.ServerSdk.Consul.csproj
@@ -20,17 +20,53 @@
true
snupkg
LaunchDarkly.Sdk.Server.Integrations
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
+
+
+
+
+
+
+
+
+
+
+
+ CHANGELOG.md
+
+
+ CONTRIBUTING.md
+
+
+ docfx.json
+
+
+ index.md
+
+
+ README.md
+
+
+ SECURITY.md
+
+
+
bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.ServerSdk.Consul.xml
diff --git a/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj b/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj
index 3a104d5c..501eb0d5 100644
--- a/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj
+++ b/pkgs/dotnet-server-sdk-dynamodb/src/LaunchDarkly.ServerSdk.DynamoDB.csproj
@@ -20,13 +20,48 @@
true
snupkg
LaunchDarkly.Sdk.Server.Integrations
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
+
+
+
+
+
+
+
+
+
+
+ CHANGELOG.md
+
+
+ CONTRIBUTING.md
+
+
+ docfx.json
+
+
+ index.md
+
+
+ README.md
+
+
+ SECURITY.md
+
+
+
bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.ServerSdk.DynamoDB.xml
diff --git a/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj b/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj
index 8bcb70ef..3e1278f5 100644
--- a/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj
+++ b/pkgs/dotnet-server-sdk-redis/src/LaunchDarkly.ServerSdk.Redis.csproj
@@ -20,13 +20,45 @@
true
snupkg
LaunchDarkly.Sdk.Server.Integrations
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
-
+
+
+
+
+
+
+
+
+
+
+
+ CHANGELOG.md
+
+
+ CONTRIBUTING.md
+
+
+ docfx.json
+
+
+ README.md
+
+
+ SECURITY.md
+
+
+
bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.ServerSdk.Redis.xml
diff --git a/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj b/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj
index 37085312..37533a3d 100644
--- a/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj
+++ b/pkgs/sdk/client/src/LaunchDarkly.ClientSdk.csproj
@@ -37,6 +37,12 @@
1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
@@ -118,6 +124,23 @@
+
+
+ CHANGELOG.md
+
+
+ CONTRIBUTING.md
+
+
+ index.md
+
+
+ README.md
+
+
+ toc.yml
+
+
../../../../LaunchDarkly.ClientSdk.snk
true
diff --git a/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj b/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj
index 695c713f..c218056c 100644
--- a/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj
+++ b/pkgs/sdk/server-ai/src/LaunchDarkly.ServerSdk.Ai.csproj
@@ -35,13 +35,51 @@
1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
-
+
+
+
+
+
+
+
+
+
+
+
+ CHANGELOG.md
+
+
+ CONTRIBUTING.md
+
+
+ docfx.json
+
+
+ docs-src\namespaces\LaunchDarkly.Sdk.Server.Ai.md
+
+
+ docs-src\README.md
+
+
+ index.md
+
+
+ README.md
+
+
+
../../../../LaunchDarkly.snk
true
diff --git a/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj b/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj
index 67102b1f..ac18b50a 100644
--- a/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj
+++ b/pkgs/sdk/server/src/LaunchDarkly.ServerSdk.csproj
@@ -35,6 +35,12 @@
1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
@@ -51,6 +57,45 @@
+
+
+ CHANGELOG.md
+
+
+ CONTRIBUTING.md
+
+
+ docfx.json
+
+
+ docs-src\namespaces\LaunchDarkly.Sdk.Json.md
+
+
+ docs-src\namespaces\LaunchDarkly.Sdk.md
+
+
+ docs-src\namespaces\LaunchDarkly.Sdk.Server.Integrations.md
+
+
+ docs-src\namespaces\LaunchDarkly.Sdk.Server.Interfaces.md
+
+
+ docs-src\namespaces\LaunchDarkly.Sdk.Server.md
+
+
+ docs-src\namespaces\LaunchDarkly.Sdk.Server.Subsystems.md
+
+
+ docs-src\README.md
+
+
+ index.md
+
+
+ README.md
+
+
+
../../../../LaunchDarkly.snk
true
diff --git a/pkgs/sdk/server/src/Properties/AssemblyInfo.cs b/pkgs/sdk/server/src/Properties/AssemblyInfo.cs
index d40c5c1d..a732335e 100644
--- a/pkgs/sdk/server/src/Properties/AssemblyInfo.cs
+++ b/pkgs/sdk/server/src/Properties/AssemblyInfo.cs
@@ -14,7 +14,7 @@
// Allow unit tests to see internal classes (note, the test assembly is not signed;
// tests must be run against the Debug configuration of this assembly)
[assembly: InternalsVisibleTo("LaunchDarkly.ServerSdk.Tests")]
-[assembly: InternalsVisibleTo("dotnet-server-test-app")]
+[assembly: InternalsVisibleTo("dotnet-server-sandbox")]
// Allow contract tests to see internal classes
[assembly: InternalsVisibleTo("ContractTestService")]
diff --git a/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj b/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj
index a74fd8e4..921daaf5 100644
--- a/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj
+++ b/pkgs/shared/common/src/LaunchDarkly.CommonSdk.csproj
@@ -34,6 +34,12 @@
bin\$(Configuration)\$(TargetFramework)\LaunchDarkly.CommonSdk.xml
LaunchDarkly.Sdk
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
diff --git a/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj b/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj
index dd78456f..5c14f270 100644
--- a/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj
+++ b/pkgs/shared/dotnet-server-sdk-shared-tests/src/LaunchDarkly.ServerSdk.SharedTests.csproj
@@ -10,11 +10,26 @@
Copyright 2020 Catamorphic, Co.
Apache-2.0
LaunchDarkly.Sdk.Server.SharedTests
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+ DEBUG;TRACE
-
+
+
+
+
+
+
+
+
+
+
diff --git a/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj b/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj
index d7f332eb..9818d80f 100644
--- a/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj
+++ b/pkgs/telemetry/src/LaunchDarkly.ServerSdk.Telemetry.csproj
@@ -34,17 +34,41 @@
1570,1571,1572,1573,1574,1580,1581,1584,1591,1710,1711,1712
+ Debug;Release;DebugLocalReferences
+ AnyCPU
-
+
+ DEBUG;TRACE
+
+
+
+
+
+
+
+
+
+
+
+ CHANGELOG.md
+
+
+ docfx.json
+
+
+ index.md
+
+
+
../../../LaunchDarkly.snk
true
diff --git a/sandbox/dotnet-server-sandbox/Configuration/DataSystemConfigurationBuilder.cs b/sandbox/dotnet-server-sandbox/Configuration/DataSystemConfigurationBuilder.cs
new file mode 100644
index 00000000..c9354353
--- /dev/null
+++ b/sandbox/dotnet-server-sandbox/Configuration/DataSystemConfigurationBuilder.cs
@@ -0,0 +1,108 @@
+using LaunchDarkly.Sdk.Server;
+using LaunchDarkly.Sdk.Server.Integrations;
+
+namespace dotnet_server_test_app.Configuration;
+
+///
+/// Builds DataSystem configurations based on environment variables.
+///
+internal static class DataSystemConfigurationBuilder
+{
+ ///
+ /// Builds a DataSystem configuration based on LAUNCHDARKLY_DATA_SYSTEM_MODE environment variable.
+ /// Returns null if using the default mode (which doesn't need explicit configuration).
+ ///
+ internal static DataSystemBuilder? Build()
+ {
+ var mode = EnvironmentVariables.GetString(
+ EnvironmentVariables.DataSystemMode,
+ EnvironmentVariables.DefaultDataSystemMode);
+
+ return mode.ToLower() switch
+ {
+ "default" => BuildDefault(),
+ "streaming" => BuildStreaming(),
+ "polling" => BuildPolling(),
+ "daemon" => BuildDaemon(),
+ "persistent-store" => BuildPersistentStore(),
+ _ => throw new ArgumentException(
+ $"Invalid data system mode: got '{mode}', expected one of: default, streaming, polling, daemon, persistent-store")
+ };
+ }
+
+ ///
+ /// Builds the default DataSystem configuration (CDN + streaming with fallback).
+ ///
+ private static DataSystemBuilder BuildDefault()
+ {
+ return Components.DataSystem().Default();
+ }
+
+ ///
+ /// Builds a streaming-only DataSystem configuration.
+ ///
+ private static DataSystemBuilder BuildStreaming()
+ {
+ return Components.DataSystem().Streaming();
+ }
+
+ ///
+ /// Builds a polling-only DataSystem configuration.
+ ///
+ private static DataSystemBuilder BuildPolling()
+ {
+ return Components.DataSystem().Polling();
+ }
+
+ ///
+ /// Builds a daemon mode DataSystem configuration (read-only from persistent store).
+ /// Requires a persistent store to be configured.
+ ///
+ private static DataSystemBuilder BuildDaemon()
+ {
+ var persistentStore = PersistentStoreConfigurationBuilder.Build();
+
+ if (persistentStore == null)
+ {
+#if DEBUG_LOCAL_REFERENCES
+ throw new InvalidOperationException(
+ $"{EnvironmentVariables.DataSystemMode} is set to 'daemon' but {EnvironmentVariables.PersistentStoreType} is not configured. " +
+ "Daemon mode requires a persistent store.");
+#else
+ Console.WriteLine("ERROR: Daemon mode requires a persistent store, but persistent store support is not available in this build configuration.");
+ Console.WriteLine("Please rebuild with DebugLocalReferences configuration to use Redis or DynamoDB persistent stores.");
+ Console.WriteLine(" dotnet build -c DebugLocalReferences");
+ throw new InvalidOperationException(
+ "Daemon mode requires persistent store support. Rebuild with DebugLocalReferences configuration.");
+#endif
+ }
+
+ return Components.DataSystem().Daemon(persistentStore);
+ }
+
+ ///
+ /// Builds a persistent store DataSystem configuration (default mode + persistent store backup).
+ /// Requires a persistent store to be configured.
+ ///
+ private static DataSystemBuilder BuildPersistentStore()
+ {
+ var persistentStore = PersistentStoreConfigurationBuilder.Build();
+
+ if (persistentStore == null)
+ {
+#if DEBUG_LOCAL_REFERENCES
+ throw new InvalidOperationException(
+ $"{EnvironmentVariables.DataSystemMode} is set to 'persistent-store' but {EnvironmentVariables.PersistentStoreType} is not configured. " +
+ "Persistent-store mode requires a persistent store.");
+#else
+ Console.WriteLine("ERROR: Persistent-store mode requires a persistent store, but persistent store support is not available in this build configuration.");
+ Console.WriteLine("Please rebuild with DebugLocalReferences configuration to use Redis or DynamoDB persistent stores.");
+ Console.WriteLine(" dotnet build -c DebugLocalReferences");
+ throw new InvalidOperationException(
+ "Persistent-store mode requires persistent store support. Rebuild with DebugLocalReferences configuration.");
+#endif
+ }
+
+ return Components.DataSystem().PersistentStore(persistentStore);
+ }
+}
diff --git a/sandbox/dotnet-server-sandbox/Configuration/EnvironmentVariables.cs b/sandbox/dotnet-server-sandbox/Configuration/EnvironmentVariables.cs
new file mode 100644
index 00000000..ebd6bf43
--- /dev/null
+++ b/sandbox/dotnet-server-sandbox/Configuration/EnvironmentVariables.cs
@@ -0,0 +1,110 @@
+namespace dotnet_server_test_app.Configuration;
+
+///
+/// Centralized environment variable names, defaults, and parsing utilities for SDK configuration.
+///
+public static class EnvironmentVariables
+{
+ // Environment variable names
+ public const string SdkKey = "LAUNCHDARKLY_SDK_KEY";
+ public const string Offline = "LAUNCHDARKLY_OFFLINE";
+ public const string DataSystemMode = "LAUNCHDARKLY_DATA_SYSTEM_MODE";
+ public const string StartWaitTimeMs = "LAUNCHDARKLY_START_WAIT_TIME_MS";
+ public const string PersistentStoreType = "LAUNCHDARKLY_PERSISTENT_STORE_TYPE";
+
+ // Redis configuration
+ public const string RedisHost = "LAUNCHDARKLY_REDIS_HOST";
+ public const string RedisPort = "LAUNCHDARKLY_REDIS_PORT";
+ public const string RedisPrefix = "LAUNCHDARKLY_REDIS_PREFIX";
+ public const string RedisConnectTimeoutMs = "LAUNCHDARKLY_REDIS_CONNECT_TIMEOUT_MS";
+ public const string RedisOperationTimeoutMs = "LAUNCHDARKLY_REDIS_OPERATION_TIMEOUT_MS";
+
+ // DynamoDB configuration
+ public const string DynamoDBTableName = "LAUNCHDARKLY_DYNAMODB_TABLE_NAME";
+ public const string DynamoDBPrefix = "LAUNCHDARKLY_DYNAMODB_PREFIX";
+
+ // Default values
+ public const bool DefaultOffline = false;
+ public const string DefaultDataSystemMode = "default";
+ public const int DefaultStartWaitTimeMs = 10000;
+
+ public const string DefaultRedisHost = "localhost";
+ public const int DefaultRedisPort = 6379;
+ public const string DefaultRedisPrefix = "launchdarkly";
+ public const int DefaultRedisConnectTimeoutMs = 5000;
+ public const int DefaultRedisOperationTimeoutMs = 3000;
+
+ public const string DefaultDynamoDBPrefix = "";
+
+ ///
+ /// Gets a string environment variable value or returns the default if not set.
+ ///
+ public static string GetString(string varName, string defaultValue)
+ {
+ var value = Environment.GetEnvironmentVariable(varName);
+ return string.IsNullOrEmpty(value) ? defaultValue : value;
+ }
+
+ ///
+ /// Parses an integer environment variable value or returns the default if not set.
+ /// Throws FormatException if the value is invalid.
+ ///
+ public static int ParseInt(string varName, int defaultValue)
+ {
+ var value = Environment.GetEnvironmentVariable(varName);
+ if (string.IsNullOrEmpty(value))
+ {
+ return defaultValue;
+ }
+
+ if (int.TryParse(value, out var result))
+ {
+ return result;
+ }
+
+ throw new FormatException($"Invalid integer value for {varName}: got '{value}', expected a valid integer");
+ }
+
+ ///
+ /// Parses a boolean environment variable value or returns the default if not set.
+ /// Accepts "true"/"false" (case insensitive).
+ /// Throws FormatException if the value is invalid.
+ ///
+ public static bool ParseBool(string varName, bool defaultValue)
+ {
+ var value = Environment.GetEnvironmentVariable(varName);
+ if (string.IsNullOrEmpty(value))
+ {
+ return defaultValue;
+ }
+
+ if (bool.TryParse(value, out var result))
+ {
+ return result;
+ }
+
+ throw new FormatException($"Invalid boolean value for {varName}: got '{value}', expected 'true' or 'false'");
+ }
+
+ ///
+ /// Parses an enum environment variable value or returns the default if not set.
+ /// Enum values should be provided as strings matching enum names (case insensitive).
+ /// Throws ArgumentException if the value is invalid.
+ ///
+ public static T ParseEnum(string varName, T defaultValue, string[] validValues) where T : struct
+ {
+ var value = Environment.GetEnvironmentVariable(varName);
+ if (string.IsNullOrEmpty(value))
+ {
+ return defaultValue;
+ }
+
+ if (Enum.TryParse(value, ignoreCase: true, out var result))
+ {
+ return result;
+ }
+
+ var validValuesStr = string.Join(", ", validValues);
+ throw new ArgumentException($"Invalid value for {varName}: got '{value}', expected one of: {validValuesStr}");
+ }
+}
diff --git a/sandbox/dotnet-server-sandbox/Configuration/PersistentStoreConfigurationBuilder.cs b/sandbox/dotnet-server-sandbox/Configuration/PersistentStoreConfigurationBuilder.cs
new file mode 100644
index 00000000..95fdf8c3
--- /dev/null
+++ b/sandbox/dotnet-server-sandbox/Configuration/PersistentStoreConfigurationBuilder.cs
@@ -0,0 +1,109 @@
+using LaunchDarkly.Sdk.Server;
+#if DEBUG_LOCAL_REFERENCES
+using LaunchDarkly.Sdk.Server.Integrations;
+#endif
+using LaunchDarkly.Sdk.Server.Subsystems;
+
+namespace dotnet_server_test_app.Configuration;
+
+///
+/// Builds persistent store configurations (Redis or DynamoDB) from environment variables.
+/// Note: Redis and DynamoDB support is only available when building with DebugLocalReferences configuration.
+///
+internal static class PersistentStoreConfigurationBuilder
+{
+ ///
+ /// Builds a persistent store configuration based on LAUNCHDARKLY_PERSISTENT_STORE_TYPE environment variable.
+ /// Returns null if no persistent store is configured.
+ ///
+ internal static IComponentConfigurer? Build()
+ {
+ var storeType = Environment.GetEnvironmentVariable(EnvironmentVariables.PersistentStoreType);
+
+ if (string.IsNullOrEmpty(storeType))
+ {
+ return null;
+ }
+
+ return storeType.ToLower() switch
+ {
+ "redis" => BuildRedisStore(),
+ "dynamodb" => BuildDynamoDBStore(),
+ _ => throw new ArgumentException(
+ $"Invalid persistent store type: got '{storeType}', expected one of: redis, dynamodb")
+ };
+ }
+
+#if DEBUG_LOCAL_REFERENCES
+ ///
+ /// Builds a Redis persistent store configuration from environment variables.
+ ///
+ private static IComponentConfigurer BuildRedisStore()
+ {
+ var host = EnvironmentVariables.GetString(EnvironmentVariables.RedisHost, EnvironmentVariables.DefaultRedisHost);
+ var port = EnvironmentVariables.ParseInt(EnvironmentVariables.RedisPort, EnvironmentVariables.DefaultRedisPort);
+ var prefix = EnvironmentVariables.GetString(EnvironmentVariables.RedisPrefix, EnvironmentVariables.DefaultRedisPrefix);
+ var connectTimeoutMs = EnvironmentVariables.ParseInt(
+ EnvironmentVariables.RedisConnectTimeoutMs,
+ EnvironmentVariables.DefaultRedisConnectTimeoutMs);
+ var operationTimeoutMs = EnvironmentVariables.ParseInt(
+ EnvironmentVariables.RedisOperationTimeoutMs,
+ EnvironmentVariables.DefaultRedisOperationTimeoutMs);
+
+ var redisBuilder = Redis.DataStore()
+ .HostAndPort(host, port)
+ .Prefix(prefix)
+ .ConnectTimeout(TimeSpan.FromMilliseconds(connectTimeoutMs))
+ .OperationTimeout(TimeSpan.FromMilliseconds(operationTimeoutMs));
+
+ return Components.PersistentDataStore(redisBuilder);
+ }
+
+ ///
+ /// Builds a DynamoDB persistent store configuration from environment variables.
+ ///
+ private static IComponentConfigurer BuildDynamoDBStore()
+ {
+ var tableName = Environment.GetEnvironmentVariable(EnvironmentVariables.DynamoDBTableName);
+
+ if (string.IsNullOrEmpty(tableName))
+ {
+ throw new InvalidOperationException(
+ $"{EnvironmentVariables.DynamoDBTableName} is required when using DynamoDB persistent store");
+ }
+
+ var prefix = EnvironmentVariables.GetString(
+ EnvironmentVariables.DynamoDBPrefix,
+ EnvironmentVariables.DefaultDynamoDBPrefix);
+
+ var builder = DynamoDB.DataStore(tableName);
+
+ if (!string.IsNullOrEmpty(prefix))
+ {
+ builder.Prefix(prefix);
+ }
+
+ return Components.PersistentDataStore(builder);
+ }
+#else
+ ///
+ /// Stub for Redis store when not building with DebugLocalReferences.
+ ///
+ private static IComponentConfigurer? BuildRedisStore()
+ {
+ Console.WriteLine("WARNING: Redis persistent store is only available when building with DebugLocalReferences configuration.");
+ Console.WriteLine("Current build does not include Redis integration. Persistent store will not be used.");
+ return null;
+ }
+
+ ///
+ /// Stub for DynamoDB store when not building with DebugLocalReferences.
+ ///
+ private static IComponentConfigurer? BuildDynamoDBStore()
+ {
+ Console.WriteLine("WARNING: DynamoDB persistent store is only available when building with DebugLocalReferences configuration.");
+ Console.WriteLine("Current build does not include DynamoDB integration. Persistent store will not be used.");
+ return null;
+ }
+#endif
+}
diff --git a/sandbox/dotnet-server-sandbox/Configuration/SdkConfigurationBuilder.cs b/sandbox/dotnet-server-sandbox/Configuration/SdkConfigurationBuilder.cs
new file mode 100644
index 00000000..318db12c
--- /dev/null
+++ b/sandbox/dotnet-server-sandbox/Configuration/SdkConfigurationBuilder.cs
@@ -0,0 +1,60 @@
+using LaunchDarkly.Sdk.Server;
+
+namespace dotnet_server_test_app.Configuration;
+
+///
+/// Main configuration builder that reads environment variables and builds SDK configuration.
+///
+public static class SdkConfigurationBuilder
+{
+ ///
+ /// Builds a LaunchDarkly SDK configuration from environment variables.
+ ///
+ /// A configured Configuration object ready for use with LdClient
+ /// Thrown when LAUNCHDARKLY_SDK_KEY is not set
+ /// Thrown when configuration is inconsistent
+ /// Thrown when an invalid value is provided
+ /// Thrown when a value cannot be parsed
+ public static LaunchDarkly.Sdk.Server.Configuration BuildFromEnvironment()
+ {
+ // 1. Validate SDK key exists (required)
+ var sdkKey = Environment.GetEnvironmentVariable(EnvironmentVariables.SdkKey);
+ if (string.IsNullOrEmpty(sdkKey))
+ {
+ throw new ArgumentNullException(
+ EnvironmentVariables.SdkKey,
+ $"{EnvironmentVariables.SdkKey} environment variable is required");
+ }
+
+ // 2. Create configuration builder
+ var builder = LaunchDarkly.Sdk.Server.Configuration.Builder(sdkKey);
+
+ // 3. Apply offline mode if specified
+ var offline = EnvironmentVariables.ParseBool(
+ EnvironmentVariables.Offline,
+ EnvironmentVariables.DefaultOffline);
+ if (offline)
+ {
+ builder.Offline(true);
+ }
+
+ // 4. Apply DataSystem configuration (if not offline)
+ if (!offline)
+ {
+ var dataSystem = DataSystemConfigurationBuilder.Build();
+ if (dataSystem != null)
+ {
+ builder.DataSystem(dataSystem);
+ }
+ }
+
+ // 5. Apply start wait time
+ var startWaitTimeMs = EnvironmentVariables.ParseInt(
+ EnvironmentVariables.StartWaitTimeMs,
+ EnvironmentVariables.DefaultStartWaitTimeMs);
+ builder.StartWaitTime(TimeSpan.FromMilliseconds(startWaitTimeMs));
+
+ // 6. Build and return
+ return builder.Build();
+ }
+}
diff --git a/sandbox/dotnet-server-sandbox/Program.cs b/sandbox/dotnet-server-sandbox/Program.cs
new file mode 100644
index 00000000..a83bf573
--- /dev/null
+++ b/sandbox/dotnet-server-sandbox/Program.cs
@@ -0,0 +1,48 @@
+// See https://aka.ms/new-console-template for more information
+
+using dotnet_server_test_app.Configuration;
+using LaunchDarkly.Sdk;
+using LaunchDarkly.Sdk.Server;
+
+Configuration config;
+try
+{
+ config = SdkConfigurationBuilder.BuildFromEnvironment();
+}
+catch (Exception ex)
+{
+ Console.WriteLine($"Configuration Error: {ex.Message}");
+ return 1;
+}
+
+Console.WriteLine("Initializing client");
+var client = new LdClient(config);
+
+client.DataSourceStatusProvider.StatusChanged += (sender, status) =>
+{
+ Console.WriteLine($"Status changed: {status}");
+};
+
+client.DataStoreStatusProvider.StatusChanged += (sender, status) =>
+{
+ Console.WriteLine($"Status changed: {status}");
+};
+
+Console.WriteLine($"Data source status {client.DataSourceStatusProvider.Status}");
+Console.WriteLine($"Data store status {client.DataStoreStatusProvider.Status}");
+
+Console.WriteLine($"Initialized: {client.Initialized}");
+
+Console.WriteLine($"my-boolean-flag: {client.BoolVariation("my-boolean-flag", Context.New("bob"), false)}");
+
+client.FlagTracker.FlagChanged += client.FlagTracker.FlagValueChangeHandler("my-boolean-flag", Context.New("bob"),
+ ((sender, @event) => { Console.WriteLine("Got change {0}, {1}", @event.Key, @event.NewValue); }));
+
+Console.WriteLine("Evaluate {0}", client.BoolVariation("my-boolean-flag", Context.New("bob"), false));
+
+while (true)
+{
+ Console.ReadLine();
+
+ Console.WriteLine($"my-boolean-flag: {client.BoolVariation("my-boolean-flag", Context.New("bob"), false)}");
+}
diff --git a/sandbox/dotnet-server-sandbox/README.md b/sandbox/dotnet-server-sandbox/README.md
new file mode 100644
index 00000000..a3c17d5b
--- /dev/null
+++ b/sandbox/dotnet-server-sandbox/README.md
@@ -0,0 +1,288 @@
+# LaunchDarkly .NET Server SDK Sandbox - Environment Variable Configuration
+
+This sandbox application supports configuration through environment variables, allowing you to test different SDK configurations.
+
+## Quick Start
+
+The minimal configuration requires only the SDK key:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="your-sdk-key-here"
+dotnet run
+```
+
+## Build Configuration Requirements
+
+### Persistent Store Support (Redis and DynamoDB)
+
+**Important:** Redis and DynamoDB persistent store integrations are only available when building with the `DebugLocalReferences` configuration.
+
+```bash
+# Run with persistent store support
+export LAUNCHDARKLY_SDK_KEY="your-sdk-key"
+export LAUNCHDARKLY_DATA_SYSTEM_MODE="persistent-store"
+export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis"
+dotnet run --configuration DebugLocalReferences
+```
+
+**Why DebugLocalReferences?**
+
+This is required to be able to use local dependencies without building them with the strong-naming key. This project uses a project reference for the Server SDK and the persistent stores also need to be using a project reference. If they use the nuget references, then the strong naming requirement will prevent the project from building/running.
+
+**What works in other configurations (Debug/Release):**
+- Default mode
+- Streaming-only mode
+- Polling-only mode
+- Offline mode
+
+**What requires DebugLocalReferences:**
+- Daemon mode (read-only from persistent store)
+- Persistent-store mode (default + persistent store backup)
+
+If you attempt to use persistent store features without building with DebugLocalReferences, you'll see a clear warning message and the application will either fall back to in-memory storage or fail with an informative error.
+
+## Environment Variables Reference
+
+### Required Variables
+
+| Variable | Description | Example |
+|----------|-------------|---------|
+| `LAUNCHDARKLY_SDK_KEY` | Your LaunchDarkly SDK key (required) | `sdk-abc-123-xyz` |
+
+### Optional - Core Configuration
+
+| Variable | Type | Default | Description |
+|----------|------|---------|-------------|
+| `LAUNCHDARKLY_OFFLINE` | Boolean | `false` | Run SDK in offline mode (no connections to LaunchDarkly) |
+| `LAUNCHDARKLY_DATA_SYSTEM_MODE` | Enum | `default` | Data acquisition strategy (see modes below) |
+| `LAUNCHDARKLY_START_WAIT_TIME_MS` | Integer | `10000` | Maximum time (ms) to wait for SDK initialization |
+
+#### Data System Modes
+
+| Mode | Description |
+|------|----------------------------------------------------|
+| `default` | poll + streaming with polling fallback |
+| `streaming` | Real-time streaming updates only |
+| `polling` | Periodic polling only, no streaming |
+| `daemon` | Read-only from persistent store |
+| `persistent-store` | Default mode + persistent store backup |
+
+### Optional - Persistent Store Configuration
+
+| Variable | Type | Default | Description |
+|----------|------|---------|-------------|
+| `LAUNCHDARKLY_PERSISTENT_STORE_TYPE` | Enum | (none) | Type of persistent store: `redis` or `dynamodb` |
+
+**Note:** Required when using `daemon` or `persistent-store` data system modes.
+
+### Optional - Redis Configuration
+
+These variables apply when `LAUNCHDARKLY_PERSISTENT_STORE_TYPE=redis`:
+
+| Variable | Type | Default | Description |
+|----------|------|---------|-------------|
+| `LAUNCHDARKLY_REDIS_HOST` | String | `localhost` | Redis server hostname |
+| `LAUNCHDARKLY_REDIS_PORT` | Integer | `6379` | Redis server port |
+| `LAUNCHDARKLY_REDIS_PREFIX` | String | `launchdarkly` | Key prefix for all Redis keys |
+| `LAUNCHDARKLY_REDIS_CONNECT_TIMEOUT_MS` | Integer | `5000` | Connection timeout in milliseconds |
+| `LAUNCHDARKLY_REDIS_OPERATION_TIMEOUT_MS` | Integer | `3000` | Operation timeout in milliseconds |
+
+### Optional - DynamoDB Configuration
+
+These variables apply when `LAUNCHDARKLY_PERSISTENT_STORE_TYPE=dynamodb`:
+
+| Variable | Type | Default | Description |
+|----------|------|---------|-------------|
+| `LAUNCHDARKLY_DYNAMODB_TABLE_NAME` | String | (required) | DynamoDB table name (must exist) |
+| `LAUNCHDARKLY_DYNAMODB_PREFIX` | String | `""` | Key prefix for DynamoDB items |
+
+**DynamoDB Table Requirements:**
+- Partition key: `namespace` (String)
+- Sort key: `key` (String)
+
+## Configuration Examples
+
+### 1. Default Mode (Recommended)
+
+Minimal configuration with just SDK key. Uses CDN + streaming:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+dotnet run
+```
+
+### 2. Offline Mode
+
+For testing without connecting to LaunchDarkly:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="any-value"
+export LAUNCHDARKLY_OFFLINE="true"
+dotnet run
+```
+
+### 3. Redis Persistent Store
+
+Default mode backed by Redis persistent store:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+export LAUNCHDARKLY_DATA_SYSTEM_MODE="persistent-store"
+export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis"
+export LAUNCHDARKLY_REDIS_HOST="redis.example.com"
+export LAUNCHDARKLY_REDIS_PORT="6379"
+export LAUNCHDARKLY_REDIS_PREFIX="myapp:prod"
+dotnet run
+```
+
+### 4. Daemon Mode with Redis
+
+Read-only mode for SDKs behind Relay Proxy:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+export LAUNCHDARKLY_DATA_SYSTEM_MODE="daemon"
+export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis"
+export LAUNCHDARKLY_REDIS_HOST="localhost"
+export LAUNCHDARKLY_REDIS_PREFIX="ld:relay:prod"
+dotnet run
+```
+
+### 5. DynamoDB Persistent Store
+
+Default mode backed by DynamoDB:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+export LAUNCHDARKLY_DATA_SYSTEM_MODE="persistent-store"
+export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="dynamodb"
+export LAUNCHDARKLY_DYNAMODB_TABLE_NAME="launchdarkly-features"
+export LAUNCHDARKLY_DYNAMODB_PREFIX="myapp"
+dotnet run
+```
+
+### 6. Streaming-Only Mode
+
+Real-time updates without CDN initialization:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+export LAUNCHDARKLY_DATA_SYSTEM_MODE="streaming"
+dotnet run
+```
+
+### 7. Polling-Only Mode
+
+For restricted network environments:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+export LAUNCHDARKLY_DATA_SYSTEM_MODE="polling"
+dotnet run
+```
+
+### 8. Custom Timeouts
+
+Adjust SDK behavior for slow networks:
+
+```bash
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+export LAUNCHDARKLY_START_WAIT_TIME_MS="30000"
+export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="redis"
+export LAUNCHDARKLY_REDIS_CONNECT_TIMEOUT_MS="10000"
+export LAUNCHDARKLY_REDIS_OPERATION_TIMEOUT_MS="5000"
+dotnet run
+```
+
+## Data System Modes Explained
+
+### Default Mode
+**Use when:** You want LaunchDarkly's recommended configuration (best for most production scenarios)
+
+**How it works:**
+1. Fetches initial data from global CDN (fast)
+2. Establishes streaming connection for real-time updates
+3. Falls back to polling if streaming is interrupted
+
+### Streaming Mode
+**Use when:** You need real-time updates without CDN initialization delay
+
+**How it works:**
+- Establishes streaming connection immediately
+- Receives real-time updates as flags change
+- Can fall back to polling if instructed by LaunchDarkly
+
+### Polling Mode
+**Use when:** Your network doesn't support streaming (firewall restrictions, etc.)
+
+**How it works:**
+- Periodically polls LaunchDarkly CDN for updates
+- No real-time updates
+- Predictable network traffic pattern
+
+### Daemon Mode
+**Use when:** Multiple SDK instances need to share flag data via Relay Proxy
+
+**How it works:**
+- SDK never connects to LaunchDarkly
+- Reads flag data from persistent store (populated by Relay Proxy or another SDK)
+- SDK never writes to the store (read-only)
+
+**Requirements:** Must configure `LAUNCHDARKLY_PERSISTENT_STORE_TYPE`
+
+### Persistent Store Mode
+**Use when:** You want fast startup times and resilience to temporary network issues
+
+**How it works:**
+- Uses default mode (CDN + streaming)
+- Maintains a persistent store with latest flag data
+- On startup, can serve flags from store while waiting for fresh data
+- Keeps store up-to-date as new data arrives
+
+**Requirements:** Must configure `LAUNCHDARKLY_PERSISTENT_STORE_TYPE`
+
+## Troubleshooting
+
+### Error: "LAUNCHDARKLY_SDK_KEY environment variable is required"
+**Solution:** Set the `LAUNCHDARKLY_SDK_KEY` environment variable before running the application.
+
+### Error: "Invalid data system mode"
+**Solution:** Check that `LAUNCHDARKLY_DATA_SYSTEM_MODE` is set to one of: `default`, `streaming`, `polling`, `daemon`, or `persistent-store`.
+
+### Error: "daemon mode requires a persistent store"
+**Solution:** When using daemon or persistent-store modes, you must set `LAUNCHDARKLY_PERSISTENT_STORE_TYPE` to either `redis` or `dynamodb`.
+
+### Error: "LAUNCHDARKLY_DYNAMODB_TABLE_NAME is required"
+**Solution:** When using DynamoDB as the persistent store, you must specify the table name via `LAUNCHDARKLY_DYNAMODB_TABLE_NAME`.
+
+### Error: "Invalid integer value for..."
+**Solution:** Ensure numeric environment variables (ports, timeouts) contain valid integer values.
+
+### Error: "Invalid boolean value for..."
+**Solution:** Boolean environment variables must be set to either `true` or `false` (case-insensitive).
+
+## AWS Credentials for DynamoDB
+
+When using DynamoDB, the SDK uses the standard AWS credential chain:
+1. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
+2. Shared credentials file (`~/.aws/credentials`)
+3. IAM role (when running on AWS infrastructure)
+
+Example with explicit credentials:
+```bash
+export AWS_ACCESS_KEY_ID="your-access-key"
+export AWS_SECRET_ACCESS_KEY="your-secret-key"
+export AWS_REGION="us-east-1"
+export LAUNCHDARKLY_SDK_KEY="sdk-abc-123"
+export LAUNCHDARKLY_PERSISTENT_STORE_TYPE="dynamodb"
+export LAUNCHDARKLY_DYNAMODB_TABLE_NAME="launchdarkly-flags"
+dotnet run
+```
+
+## Boolean Values
+
+Boolean environment variables accept the following values (case-insensitive):
+- True: `true`, `True`, `TRUE`
+- False: `false`, `False`, `FALSE`
+
+Any other value will result in a format error.
diff --git a/sandbox/dotnet-server-sandbox/dotnet-server-sandbox.csproj b/sandbox/dotnet-server-sandbox/dotnet-server-sandbox.csproj
new file mode 100644
index 00000000..29afa44f
--- /dev/null
+++ b/sandbox/dotnet-server-sandbox/dotnet-server-sandbox.csproj
@@ -0,0 +1,32 @@
+
+
+
+ Exe
+ net8.0
+ dotnet_server_test_app
+ enable
+ enable
+ true
+ true
+ Debug;Release;DebugLocalReferences
+ AnyCPU
+
+
+
+
+ DEBUG_LOCAL_REFERENCES
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+