Skip to content

Comments

Control#278

Draft
dferber90 wants to merge 55 commits intomainfrom
control
Draft

Control#278
dferber90 wants to merge 55 commits intomainfrom
control

Conversation

@dferber90
Copy link
Collaborator

@dferber90 dferber90 commented Feb 17, 2026

Summary

  • Replaces the monolithic FlagNetworkDataSource with a Controller state machine backed by dedicated StreamSource, PollingSource, and BundledSource I/O modules
  • Tags all data with its origin at arrival (stream, poll, bundled, provided, fetched), flowing into a new metrics.source field (in-memory, remote, embedded)
  • Enforces mutually exclusive streaming and polling — never runs both simultaneously
  • Adds a configUpdatedAt guard that rejects stale data from overwriting newer in-memory state
  • Hardens stream reconnection: 401s now fast-fail (no waiting for timeout), a minimum 1s gap between attempts prevents server spam, and X-Retry-Attempt headers aid debugging
  • Moves per-request deduplication from a global WeakSet to per-instance, so multiple createClient() calls no longer share tracking state
  • Adds requeue-on-failure to UsageTracker — failed ingest events are prepended back to the queue (capped at 500) instead of silently dropped
  • Deduplicates build-step reads: all concurrent evaluate() calls during a build share a single fetch promise and emit a single usage tracking event
  • Adds ReDoS protection (10k char limit on regex comparator inputs) and circular environment-reuse detection in evaluation
  • Rewrites the entire test suite as black-box tests through the public createClient API using fetchMock and createMockStream, removing the msw dependency

Breaking Changes

Renamed exports (old names preserved as deprecated aliases):

  • FlagNetworkDataSource class → Controller (alias kept)
  • FlagNetworkDataSourceOptions type → ControllerOptions (alias kept)
  • DataSource interface → ControllerInterface (no alias — this was the lower-level interface, not the re-exported one)

Since FlagNetworkDataSource and FlagNetworkDataSourceOptions are still exported with @deprecated annotations, consumers using those names won't break. However, DataSource was renamed to ControllerInterface without an alias — anyone importing DataSource from types will break.

Metrics.mode is now required on all evaluation results:

  • Added mode: 'streaming' | 'polling' | 'build' | 'offline' to the Metrics type
  • Any code that constructs or pattern-matches Metrics objects exhaustively would need updating

evaluate() no longer throws when all data sources fail (if defaultValue is provided):

  • On main: controller-fns.evaluate() calls ds.read() without try/catch — if read throws, the error propagates
  • On control: wraps controller.read() in try/catch and returns { value: defaultValue, reason: ERROR } when a default is provided
  • This is a behavioral change — callers that relied on catching errors from evaluate() when sources are down will now silently get the default value back

evaluate() now reports on FLAG_NOT_FOUND:

  • On main: no internalReportValue call when the flag definition is missing
  • On control: calls internalReportValue with reason: ERROR when datafile.projectId exists

create-raw-client initialization failures are swallowed:

  • On main: evaluate() does if (!instance?.initialized) await api.initialize() — init errors propagate
  • On control: wraps in try/catch — init errors are swallowed, letting evaluate() handle its own fallback chain

Error message prefix changed:

  • 'flags: Missing sdkKey''@vercel/flags-core: Missing sdkKey'
  • 'flags: Missing sdkKey in connection string''@vercel/flags-core: Missing sdkKey in connection string'
  • 'Definition not found for flag "..."' → `'@vercel/flags-core: Definition not found for flag "..."

Additions (non-breaking)

Addition Details
Controller export New primary name for the data source class
ControllerOptions type New primary name for options
Metrics.mode field 'streaming' | 'polling' | 'build' | 'offline'
ControllerInterface Renamed from DataSource
getDatafile() awaits pending init Now waits for in-flight init before reading, instead of immediately reading
Input validation on createClient Throws if sdkKeyOrConnectionString is not a string (previously only checked for falsy)

Removals

Removal Details
DataSource interface name Renamed to ControllerInterface, no alias
client-map.ts module ClientInstance and clientMap are now ControllerInstance and controllerInstanceMap in controller-fns.ts
data-source/ directory FlagNetworkDataSource, InMemoryDataSource, stream-connection all replaced by controller/
msw dev dependency Tests migrated to fetchMock

Deprecations

Symbol Replacement
FlagNetworkDataSource Controller
FlagNetworkDataSourceOptions `ControllerOptions

@vercel
Copy link
Contributor

vercel bot commented Feb 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flags-sdk-dev Ready Ready Preview, Comment, Open in v0 Feb 21, 2026 6:04am
flags-sdk-next-15 Ready Ready Preview, Comment, Open in v0 Feb 21, 2026 6:04am
flags-sdk-next-16 Ready Ready Preview, Comment, Open in v0 Feb 21, 2026 6:04am
flags-sdk-snippets Ready Ready Preview, Comment, Open in v0 Feb 21, 2026 6:04am
flags-sdk-sveltekit-snippets Ready Ready Preview, Comment, Open in v0 Feb 21, 2026 6:04am
shirt-shop Ready Ready Preview, Comment, Open in v0 Feb 21, 2026 6:04am
shirt-shop-api Ready Ready Preview, Comment, Open in v0 Feb 21, 2026 6:04am

@socket-security
Copy link

socket-security bot commented Feb 17, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​vercel/​edge@​1.2.21001007288100
Updatedreact@​19.3.0-canary-6066c782-20260212 ⏵ 19.3.0-canary-03ca38e6-202602131001008498100
Addedflags@​4.0.11001009490100

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant