Skip to content

Authorize feature flag management across app-local organizations - #2824

Merged
3mdistal merged 19 commits into
mainfrom
codex/feature-flag-domain-delegation
Aug 13, 2026
Merged

Authorize feature flag management across app-local organizations#2824
3mdistal merged 19 commits into
mainfrom
codex/feature-flag-domain-delegation

Conversation

@3mdistal

@3mdistal 3mdistal commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Problem

Workspace administrators manage feature flags for the app fleet from Analytics, but each hosted app owns a separate organization table. Analytics was sending its own local organization ID and receivers treated that foreign database ID as authorization scope, so legitimate administrators appeared forbidden. Dispatch was also missing from the fleet despite owning desktop.workspace-sso.

This is a separate feature-flag infrastructure repair. It does not alter OAuth custody or widen OAuth Foundations PR #2602.

What changed

  • Privileged flag delegation carries the verified organization domain. Each receiver maps it to its own local organization ID, then performs its own owner/admin check and target-local persistence.
  • Delegated write JTIs are consumed once at the framework's actual built-in action-route boundary; replaying the same mutation token is rejected.
  • Local browser administration remains available for domainless organizations.
  • Mutation acknowledgment contract v2 returns the stable domain and receiver-local ID; Analytics validates the domain, flag key, and persisted rules without equating app-local IDs.
  • Dispatch returns the complete authorized fleet. Analytics filters itself, while ordinary consumers retain client-side ID/origin self-filtering.
  • Explicit local URL preference survives resource and workspace-manifest overlays, so isolated fleets cannot be redirected to hosted built-ins.
  • Analytics exposes only fixed safe failure classes: token-generation, timeout, network, and target-execution.
  • Feature-flag rows switch to their two-column layout at the large breakpoint, preserving readable content at 768px.

Safety

There is no destructive migration or backfill. Generic non-flag A2A callers remain compatible. A receiver without the verified domain mapping fails closed; sender roles are never trusted; v1 or wrong-domain acknowledgments are rejected.

Verification

  • Core focused suites: 82 tests passing across agent discovery, action routing, feature-flag A2A auth, and the replay store.
  • Analytics workspace feature-flag suite: 11 tests passing.
  • Core build and typecheck pass; Analytics typecheck passes.
  • All 53 repository guards pass.
  • Same-thread real-interface acceptance passed on isolated Analytics, Dispatch, and Clips servers with deliberately different local organization IDs.
  • Analytics listed Dispatch and Clips, enabled and read back a Clips flag, and returned the Clips-local org ID plus builder.test.
  • A mapped member and the same email presented for another target-local organization both received HTTP 403; the rule remained off.
  • Live replay proof returned HTTP 200 for the first use of one write token and HTTP 401 for the second, with one durable receiver-local JTI record.
  • Chrome visual QA passed at 1280 x 800 and 768 x 900; the narrow page had no horizontal overflow and browser logs were clean.
  • Unavailable apps retained bounded network/timeout states without leaked response bodies or secrets.
  • Disposable runtimes were stopped; ports 8088, 8092, and 8094 were confirmed closed, and the fixture directory was moved to Trash.

Review focus

  • Does every privileged route derive scope only from the verified domain and preserve the receiver-local owner/admin check?
  • Is the JTI consumed on every production mutation route before the action runs?
  • Does local URL preference remain stable across every overlay without changing normal workspace routing?
  • Is the v2 acknowledgment strict without equating unrelated local IDs?

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

builder-io-integration[bot]

This comment was marked as outdated.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

builder-io-integration[bot]

This comment was marked as outdated.

@netlify

This comment has been minimized.

builder-io-integration[bot]

This comment was marked as outdated.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

builder-io-integration[bot]

This comment was marked as outdated.

@netlify

This comment has been minimized.

builder-io-integration[bot]

This comment was marked as outdated.

builder-io-integration[bot]

This comment was marked as outdated.

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builder reviewed your changes — looks good ✅

Review Details

Code Review Summary

This incremental update partitions org-directory cache entries by includeDirectoryApp, preserving the explicit whole-fleet contract for Analytics while keeping legacy self-filtered callers isolated. The prior cache-mode finding was verified fixed and its thread was resolved. Focused review agents found no new actionable issues across directory headers and MCP callers, JTI replay protection, domain-based authorization, route compatibility, or the responsive Feature Flags panel.

The overall approach remains sound for the high-risk cross-app authorization change: the receiver maps verified domains to local organizations, delegated mutations consume one-time JTIs, and local feature-flag administration remains available without a domain. Focused suites reported 100–103 passing tests across the changed areas.

🧪 Browser testing: Attempted after this review, but Chrome MCP tools were unavailable; the 768px and 1280px Feature Flags layout cases remain environment-limited.

@3mdistal
3mdistal merged commit 4a3849b into main Aug 13, 2026
42 checks passed
@3mdistal
3mdistal deleted the codex/feature-flag-domain-delegation branch August 13, 2026 16:40
@netlify

This comment has been minimized.

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.

2 participants