

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# Feature Gating with MSIDFlightManager23## Overview45This document provides guidance for AI agents on implementing feature flags in the Microsoft Authentication Library (MSAL) for iOS and macOS using `MSIDFlightManager`. Feature flags enable controlled rollout of new features and A/B testing capabilities.67## Important Limitations89⚠️ **CRITICAL: Microsoft Internal Use Only**1011The `MSIDFlightManager` feature flag system is **ONLY available in broker context** or when the broker returns flight configurations as part of its response. This is a Microsoft-internal mechanism and is **NOT accessible to third-party developers**.1213### Broker Context Requirement1415- Feature flags are **only available** when:16 1. The application is running inside the Microsoft Authenticator or Company Portal broker17 2. The broker explicitly returns flight configurations in its authentication response1819- **Third-party developers must NOT rely on this system** for their applications20- Third-party developers should implement their own feature flag provider if needed2122### Third-Party Developer Guidance2324If you are a third-party developer:2526- ✅ Implement your own feature flag system using:27 - Remote configuration services (for example: Azure App Configuration)28 - Custom backend configuration endpoints29 - Local configuration files with remote updates3031## MSIDFlightManager Architecture3233### Location3435`MSIDFlightManager` is part of the **IdentityCore** common library:3637```38MSAL/IdentityCore/IdentityCore/src/MSIDFlightManager.h39MSAL/IdentityCore/IdentityCore/src/MSIDFlightManager.m40```4142### Key Characteristics4344- **Singleton pattern**: Accessed via `[MSIDFlightManager sharedInstance]`45- **Thread-safe**: Uses `dispatch_once` for initialization46- **Broker-dependent**: Only populated with data from broker responses47- **Read-only for MSAL**: MSAL code reads flags, broker sets them4849## When to Use Feature Flags5051Feature flags should be used for:52531. **New Features**: Gradual rollout of new functionality542. **Breaking Changes**: Safe migration paths with fallback behavior553. **A/B Testing**: Testing different implementation approaches564. **Risk Mitigation**: Ability to quickly disable problematic features575. **Platform-Specific Behavior**: Different behavior for iOS vs macOS vs visionOS5859Feature flags should **NOT** be used for:6061- Permanent configuration options (use config classes instead)62- User-facing preferences (use proper settings)63- Build-time configurations (use compiler flags)64- Debug-only features (use `#if DEBUG`)6566## Implementation Pattern6768### Step 1: Define the Feature Flag Key6970Feature flag keys should follow naming conventions:7172```objc73// In MSIDFlightManager.h or appropriate header74static NSString * const MSIDFlightKeyNewAuthFlow = @"new_auth_flow";75static NSString * const MSIDFlightKeyEnhancedTokenCache = @"enhanced_token_cache";76static NSString * const MSIDFlightKeyNativeAuthV2 = @"native_auth_v2";77```7879**Naming Convention:**8081- Use snake_case for flag keys82- Prefix with feature area if applicable83- Keep names descriptive but concise84- Document in code comments8586### Step 2: Check Feature Flag in Code8788Always provide a default fallback behavior when feature flag is not available:8990```objc91// Example: Checking if new feature is enabled92BOOL isNewAuthFlowEnabled = [[MSIDFlightManager sharedInstance]93 isFlightEnabled:MSIDFlightKeyNewAuthFlow];9495if (isNewAuthFlowEnabled)96{97 // New implementation98 [self performNewAuthenticationFlow];99}100else101{102 // Existing/fallback implementation103 [self performLegacyAuthenticationFlow];104}105```106107### Step 3: Handle Missing/Default State108109**CRITICAL**: Always assume feature flags may be unavailable (nil or NO):110111```objc112- (void)performOperationWithContext:(id<MSIDRequestContext>)context113{114 // Default to NO/false if flag is not set by broker115 BOOL useEnhancedCache = [[MSIDFlightManager sharedInstance]116 isFlightEnabled:MSIDFlightKeyEnhancedTokenCache];117118 if (useEnhancedCache)119 {120 MSID_LOG_WITH_CTX(MSIDLogLevelInfo, context,121 @"Using enhanced token cache (feature flag enabled)");122 [self useEnhancedTokenCache];123 }124 else125 {126 MSID_LOG_WITH_CTX(MSIDLogLevelInfo, context,127 @"Using standard token cache (feature flag disabled or unavailable)");128 [self useStandardTokenCache];129 }130}131```132133### Step 4: Add Logging134135Always log feature flag decisions for debugging:136137```objc138BOOL isFeatureEnabled = [[MSIDFlightManager sharedInstance]139 isFlightEnabled:MSIDFlightKeyNewFeature];140141MSID_LOG_WITH_CTX_PII(MSIDLogLevelInfo, context,142 @"Feature 'new_feature' is %@",143 isFeatureEnabled ? @"ENABLED" : @"DISABLED");144```145146## Common Patterns147148### Pattern 1: Simple On/Off Toggle149150```objc151- (void)processAuthenticationWithParameters:(MSALTokenParameters *)parameters152 error:(NSError **)error153{154 BOOL useNewFlow = [[MSIDFlightManager sharedInstance]155 isFlightEnabled:@"new_auth_flow"];156157 if (useNewFlow)158 {159 return [self processAuthenticationNewFlow:parameters error:error];160 }161 else162 {163 return [self processAuthenticationLegacyFlow:parameters error:error];164 }165}166```167168### Pattern 2: Platform-Specific Feature Flags169170```objc171- (void)configureWebView:(WKWebView *)webView172{173 #if TARGET_OS_IOS174 BOOL useEnhancedWebView = [[MSIDFlightManager sharedInstance]175 isFlightEnabled:@"enhanced_webview_ios"];176 #elif TARGET_OS_OSX177 BOOL useEnhancedWebView = [[MSIDFlightManager sharedInstance]178 isFlightEnabled:@"enhanced_webview_macos"];179 #else180 BOOL useEnhancedWebView = NO;181 #endif182183 if (useEnhancedWebView)184 {185 [self configureEnhancedWebView:webView];186 }187 else188 {189 [self configureStandardWebView:webView];190 }191}192```193194### Pattern 3: Multiple Flag Combinations195196```objc197- (void)performAdvancedOperation198{199 BOOL featureA = [[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_a"];200 BOOL featureB = [[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_b"];201202 if (featureA && featureB)203 {204 // Both features enabled205 [self performOperationWithBothFeatures];206 }207 else if (featureA)208 {209 // Only feature A enabled210 [self performOperationWithFeatureA];211 }212 else if (featureB)213 {214 // Only feature B enabled215 [self performOperationWithFeatureB];216 }217 else218 {219 // Neither feature enabled - use baseline220 [self performBaselineOperation];221 }222}223```224225## Best Practices226227### 1. Always Provide Fallback228229```objc230// ✅ GOOD: Has clear fallback231BOOL useNewFeature = [[MSIDFlightManager sharedInstance]232 isFlightEnabled:@"new_feature"];233if (useNewFeature)234{235 [self useNewImplementation];236}237else238{239 [self useStableImplementation]; // Clear fallback240}241242// ❌ BAD: Assumes flag will always be available243if ([[MSIDFlightManager sharedInstance] isFlightEnabled:@"new_feature"])244{245 [self useNewImplementation];246}247// What happens if flag is NO or unavailable?248```249250### 2. Document Flag Dependencies251252```objc253/**254 Performs token acquisition with optional enhanced caching.255256 @param parameters Token acquisition parameters257 @param error Error if operation fails258259 @return MSALResult on success, nil on failure260261 @note This method uses the 'enhanced_token_cache' feature flag when262 available in broker context. Falls back to standard caching263 when flag is disabled or unavailable.264 */265- (MSALResult *)acquireTokenWithParameters:(MSALTokenParameters *)parameters266 error:(NSError **)error;267```268269### 3. Log Feature Flag State270271```objc272- (void)performOperation273{274 BOOL featureEnabled = [[MSIDFlightManager sharedInstance]275 isFlightEnabled:@"my_feature"];276277 MSID_LOG_WITH_CTX(MSIDLogLevelInfo, nil,278 @"Feature 'my_feature' state: %@",279 featureEnabled ? @"ENABLED" : @"DISABLED");280281 // ... rest of implementation282}283```284285### 4. Plan for Removal286287Feature flags should be temporary. Document removal plan:288289```objc290/**291 TODO: Remove feature flag check after Q2 2025 rollout292293 Feature flag: 'new_auth_flow'294 Rollout started: 2024-Q4295 Expected completion: 2025-Q2296 Tracking: https://example.com/feature/new-auth-flow297298 Once rollout is complete, remove the flag check and keep only299 the new implementation.300 */301BOOL useNewAuthFlow = [[MSIDFlightManager sharedInstance]302 isFlightEnabled:@"new_auth_flow"];303```304305### 5. Avoid Deep Nesting306307```objc308// ❌ BAD: Too many nested feature flags309if ([[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_a"])310{311 if ([[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_b"])312 {313 if ([[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_c"])314 {315 // Complex logic here316 }317 }318}319320// ✅ GOOD: Extract to separate method with clear logic321BOOL featureA = [[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_a"];322BOOL featureB = [[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_b"];323BOOL featureC = [[MSIDFlightManager sharedInstance] isFlightEnabled:@"feature_c"];324325[self performOperationWithFeatureA:featureA326 featureB:featureB327 featureC:featureC];328```329330### 6. Consider Performance331332```objc333// ✅ GOOD: Cache flag value if checked multiple times334- (void)performMultipleOperations335{336 // Check once and cache337 BOOL useOptimization = [[MSIDFlightManager sharedInstance]338 isFlightEnabled:@"optimization"];339340 [self operation1WithOptimization:useOptimization];341 [self operation2WithOptimization:useOptimization];342 [self operation3WithOptimization:useOptimization];343}344345// ❌ LESS EFFICIENT: Checking same flag multiple times346- (void)performMultipleOperations347{348 [self operation1WithOptimization:[[MSIDFlightManager sharedInstance]349 isFlightEnabled:@"optimization"]];350 [self operation2WithOptimization:[[MSIDFlightManager sharedInstance]351 isFlightEnabled:@"optimization"]];352 [self operation3WithOptimization:[[MSIDFlightManager sharedInstance]353 isFlightEnabled:@"optimization"]];354}355```356357## Error Handling with Feature Flags358359```objc360- (BOOL)performOperationWithError:(NSError **)error361{362 BOOL useNewImplementation = [[MSIDFlightManager sharedInstance]363 isFlightEnabled:@"new_implementation"];364365 if (useNewImplementation)366 {367 NSError *internalError = nil;368 BOOL result = [self performNewImplementationWithError:&internalError];369370 if (!result)371 {372 MSID_LOG_WITH_CTX(MSIDLogLevelError, nil,373 @"New implementation failed, falling back: %@",374 internalError);375376 // Optional: Fall back to old implementation on failure377 result = [self performLegacyImplementationWithError:&internalError];378 }379380 if (!result && error)381 {382 *error = internalError;383 }384385 return result;386 }387 else388 {389 return [self performLegacyImplementationWithError:error];390 }391}392```393394## Example: Adding a New Feature with Flag395396Here's a complete example of adding a new feature behind a feature flag:397398```objc399// 1. Define the flag key constant400static NSString * const MSIDFlightKeyEnhancedErrorReporting = @"enhanced_error_reporting";401402// 2. Implement the feature-flagged method403- (void)reportError:(NSError *)error404 withContext:(id<MSIDRequestContext>)context405{406 // Check feature flag407 BOOL useEnhancedReporting = [[MSIDFlightManager sharedInstance]408 isFlightEnabled:MSIDFlightKeyEnhancedErrorReporting];409410 // Log the decision411 MSID_LOG_WITH_CTX(MSIDLogLevelInfo, context,412 @"Enhanced error reporting: %@",413 useEnhancedReporting ? @"ENABLED" : @"DISABLED");414415 if (useEnhancedReporting)416 {417 // New enhanced reporting418 [self reportErrorEnhanced:error withContext:context];419 }420 else421 {422 // Existing stable reporting423 [self reportErrorLegacy:error withContext:context];424 }425}426427// 3. Implement both code paths428- (void)reportErrorEnhanced:(NSError *)error429 withContext:(id<MSIDRequestContext>)context430{431 // New implementation with additional telemetry, diagnostics, etc.432 MSID_LOG_WITH_CTX(MSIDLogLevelError, context,433 @"Enhanced error report: %@ (domain: %@, code: %ld)",434 error.localizedDescription,435 error.domain,436 (long)error.code);437438 // Additional enhanced reporting logic439 [self collectDiagnostics:error];440 [self sendTelemetryForError:error];441}442443- (void)reportErrorLegacy:(NSError *)error444 withContext:(id<MSIDRequestContext>)context445{446 // Existing stable implementation447 MSID_LOG_WITH_CTX(MSIDLogLevelError, context,448 @"Error: %@", error.localizedDescription);449}450```451452## Checklist for Adding Feature Flags453454When implementing a new feature behind a feature flag:455456- [ ] Define clear, descriptive flag key constant457- [ ] Implement both new and fallback code paths458- [ ] Add logging for feature flag state459- [ ] Handle nil/NO case gracefully (default to stable behavior)460- [ ] Write unit tests for both enabled and disabled states461- [ ] Document the feature flag in code comments462- [ ] Add telemetry/metrics if appropriate463- [ ] Plan for eventual flag removal (add TODO with timeline)464- [ ] Verify behavior when broker context is unavailable465- [ ] Test in real broker context (Microsoft Authenticator/Company Portal)466467## Summary468469**Key Takeaways for AI Agents:**4704711. ✅ **Use feature flags for gradual rollout** of new features4722. ✅ **Always provide stable fallback** behavior4733. ✅ **Remember: Only works in broker context** - not for third-party apps4744. ✅ **Log feature flag decisions** for debugging4755. ✅ **Test both enabled and disabled states**4766. ✅ **Plan for eventual removal** of feature flags4777. ✅ **Document flag dependencies** in code comments4788. ❌ **Don't use for permanent configuration**4799. ❌ **Don't assume flags will always be available**48010. ❌ **Don't leave flags in code indefinitely**481482## Related Documentation483484- `.clinerules/04-Code-style-guidelines.md` - Code style requirements485- `MSAL/IdentityCore/IdentityCore/src/MSIDFlightManager.h` - Flight manager API486- Microsoft internal documentation for broker flight configuration487488## Questions?489490For questions about feature flag implementation:491492- **Microsoft employees**: Contact MSAL iOS team or check internal documentation493- **Third-party developers**: Implement your own feature flag system494
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| AzureAD/microsoft-authentication-library-for-objcCLAUDE.md · 345 | CLAUDE.md | buildteststylearch+6 | 76/100 | today | |
| AzureAD/microsoft-authentication-library-for-objc.clinerules/02-External-tenant-configuration.md · 345 | Cline rules | setupbuildteststyle+7 | 69/100 | 14 days ago | |
| AzureAD/microsoft-authentication-library-for-objc.clinerules/04-Code-style-guidelines.md · 345 | Cline rules | lint-formatstylearchtypes+5 | 73/100 | today | |
| AzureAD/microsoft-authentication-library-for-objc.clinerules/AGENTS.md · 345 | AGENTS.md | buildteststyleapi+2 | 82/100 | today | |
| AzureAD/microsoft-authentication-library-for-objc.cursor/rules/ruler_cursor_instructions.mdc · 345 | Cursor rules | buildteststylearch+6 | 76/100 | 14 days ago | |
| AzureAD/microsoft-authentication-library-for-objc.github/copilot-instructions.md · 345 | Copilot instructions | setupbuildteststyle+11 | 64/100 | 14 days ago | |
| AzureAD/microsoft-authentication-library-for-objcAGENTS.md · 345 | AGENTS.md | buildteststylearch+6 | 76/100 | 14 days ago | |
| AzureAD/microsoft-authentication-library-for-objc.clinerules/06-Customer-communication-guidelines.md · 345 | Cline rules | stylemonorepodo-notagent-behaviour | 51/100 | 14 days ago | |
| AzureAD/microsoft-authentication-library-for-objc.clinerules/01-Workforce-tenant-configuration.md · 345 | Cline rules | setupbuildtestarch+5 | 58/100 | 14 days ago | |
| AzureAD/microsoft-authentication-library-for-objc.clinerules/03-MSAL-API-usage.md · 345 | Cline rules | styleapi | 58/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| JCodesMore/ai-website-cloner-template.clinerules · 32k | Cline rules | buildlint-formatstylearch+3 | 97/100 | 7 days ago | |
| BryaanF/LiantPortfolio.clinerules/project-guidelines.md · 0 | Cline rules | buildstylearchgit+2 | 96/100 | 14 days ago | |
| enuno/unifi-mcp-server.clinerules · 226 | Cline rules | setuptestlint-formatstyle+10 | 96/100 | today | |
| lepinkainen/humanlog.clinerules/project-rules.md · 0 | Cline rules | setupbuildtestlint-format+8 | 96/100 | 14 days ago | |
| u9401066/pubmed-search-mcp.clinerules/50-pubmed-project.md · 25 | Cline rules | testlint-formatstylearch+1 | 94/100 | 14 days ago | |
| u9401066/zotero-keeper.clinerules/50-pubmed-project.md · 6 | Cline rules | testlint-formatstylearch+1 | 94/100 | 14 days ago | |
| u9401066/zotero-keepervscode-extension/resources/repo-assets/pubmed-search-mcp/.clinerules/50-pubmed-project.md · 6 | Cline rules | testlint-formatstylearch+1 | 94/100 | 14 days ago | |
| VaillerTeeter/HoshimiNest.clinerules/project-identity.md · 1 | Cline rules | setuparchtypesdo-not | 93/100 | 12 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/azuread-microsoft-authentication-library-for-objc-clinerules-05-feature-gating)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.