@@ -200,11 +200,196 @@ rec {
200200 } ;
201201 } ;
202202
203- # Extensible: additional settings discovered during migration
204- # will be added here as we migrate more VMs
203+ # ═══════════════════════════════════════════════════════════════════════
204+ # FEATURES - Service Assignment Configuration
205+ # ═══════════════════════════════════════════════════════════════════════
206+ #
207+ # Features define which services are enabled and in which VMs they run.
208+ # Each feature has:
209+ # - enable: Whether the feature is available system-wide
210+ # - targetVms: List of VMs that should have this feature
211+ #
212+ # Usage in downstream:
213+ # ghaf.global-config.features.fprint.targetVms = [ "admin-vm" ];
214+ # ghaf.global-config.features.yubikey.targetVms = [ "gui-vm" "admin-vm" ];
215+ #
216+ # VM base modules check: lib.ghaf.features.isEnabledFor globalConfig "fprint" vmName
217+ #
218+ features = {
219+ # Hardware authentication services
220+ fprint = {
221+ enable = mkOption {
222+ type = types . bool ;
223+ default = true ;
224+ description = "Enable fingerprint authentication support" ;
225+ } ;
226+ targetVms = mkOption {
227+ type = types . listOf types . str ;
228+ default = [ "gui-vm" ] ;
229+ example = [
230+ "gui-vm"
231+ "admin-vm"
232+ ] ;
233+ description = "VMs that should have fingerprint support" ;
234+ } ;
235+ } ;
236+
237+ yubikey = {
238+ enable = mkOption {
239+ type = types . bool ;
240+ default = true ;
241+ description = "Enable Yubikey 2FA support" ;
242+ } ;
243+ targetVms = mkOption {
244+ type = types . listOf types . str ;
245+ default = [ "gui-vm" ] ;
246+ example = [
247+ "gui-vm"
248+ "admin-vm"
249+ ] ;
250+ description = "VMs that should have Yubikey support" ;
251+ } ;
252+ } ;
253+
254+ brightness = {
255+ enable = mkOption {
256+ type = types . bool ;
257+ default = true ;
258+ description = "Enable brightness control via VirtIO" ;
259+ } ;
260+ targetVms = mkOption {
261+ type = types . listOf types . str ;
262+ default = [ "gui-vm" ] ;
263+ description = "VMs that should have brightness control" ;
264+ } ;
265+ } ;
266+
267+ # Networking services
268+ wifi = {
269+ enable = mkOption {
270+ type = types . bool ;
271+ default = true ;
272+ description = "Enable WiFi networking support" ;
273+ } ;
274+ targetVms = mkOption {
275+ type = types . listOf types . str ;
276+ default = [ "net-vm" ] ;
277+ description = "VMs that should have WiFi support" ;
278+ } ;
279+ } ;
280+
281+ # Audio services
282+ audio = {
283+ enable = mkOption {
284+ type = types . bool ;
285+ default = true ;
286+ description = "Enable audio services" ;
287+ } ;
288+ targetVms = mkOption {
289+ type = types . listOf types . str ;
290+ default = [ "audio-vm" ] ;
291+ description = "VMs that should have audio support" ;
292+ } ;
293+ } ;
294+
295+ bluetooth = {
296+ enable = mkOption {
297+ type = types . bool ;
298+ default = true ;
299+ description = "Enable Bluetooth support" ;
300+ } ;
301+ targetVms = mkOption {
302+ type = types . listOf types . str ;
303+ default = [ "audio-vm" ] ;
304+ description = "VMs that should have Bluetooth support" ;
305+ } ;
306+ } ;
307+ } ;
205308 } ;
206309 } ;
207310
311+ # ═══════════════════════════════════════════════════════════════════════════
312+ # FEATURE UTILITIES
313+ # ═══════════════════════════════════════════════════════════════════════════
314+ #
315+ # Helper functions for checking and managing service feature assignments.
316+ # These are used by VM base modules to determine which services to enable.
317+ #
318+ # Usage in VM base modules:
319+ # ghaf.services.fprint.enable = lib.ghaf.features.isEnabledFor globalConfig "fprint" vmName;
320+ #
321+ features = {
322+ # Check if a feature should be enabled for a specific VM
323+ #
324+ # Usage:
325+ # lib.ghaf.features.isEnabledFor globalConfig "fprint" "gui-vm"
326+ # # Returns: true if fprint.enable && "gui-vm" in fprint.targetVms
327+ #
328+ # Parameters:
329+ # globalConfig: The ghaf.global-config attribute set (from specialArgs)
330+ # featureName: Name of the feature (e.g., "fprint", "wifi")
331+ # vmName: Name of the VM to check (e.g., "gui-vm", "net-vm")
332+ #
333+ # Returns: bool
334+ isEnabledFor =
335+ globalConfig : featureName : vmName :
336+ let
337+ featuresAttr = globalConfig . features or { } ;
338+ feature =
339+ featuresAttr . ${ featureName } or {
340+ enable = false ;
341+ targetVms = [ ] ;
342+ } ;
343+ in
344+ ( feature . enable or false ) && builtins . elem vmName ( feature . targetVms or [ ] ) ;
345+
346+ # Get all features enabled for a specific VM
347+ #
348+ # Usage:
349+ # lib.ghaf.features.forVm globalConfig "gui-vm"
350+ # # Returns: { fprint = true; yubikey = true; brightness = true; wifi = false; ... }
351+ #
352+ # Parameters:
353+ # globalConfig: The ghaf.global-config attribute set
354+ # vmName: Name of the VM to check
355+ #
356+ # Returns: attrset of featureName -> bool
357+ forVm =
358+ globalConfig : vmName :
359+ let
360+ featuresAttr = globalConfig . features or { } ;
361+ in
362+ lib . mapAttrs (
363+ _name : feature : ( feature . enable or false ) && builtins . elem vmName ( feature . targetVms or [ ] )
364+ ) featuresAttr ;
365+
366+ # List all available feature names
367+ #
368+ # Usage:
369+ # lib.ghaf.features.available globalConfig
370+ # # Returns: [ "fprint" "yubikey" "brightness" "wifi" "audio" "bluetooth" ]
371+ #
372+ available = globalConfig : builtins . attrNames ( globalConfig . features or { } ) ;
373+
374+ # Get VMs that have a specific feature enabled
375+ #
376+ # Usage:
377+ # lib.ghaf.features.vmsWithFeature globalConfig "fprint"
378+ # # Returns: [ "gui-vm" ] (or whatever targetVms is set to)
379+ #
380+ vmsWithFeature =
381+ globalConfig : featureName :
382+ let
383+ featuresAttr = globalConfig . features or { } ;
384+ feature =
385+ featuresAttr . ${ featureName } or {
386+ enable = false ;
387+ targetVms = [ ] ;
388+ } ;
389+ in
390+ if feature . enable or false then feature . targetVms or [ ] else [ ] ;
391+ } ;
392+
208393 # Predefined global config profiles
209394 # These can be selected and extended in target configurations
210395 profiles = {
@@ -232,6 +417,33 @@ rec {
232417 } ;
233418 shm . enable = false ;
234419 idsvm . mitmproxy . enable = false ;
420+ # Feature defaults for debug profile
421+ features = {
422+ fprint = {
423+ enable = true ;
424+ targetVms = [ "gui-vm" ] ;
425+ } ;
426+ yubikey = {
427+ enable = true ;
428+ targetVms = [ "gui-vm" ] ;
429+ } ;
430+ brightness = {
431+ enable = true ;
432+ targetVms = [ "gui-vm" ] ;
433+ } ;
434+ wifi = {
435+ enable = true ;
436+ targetVms = [ "net-vm" ] ;
437+ } ;
438+ audio = {
439+ enable = true ;
440+ targetVms = [ "audio-vm" ] ;
441+ } ;
442+ bluetooth = {
443+ enable = true ;
444+ targetVms = [ "audio-vm" ] ;
445+ } ;
446+ } ;
235447 } ;
236448
237449 # Release profile - production settings
@@ -258,6 +470,33 @@ rec {
258470 } ;
259471 shm . enable = false ;
260472 idsvm . mitmproxy . enable = false ;
473+ # Feature defaults for release profile
474+ features = {
475+ fprint = {
476+ enable = true ;
477+ targetVms = [ "gui-vm" ] ;
478+ } ;
479+ yubikey = {
480+ enable = true ;
481+ targetVms = [ "gui-vm" ] ;
482+ } ;
483+ brightness = {
484+ enable = true ;
485+ targetVms = [ "gui-vm" ] ;
486+ } ;
487+ wifi = {
488+ enable = true ;
489+ targetVms = [ "net-vm" ] ;
490+ } ;
491+ audio = {
492+ enable = true ;
493+ targetVms = [ "audio-vm" ] ;
494+ } ;
495+ bluetooth = {
496+ enable = true ;
497+ targetVms = [ "audio-vm" ] ;
498+ } ;
499+ } ;
261500 } ;
262501
263502 # Minimal profile - bare minimum
@@ -284,6 +523,33 @@ rec {
284523 } ;
285524 shm . enable = false ;
286525 idsvm . mitmproxy . enable = false ;
526+ # Feature defaults for minimal profile - all disabled
527+ features = {
528+ fprint = {
529+ enable = false ;
530+ targetVms = [ ] ;
531+ } ;
532+ yubikey = {
533+ enable = false ;
534+ targetVms = [ ] ;
535+ } ;
536+ brightness = {
537+ enable = false ;
538+ targetVms = [ ] ;
539+ } ;
540+ wifi = {
541+ enable = false ;
542+ targetVms = [ ] ;
543+ } ;
544+ audio = {
545+ enable = false ;
546+ targetVms = [ ] ;
547+ } ;
548+ bluetooth = {
549+ enable = false ;
550+ targetVms = [ ] ;
551+ } ;
552+ } ;
287553 } ;
288554 } ;
289555
0 commit comments