feat: add explicit feature flag contract
This commit is contained in:
parent
77c7b32ac0
commit
0baf32bfcf
@ -1644,6 +1644,17 @@ export class ApiServer {
|
||||
});
|
||||
});
|
||||
|
||||
this.app.get('/api/feature-flags', this.requireAuth, (_req, res) => {
|
||||
res.json({
|
||||
backtest: {
|
||||
enableBacktest: Boolean(config.ENABLE_BACKTEST),
|
||||
customerEnabled: Boolean(config.BACKTEST_CUSTOMER_ENABLED),
|
||||
maxCsvBytes: Number(config.BACKTEST_MAX_CSV_BYTES),
|
||||
maxRows: Number(config.BACKTEST_MAX_ROWS),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.app.get('/api/me/profile', this.requireAuth, async (req, res) => {
|
||||
const authReq = req as AuthenticatedRequest;
|
||||
const authUserId = authReq.authUserId;
|
||||
|
||||
@ -109,6 +109,12 @@ pnpm lint
|
||||
- backend HTTP responses echo `x-request-id` so browser/app logs can be correlated with backend logs
|
||||
- during incident review, treat `x-request-id` as the primary request correlation key across client and backend traces
|
||||
|
||||
## Feature Flag Ownership
|
||||
|
||||
- backend `GET /api/feature-flags` is the authoritative runtime contract for user-facing feature access
|
||||
- web feature gates must read explicit feature-flag contracts instead of scraping generic config payloads
|
||||
- dynamic config may still store the underlying values, but the product surfaces should consume the typed feature-flag API
|
||||
|
||||
## Staged Cutover
|
||||
|
||||
### Order
|
||||
|
||||
@ -40,6 +40,7 @@ It assumes:
|
||||
- [x] Web history, profile, marketplace, config, and manual-entry flows now run through backend APIs instead of browser-side table access
|
||||
- [x] Release smoke coverage now exists for web auth and product accessibility flows, with a tracked mobile release smoke checklist in operations
|
||||
- [x] Request ID propagation is now standardized across the main web/mobile API paths and echoed by backend HTTP responses
|
||||
- [x] Backtest feature access now reads from an explicit backend feature-flags contract instead of scraping generic runtime config
|
||||
- [x] Root verification and lint flows now run successfully without sandbox-hostile script harness behavior
|
||||
- [-] DRY cleanup completed for runtime/config/bootstrap concerns, shared websocket auth helpers, platform-session handling, and request tracing, but not yet for all persistence and feature-flag concerns
|
||||
- [!] Full common-platform data-plane replacement remains a follow-up where selected trading-record repositories still depend on legacy Supabase storage because Cosmos-native equivalents are not finished yet
|
||||
@ -178,7 +179,7 @@ Ensure all surfaces adopt one consistent platform model for auth, kill switch, t
|
||||
- [x] Define ownership split between product accessibility controls and trading-behavior controls
|
||||
- [x] Define telemetry envelope fields
|
||||
- [x] Define correlation ID and request propagation strategy
|
||||
- [ ] Define feature flag ownership and evaluation model
|
||||
- [x] Define feature flag ownership and evaluation model
|
||||
- [x] Define system-of-record ownership by concern
|
||||
- [x] Define degraded-platform fallback behavior
|
||||
- [x] Define transitional adapters needed for legacy auth flows
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { getPlatformAccessToken } from '../lib/authSession';
|
||||
import { tradingRuntime } from '../lib/runtime';
|
||||
import { createRequestId } from '../../../shared/request-id.js';
|
||||
|
||||
export interface BacktestRuntimeFlags {
|
||||
enableBacktest: boolean;
|
||||
@ -53,19 +54,20 @@ export const loadBacktestRuntimeFlags = async (): Promise<BacktestRuntimeFlags>
|
||||
}
|
||||
|
||||
const apiUrl = tradingRuntime.tradingApiUrl;
|
||||
const response = await fetch(`${apiUrl}/api/config`, {
|
||||
const response = await fetch(`${apiUrl}/api/feature-flags`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'x-request-id': createRequestId('web-flags')
|
||||
}
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch runtime config (${response.status})`);
|
||||
throw new Error(`Failed to fetch feature flags (${response.status})`);
|
||||
}
|
||||
|
||||
const body = await response.json().catch(() => ({} as any));
|
||||
const loaded: BacktestRuntimeFlags = {
|
||||
enableBacktest: toBoolean(body?.ENABLE_BACKTEST, false),
|
||||
customerEnabled: toBoolean(body?.BACKTEST_CUSTOMER_ENABLED, false)
|
||||
enableBacktest: toBoolean(body?.backtest?.enableBacktest, false),
|
||||
customerEnabled: toBoolean(body?.backtest?.customerEnabled, false)
|
||||
};
|
||||
|
||||
runtimeFlagsCache = loaded;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user