Skip to content

Commit 08ba2cd

Browse files
revert(audience-env): drop AudienceEnvironment enum per PR review
Addresses review feedback on #709 from @nattb8: avoid exposing a public enum of environments and match the Web/Pixel SDK pattern. Problems with the enum: - Makes Dev a first-class, permanently-supported public choice that cannot be removed later without a breaking change. - Forces every future backend addition onto the public enum surface. - Diverges from @imtbl/audience, which has no enum. This commit undoes the enum wiring and restores the key-prefix URL derivation that existed before the PR. A follow-up commit adds an optional BaseUrl override on AudienceConfig (Web SDK parity) so devs who need Dev can point the SDK there directly. - Delete AudienceEnvironment.cs. - Constants: restore TestKeyPrefix and the MessagesUrl/ConsentUrl/DataUrl(string?) signatures. - AudienceConfig: drop the Environment field. - HttpTransport: drop the AudienceEnvironment ctor parameter; URL derives from publishableKey prefix. - ImmutableAudience: remove the CurrentEnvironment getter and its cached backing field; revert DeleteData, SyncConsentToBackend, and Init to pass publishableKey into the URL helpers. - Tests: remove the CurrentEnvironment_* cases and the per-env URL cases; restore the pre-PR test-key / prod-key URL assertions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent dbe483a commit 08ba2cd

9 files changed

Lines changed: 16 additions & 141 deletions

File tree

src/Packages/Audience/Runtime/AudienceConfig.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ public class AudienceConfig
1010
// Studio API key. Required — Init throws if null.
1111
public string? PublishableKey { get; set; }
1212

13-
// Target backend. Sandbox default prevents accidental production
14-
// traffic; pin to Production explicitly when shipping to players.
15-
public AudienceEnvironment Environment { get; set; } = AudienceEnvironment.Sandbox;
16-
1713
// Initial consent level.
1814
public ConsentLevel Consent { get; set; } = ConsentLevel.None;
1915

src/Packages/Audience/Runtime/AudienceEnvironment.cs

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/Packages/Audience/Runtime/Core/Constants.cs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace Immutable.Audience
44
{
55
internal static class Constants
66
{
7-
internal const string DevBaseUrl = "https://api.dev.immutable.com";
7+
internal const string TestKeyPrefix = "pk_imapik-test-";
88
internal const string SandboxBaseUrl = "https://api.sandbox.immutable.com";
99
internal const string ProductionBaseUrl = "https://api.immutable.com";
1010

@@ -26,21 +26,14 @@ internal static class Constants
2626

2727
internal const string PublishableKeyHeader = "x-immutable-publishable-key";
2828

29-
internal static string MessagesUrl(AudienceEnvironment environment) => BaseUrl(environment) + MessagesPath;
30-
internal static string ConsentUrl(AudienceEnvironment environment) => BaseUrl(environment) + ConsentPath;
31-
internal static string DataUrl(AudienceEnvironment environment) => BaseUrl(environment) + DataPath;
29+
internal static string MessagesUrl(string? publishableKey) => BaseUrl(publishableKey) + MessagesPath;
30+
internal static string ConsentUrl(string? publishableKey) => BaseUrl(publishableKey) + ConsentPath;
31+
internal static string DataUrl(string? publishableKey) => BaseUrl(publishableKey) + DataPath;
3232

33-
internal static string BaseUrl(AudienceEnvironment environment) =>
34-
environment switch
35-
{
36-
AudienceEnvironment.Dev => DevBaseUrl,
37-
AudienceEnvironment.Sandbox => SandboxBaseUrl,
38-
AudienceEnvironment.Production => ProductionBaseUrl,
39-
// Defensive: a future enum addition we forget to wire up
40-
// falls back to Sandbox so accidental production traffic
41-
// is impossible without explicit opt-in.
42-
_ => SandboxBaseUrl,
43-
};
33+
internal static string BaseUrl(string? publishableKey) =>
34+
publishableKey != null && publishableKey.StartsWith(TestKeyPrefix)
35+
? SandboxBaseUrl
36+
: ProductionBaseUrl;
4437
}
4538

4639
// Message type values written to (and read back from) the "type" field.

src/Packages/Audience/Runtime/ImmutableAudience.cs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ public static class ImmutableAudience
6262
// a prior session changed it.
6363
public static ConsentLevel CurrentConsent => _state.Level;
6464

65-
// Caches the last Init's env so a diagnostic HUD does not flicker
66-
// to the Sandbox default when Shutdown clears _config.
67-
public static AudienceEnvironment CurrentEnvironment => _currentEnvironment;
68-
private static volatile AudienceEnvironment _currentEnvironment = AudienceEnvironment.Sandbox;
69-
7065
public static string? UserId => _state.UserId;
7166

7267
// Display-only — Reset and SetConsent(None) wipe it, so it is not
@@ -130,15 +125,14 @@ public static void Init(AudienceConfig config)
130125
}
131126

132127
_config = config;
133-
_currentEnvironment = config.Environment;
134128
Log.Enabled = config.Debug;
135129
// Persisted consent overrides the config default (prior downgrade survives restart).
136130
var initialLevel = ConsentStore.Load(config.PersistentDataPath) ?? config.Consent;
137131
_state = new ConsentState(initialLevel, null);
138132

139133
_store = new DiskStore(config.PersistentDataPath);
140134
_queue = new EventQueue(_store, config.FlushIntervalSeconds, config.FlushSize);
141-
_transport = new HttpTransport(_store, config.PublishableKey, config.Environment, config.OnError, config.HttpHandler);
135+
_transport = new HttpTransport(_store, config.PublishableKey, config.OnError, config.HttpHandler);
142136
_controlClient = config.HttpHandler != null
143137
? new HttpClient(config.HttpHandler, disposeHandler: false)
144138
: new HttpClient();
@@ -394,7 +388,7 @@ public static Task DeleteData(string? userId = null)
394388
query = "anonymousId=" + Uri.EscapeDataString(anonymousId);
395389
}
396390

397-
var url = Constants.DataUrl(config.Environment) + "?" + query;
391+
var url = Constants.DataUrl(config.PublishableKey) + "?" + query;
398392
var onError = config.OnError;
399393
var publishableKey = config.PublishableKey;
400394
var cancellationToken = _shutdownCancellationSource?.Token ?? CancellationToken.None;
@@ -556,7 +550,7 @@ private static void SyncConsentToBackend(AudienceConfig config, ConsentLevel lev
556550
var client = _controlClient;
557551
if (client == null) return;
558552

559-
var url = Constants.ConsentUrl(config.Environment);
553+
var url = Constants.ConsentUrl(config.PublishableKey);
560554
var publishableKey = config.PublishableKey;
561555
var onError = config.OnError;
562556
var cancellationToken = _shutdownCancellationSource?.Token ?? CancellationToken.None;
@@ -771,9 +765,6 @@ internal static void ResetState()
771765
// Defensive: Shutdown nulls _session too, but a future refactor
772766
// that bails before that null must not leak a stale Session.
773767
_session = null;
774-
// Reset the env cache so test isolation and domain-reload
775-
// both start from Sandbox; a subsequent Init overwrites it.
776-
_currentEnvironment = AudienceEnvironment.Sandbox;
777768
Identity.ClearCache();
778769
}
779770
}

src/Packages/Audience/Runtime/Transport/HttpTransport.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,18 @@ internal sealed class HttpTransport : IDisposable
2828

2929
// store: source of event batches.
3030
// publishableKey: sent as x-immutable-publishable-key on every request.
31-
// environment: which backend to send to. Defaults to Sandbox so
32-
// tests and ad-hoc construction cannot accidentally hit production.
3331
// onError: optional failure callback. Exceptions thrown inside it are caught.
3432
// handler / getUtcNow: test seams; null for production use.
3533
internal HttpTransport(
3634
DiskStore store,
3735
string publishableKey,
38-
AudienceEnvironment environment = AudienceEnvironment.Sandbox,
3936
Action<AudienceError>? onError = null,
4037
HttpMessageHandler? handler = null,
4138
Func<DateTime>? getUtcNow = null)
4239
{
4340
_store = store ?? throw new ArgumentNullException(nameof(store));
4441
_publishableKey = publishableKey ?? throw new ArgumentNullException(nameof(publishableKey));
45-
_url = Constants.MessagesUrl(environment);
42+
_url = Constants.MessagesUrl(publishableKey);
4643
_onError = onError;
4744
// disposeHandler: false so the consumer can reuse their handler
4845
// across Init/Shutdown cycles (matches _controlClient's policy).

src/Packages/Audience/Tests/Runtime/ConsentSyncTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void SetConsent_FiresPut_WithExpectedBodyShape()
4242
var put = WaitForPut(handler);
4343
var body = JsonReader.DeserializeObject(put.Body);
4444

45-
Assert.AreEqual(Constants.ConsentUrl(AudienceEnvironment.Sandbox), put.Url);
45+
Assert.AreEqual(Constants.ConsentUrl("pk_imapik-test-key1"), put.Url);
4646
Assert.AreEqual("full", body["status"]);
4747
Assert.AreEqual(Constants.ConsentSource, body["source"]);
4848
Assert.IsTrue(body.ContainsKey("anonymousId"));

src/Packages/Audience/Tests/Runtime/ConstantsTests.cs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,6 @@ namespace Immutable.Audience.Tests
66
[TestFixture]
77
internal class ConstantsTests
88
{
9-
// -----------------------------------------------------------------
10-
// BaseUrl per environment
11-
// -----------------------------------------------------------------
12-
13-
[Test]
14-
public void BaseUrl_Dev_ReturnsDevHost()
15-
{
16-
Assert.AreEqual(Constants.DevBaseUrl, Constants.BaseUrl(AudienceEnvironment.Dev));
17-
}
18-
19-
[Test]
20-
public void BaseUrl_Sandbox_ReturnsSandboxHost()
21-
{
22-
Assert.AreEqual(Constants.SandboxBaseUrl, Constants.BaseUrl(AudienceEnvironment.Sandbox));
23-
}
24-
25-
[Test]
26-
public void BaseUrl_Production_ReturnsProductionHost()
27-
{
28-
Assert.AreEqual(Constants.ProductionBaseUrl, Constants.BaseUrl(AudienceEnvironment.Production));
29-
}
30-
31-
// -----------------------------------------------------------------
32-
// Library version
33-
// -----------------------------------------------------------------
34-
359
[Test]
3610
public void LibraryVersion_MatchesPackageJson()
3711
{

src/Packages/Audience/Tests/Runtime/ImmutableAudienceTests.cs

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -80,53 +80,6 @@ public void Initialized_FlipsAroundInitAndShutdown()
8080
"Initialized should flip back to false after Shutdown");
8181
}
8282

83-
[Test]
84-
public void CurrentEnvironment_DefaultsToSandbox()
85-
{
86-
// MakeConfig() leaves Environment unset, which means
87-
// AudienceConfig's Sandbox default applies.
88-
ImmutableAudience.Init(MakeConfig());
89-
Assert.AreEqual(AudienceEnvironment.Sandbox,
90-
ImmutableAudience.CurrentEnvironment);
91-
}
92-
93-
[Test]
94-
public void CurrentEnvironment_ExplicitDev_PassesThrough()
95-
{
96-
var config = MakeConfig();
97-
config.Environment = AudienceEnvironment.Dev;
98-
ImmutableAudience.Init(config);
99-
Assert.AreEqual(AudienceEnvironment.Dev,
100-
ImmutableAudience.CurrentEnvironment);
101-
}
102-
103-
[Test]
104-
public void CurrentEnvironment_BeforeInit_ReturnsSandbox()
105-
{
106-
// Pre-Init there is no config to read. Returning Sandbox
107-
// matches the AudienceConfig default so UI never shows a
108-
// separate "(uninitialised)" sentinel for this row.
109-
Assert.AreEqual(AudienceEnvironment.Sandbox,
110-
ImmutableAudience.CurrentEnvironment);
111-
}
112-
113-
[Test]
114-
public void CurrentEnvironment_SurvivesShutdown()
115-
{
116-
// A diagnostic HUD running in Production must not flicker to
117-
// Sandbox when the SDK tears down. CurrentEnvironment caches
118-
// the last Init's env so it keeps reporting the same value
119-
// after Shutdown clears _config.
120-
var config = MakeConfig();
121-
config.Environment = AudienceEnvironment.Production;
122-
ImmutableAudience.Init(config);
123-
ImmutableAudience.Shutdown();
124-
125-
Assert.AreEqual(AudienceEnvironment.Production,
126-
ImmutableAudience.CurrentEnvironment,
127-
"CurrentEnvironment should retain the last Init's value after Shutdown");
128-
}
129-
13083
[Test]
13184
public void CurrentConsent_ReflectsLatestSetConsent()
13285
{

src/Packages/Audience/Tests/Runtime/Transport/HttpTransportTests.cs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public async Task SendBatchAsync_200_SendsPlainJsonPayloadWithoutContentEncoding
123123
#endif
124124

125125
[Test]
126-
public async Task SendBatchAsync_DefaultEnvironment_HitsSandbox()
126+
public async Task SendBatchAsync_200_UsesCorrectUrlForTestKey()
127127
{
128128
_store.Write("{\"type\":\"track\"}");
129129

@@ -138,31 +138,14 @@ public async Task SendBatchAsync_DefaultEnvironment_HitsSandbox()
138138
}
139139

140140
[Test]
141-
public async Task SendBatchAsync_ExplicitDev_HitsDev()
141+
public async Task SendBatchAsync_200_UsesCorrectUrlForProdKey()
142142
{
143143
_store.Write("{\"type\":\"track\"}");
144144

145145
HttpRequestMessage captured = null;
146146
var handler = new MockHandler(HttpStatusCode.OK, "{\"accepted\":1,\"rejected\":0}",
147147
onRequest: req => captured = req);
148-
using var transport = new HttpTransport(_store, "pk_imapik-test-key1",
149-
environment: AudienceEnvironment.Dev, handler: handler);
150-
151-
await transport.SendBatchAsync();
152-
153-
StringAssert.StartsWith(Constants.DevBaseUrl, captured.RequestUri.ToString());
154-
}
155-
156-
[Test]
157-
public async Task SendBatchAsync_ExplicitProduction_HitsProduction()
158-
{
159-
_store.Write("{\"type\":\"track\"}");
160-
161-
HttpRequestMessage captured = null;
162-
var handler = new MockHandler(HttpStatusCode.OK, "{\"accepted\":1,\"rejected\":0}",
163-
onRequest: req => captured = req);
164-
using var transport = new HttpTransport(_store, "pk_imapik-test-key1",
165-
environment: AudienceEnvironment.Production, handler: handler);
148+
using var transport = new HttpTransport(_store, "pk_imapik-prodkey", handler: handler);
166149

167150
await transport.SendBatchAsync();
168151

0 commit comments

Comments
 (0)