Coverage for gco_mcp / feature_flags.py: 100.00%

21 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-09-14 22:07 +0000

1"""Feature-flag evaluation for the GCO MCP server. 

2 

3Convention: a flag is enabled if and only if (a) the umbrella flag 

4GCO_ENABLE_ALL_TOOLS is set to "true", OR (b) the case-insensitive, 

5whitespace-stripped value of os.environ.get(<flag>, "") equals the 

6literal "true". Anything else (unset, empty, "false", "0", "yes", "1", 

7"True\n" without strip, ...) is disabled. 

8 

9The umbrella flag is mutually inclusive — setting GCO_ENABLE_ALL_TOOLS=true 

10overrides per-flag values, even per-flag values explicitly set to "false". 

11""" 

12 

13import os 

14 

15# Known flag constants. Tool modules import these by name. 

16FLAG_ALL_TOOLS = "GCO_ENABLE_ALL_TOOLS" 

17FLAG_CAPACITY_PURCHASE = "GCO_ENABLE_CAPACITY_PURCHASE" 

18FLAG_MODEL_UPLOAD = "GCO_ENABLE_MODEL_UPLOAD" 

19FLAG_IMAGE_PUBLISH = "GCO_ENABLE_IMAGE_PUBLISH" 

20FLAG_INFRASTRUCTURE_DEPLOY = "GCO_ENABLE_INFRASTRUCTURE_DEPLOY" 

21FLAG_INFRASTRUCTURE_DESTROY = "GCO_ENABLE_INFRASTRUCTURE_DESTROY" 

22FLAG_DESTRUCTIVE_OPERATIONS = "GCO_ENABLE_DESTRUCTIVE_OPERATIONS" 

23FLAG_MISSION = "GCO_ENABLE_MISSION" 

24# Read-only-but-sensitive metric readers: local-filesystem reads and per-call 

25# LLM scoring are default-off for security / cost reasons even though they 

26# never mutate AWS state. They are full members of the registry like any 

27# other per-tool flag. 

28FLAG_LOCAL_METRICS = "GCO_ENABLE_LOCAL_METRICS" 

29# Reads from or writes to the MCP host and can upload data to S3. 

30FLAG_LOCAL_STORAGE_SYNC = "GCO_ENABLE_LOCAL_STORAGE_SYNC" 

31FLAG_SEMANTIC_PROGRESS = "GCO_ENABLE_SEMANTIC_PROGRESS" 

32# Writes to the deployment configuration (cdk.json) on the MCP host — 

33# validated, atomic, and audited via the managed-config engine, but still a 

34# local-file mutation an agent could chain into a deploy, so default-off. 

35FLAG_CONFIG_MANAGEMENT = "GCO_ENABLE_CONFIG_MANAGEMENT" 

36# Swarm supervision: one orchestrator Mission session spawning and driving 

37# concurrent child Mission sessions. Default-off because it multiplies the 

38# blast radius of whatever tool flags are already enabled (N children acting 

39# concurrently) and because loop-spawning-loops deserves an explicit opt-in. 

40FLAG_SWARM = "GCO_ENABLE_SWARM" 

41 

42# Per-tool flags. The umbrella is intentionally not in this tuple — callers 

43# iterating ALL_FLAGS for "what gates this tool?" lookups should not see 

44# the umbrella, only the per-tool flags. 

45ALL_FLAGS = ( 

46 FLAG_CAPACITY_PURCHASE, 

47 FLAG_MODEL_UPLOAD, 

48 FLAG_IMAGE_PUBLISH, 

49 FLAG_INFRASTRUCTURE_DEPLOY, 

50 FLAG_INFRASTRUCTURE_DESTROY, 

51 FLAG_DESTRUCTIVE_OPERATIONS, 

52 FLAG_MISSION, 

53 FLAG_LOCAL_METRICS, 

54 FLAG_LOCAL_STORAGE_SYNC, 

55 FLAG_SEMANTIC_PROGRESS, 

56 FLAG_CONFIG_MANAGEMENT, 

57 FLAG_SWARM, 

58) 

59 

60 

61def _raw(flag_name: str) -> bool: 

62 """Return True iff the env var equals literal "true" (case-insensitive, stripped).""" 

63 return os.environ.get(flag_name, "").strip().lower() == "true" 

64 

65 

66def is_enabled(flag_name: str) -> bool: 

67 """Return True iff the umbrella flag is set OR the named flag is set.""" 

68 return _raw(FLAG_ALL_TOOLS) or _raw(flag_name) 

69 

70 

71def all_tools_enabled() -> bool: 

72 """Return True iff GCO_ENABLE_ALL_TOOLS is set. Used by emit_startup_log.""" 

73 return _raw(FLAG_ALL_TOOLS)