Skip to content

feat(flags): feature-flag system with sdk.flags and operation gating#59

Merged
Datata1 merged 2 commits into
mainfrom
feat/feature-flags
Jul 16, 2026
Merged

feat(flags): feature-flag system with sdk.flags and operation gating#59
Datata1 merged 2 commits into
mainfrom
feat/feature-flags

Conversation

@Datata1

@Datata1 Datata1 commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Platform instances enable features per environment, exposed at GET /ide-service/flags (categories internal/preview/features, each with available+enabled lists). This adds:

  • sdk.flags (FlagsResource): get()/refresh()/is_available()/is_enabled()/ require(), category-scoped or union lookups, categories_with() for collision insight. Snapshot models are frozen pydantic classes
  • Gating infrastructure: APIOperation gains required_flag: FlagRequirement | None (mirrors the input_model pattern); enforced as the first step of execute_operation, so a gated call raises BEFORE any request when the flag is not enabled. _require_flag() escape hatch on ResourceBase/BoundModel for non-operation paths (streams, shell features). No existing endpoint is gated
  • FlagsStore engine in new top-level feature_flags.py (cycle-free wrt core<->http_client), hosted per-connection on APIHttpClient; lazy fetch under an asyncio.Lock (one fetch across concurrent gated calls), cached for client lifetime, refresh() re-fetches. Fail closed on legacy instances: flags-endpoint 404 caches an empty snapshot and gated calls raise with a legacy-platform hint; transient errors propagate uncached
  • New exceptions: FeatureFlagError base (flag/category attrs) with FeatureNotAvailableError (wrong instance/platform version) and FeatureNotEnabledError (available but off), exported top-level along with FlagCategory/FlagsSnapshot/CategoryFlags
  • Tests: snapshot model matrix, sdk.flags caching/refresh/404/transient behavior, operation gating incl. pre-request fail-fast proof (gated route never called), single flag fetch across concurrent gated calls, _require_flag on ResourceBase and bound/detached BoundModel; exception matrix extended; live integration test
  • Docs: CONTRIBUTING 'Gating an Endpoint Behind a Feature Flag' recipe (explicit category required in SDK declarations, async-generator guidance, test pattern), README 'Feature flags' section

Platform instances enable features per environment, exposed at
GET /ide-service/flags (categories internal/preview/features, each with
available+enabled lists). This adds:

- sdk.flags (FlagsResource): get()/refresh()/is_available()/is_enabled()/
  require(), category-scoped or union lookups, categories_with() for
  collision insight. Snapshot models are frozen pydantic classes
- Gating infrastructure: APIOperation gains required_flag:
  FlagRequirement | None (mirrors the input_model pattern); enforced as
  the first step of execute_operation, so a gated call raises BEFORE any
  request when the flag is not enabled. _require_flag() escape hatch on
  ResourceBase/BoundModel for non-operation paths (streams, shell
  features). No existing endpoint is gated
- FlagsStore engine in new top-level feature_flags.py (cycle-free wrt
  core<->http_client), hosted per-connection on APIHttpClient; lazy
  fetch under an asyncio.Lock (one fetch across concurrent gated calls),
  cached for client lifetime, refresh() re-fetches. Fail closed on
  legacy instances: flags-endpoint 404 caches an empty snapshot and
  gated calls raise with a legacy-platform hint; transient errors
  propagate uncached
- New exceptions: FeatureFlagError base (flag/category attrs) with
  FeatureNotAvailableError (wrong instance/platform version) and
  FeatureNotEnabledError (available but off), exported top-level along
  with FlagCategory/FlagsSnapshot/CategoryFlags
- Tests: snapshot model matrix, sdk.flags caching/refresh/404/transient
  behavior, operation gating incl. pre-request fail-fast proof
  (gated route never called), single flag fetch across concurrent gated
  calls, _require_flag on ResourceBase and bound/detached BoundModel;
  exception matrix extended; live integration test
- Docs: CONTRIBUTING 'Gating an Endpoint Behind a Feature Flag' recipe
  (explicit category required in SDK declarations, async-generator
  guidance, test pattern), README 'Feature flags' section
@Datata1 Datata1 self-assigned this Jul 16, 2026
@github-actions

Copy link
Copy Markdown

🛡️ Bandit Security Scan Results

✅ No security issues found by Bandit.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Coverage

Test Execution Summary

Tests Skipped Failures Errors Time
481 0 💤 0 ❌ 0 🔥 6.840s ⏱️

@Datata1
Datata1 merged commit 44ad556 into main Jul 16, 2026
2 of 4 checks passed
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