Skip to content

Merging and Precedence

When multiple scopes or policies contribute flags, arguments, launch profiles, and routing, the final launch configuration is produced by two steps: selecting the Active Policy (location) and merging scopes within that policy.

What You'll Learn

  • How the system selects the Active Policy (Hub, Workspace, or User)
  • How scopes merge inside the Active Policy (Launch Profile > User Configuration > Policy > Global)
  • How flags, arguments, mounts, networking, and routing resolve conflicts
  • How authorization tie-breaks affect routing and handlers

Active Policy Selection (Location Precedence)

Before any merges occur, Turbo Launcher selects a single Active Policy file.

Rules

  • Hub (enterprise) policy at %PROGRAMDATA%\Turbo\Launcher\policy.json is authoritative when present; it becomes the Active Policy and replaces workspace or user policies.
  • Workspace policy applies only when launching in a workspace context and no Hub policy exists; it becomes the Active Policy for that launch.
  • If neither Hub nor workspace policy exists, the user policy at %LOCALAPPDATA%\Turbo\Launcher\policy.json becomes the Active Policy when present.
  • There is no cross-location merging; all merges and tie-breaks occur inside the Active Policy only. See full load/merge semantics in Deployment.
Mermaid Diagram

Workspace policies are evaluated only when launching in a workspace context and must honor Hub-defined constraints when a Hub policy exists.

Scope Precedence and Merge Order (Active Policy)

Once the Active Policy is selected, configuration merges from least to most specific:

  1. Global Configuration
  2. Application Policy
  3. User Configuration (per-user customizations inside the Active Policy)
  4. Launch Profile

The following diagram summarizes scope precedence within the Active Policy:

Mermaid Diagram

Evaluation order

  1. Start with Global Configuration (configuration.launch.runtime and global mounts).
  2. Merge enabled action: "allow" application policies (sorted by priority descending, then id alphabetical). Apply their modifications and collect their launch profiles (profiles) and capabilities.
  3. Apply User Configuration from the Active Policy.
  4. If a Launch Profile is selected, apply its modifications last on top of the merged result.

User Configuration is a scope inside the Active Policy; it is distinct from the user policy file selected during location precedence.

Merge Strategies by Data Type

ElementMerge StrategyConflict Resolution
MountsAdditivename (or destination when name is missing) last-wins by scope; policy ties use priority then id.
ArgumentsConcatenationreplace overrides; otherwise prepend/append follow scope order.
Keyed flagsLast-winsScope precedence; policy ties use priority then id.
Switch flagsDe-duplicationDeduplicate by exact string; ordered by scope.
NetworkingMixedRules are additive; arrays replace; booleans last-wins; ports replace per scope.
File routingAdditiveHighest rule priority, then rule id; default: true within a rule wins first.

Use priority (descending) then policy id (alphabetical) as the consistent tie-break inside the Policy scope.

Security and Authorization (Deny vs Allow)

Security rule: Deny overrides allow
During authorization, if any matching enabled policy has action: "deny", the launch is blocked and the app is treated as unauthorized, regardless of how many action: "allow" policies match.

Authorization evaluation occurs before visibility, modifications, capabilities, and routing resolution.

  • Collect all enabled application policies that match the discovered executable. Matching evaluates matchAll (AND) or matchAny (OR), including any nested groups. Apply any identity requirements.
  • If any matching policy has action: "deny", authorization is denied. The app is not visible and cannot be used by routing.
  • Otherwise, if any matching policy has action: "allow", the app is authorized. Modifications and launch profile merges proceed among matching allow policies (priority desc, then id alphabetical).
  • If no allow policies match, the app is not authorized.

Site Visibility

Site constraints are evaluated after authorization but affect visibility only:

  1. Authorization check (allow/deny) must pass first
  2. visibility: "hidden" takes absolute precedence (always hidden)
  3. If visibility: "visible" and siteRefs is specified, the app is visible only when the selected site matches

Site constraints do not affect file association routing—hidden-by-site apps can still serve as handlers.

Runtime settings and VM flags

Flag key normalization

  • A flag’s key is the portion after leading dashes up to the first "=" or whitespace.
    • --clipboard-size=1000 → key clipboard-size
    • --remote-sandbox → key remote-sandbox

Rules

  • Keyed flags: Last-wins per key by scope precedence (Launch Profile > Policy > Global). Within the Policy scope, tie-break by priority (desc), then id (alphabetical).
  • Unkeyed flags (pure switches): De-duplicate by exact string; final order is Profile → Policies (by priority desc, then id) → Global.

Example (flags)

  • Global: --clipboard-size=1000
  • Policy A (priority 200): --clipboard-size=500
  • Profile: none
  • Result: --clipboard-size=500 (Policy overrides Global). If the Launch Profile sets --clipboard-size=200, it wins.

For authoring runtime settings and examples, see: Schema Reference

Arguments

Fields

  • prepend: Insert before base shortcut arguments.
  • append: Insert after base shortcut arguments.
  • replace: Replace the entire argument string.

Rules

  • replace overrides both prepend and append within the same scope.
  • Overall scope precedence is Launch Profile > Policy > Global.
  • When no replace exists at any scope:
    • Prepend order: Global.prepend → Policies.prepend (by priority desc, then id) → Launch Profile.prepend → base shortcut args
    • Append order: base shortcut args → Global.append → Policies.append (by priority desc, then id) → Launch Profile.append

Example (args concatenation, no replace)

  • Global.append: --enable=sandboxnetwork
  • Policy A.append: --incognito
  • Launch Profile.append: --hide-crash-restore-bubble
  • Result: [base] --enable=sandboxnetwork --incognito --hide-crash-restore-bubble

For authoring arguments and examples, see: Application Arguments

Mounts precedence and merging

When mounts are defined at multiple scopes, final mounts are produced by deterministic precedence and merging:

  • Scope precedence (most specific wins): Launch Profile > User Configuration > Policy (App) > Global
  • Additive merge: Mounts are additive across scopes.
  • Conflict resolution:
    • Prefer identity by "name" when present; conflicts on the same "name" resolve last-wins by scope precedence (Launch Profile overrides Policy overrides Global).
    • If "name" is not present, conflicts resolve by "destination" using the same precedence.
    • Within the Policy scope, ordering for ties follows application policy priority (descending), then policy id alphabetical, consistent with flags/args.

Visual merge & conflict resolution (mounts)

The following diagram summarizes how mounts are merged across scopes and how conflicts are resolved:

Mermaid Diagram

See authoring details and examples: Mounts & Shared Storage

Networking precedence and proxy routing selection

Scope precedence (most specific wins)

  • Launch Profile > Policy (App) > Global.

Capabilities merging

  • Booleans (outboundAllowed, inboundAllowed, dnsAllowed): last-wins by scope.
  • Arrays (protocols, dnsServers, dnsSearchSuffixes): last-wins replacement by scope for determinism.
  • Ports (allow/deny):
    • Within a scope: deny overrides allow at evaluation time.
    • Across scopes: last-wins replacement of the entire ports object (Policy or Launch Profile can replace Global).
  • egressDefaultAction: last-wins by scope.

Proxy catalog (proxies[])

  • Defined only at Global scope: configuration.network.proxies.
  • App/profile scopes reference proxies by proxyRef; they cannot define proxies.

Proxy routing rules

  • Rules are additive across scopes (Global + Policy + Launch Profile).
  • For each connection:
    1. Filter to enabled rules whose destination match passes (cidrs, ipRanges, hosts, optional ports/protocol).
    2. Choose the rule with highest priority (descending); ties break by rule id (alphabetical).
    3. Apply action:
      • proxy: route via proxyRef; if the proxy endpoint fails and failover is set, apply failover (direct or deny).
      • direct: connect without proxy.
      • deny: block the connection (short-circuits).

See authoring details:

Launch Profiles

Combining launch profiles

  • Launch profiles from all matching allow policies are collected.
  • Conflicts by id resolve to the launch profile from the highest priority policy; ties break by policy id (alphabetical).
  • Launch profile modifications apply after all base modifications have been merged.

UI behavior

  • The context menu shows Run (base), then one item per launch profile (displayName), followed by diagnostic/reset entries.

See full launch profile details and examples: Launch Profiles

Routing selection and tie-breaks

Terminology

  • fileTypes: central registry that determines what a file “is” (e.g., pdf, word-docs).
  • fileAssociations: central UX that defines which handlers exist per verb (preview/open/edit/print), which are default, and which appear in Open With.
  • apps[].capabilities: per-app declarations of supported fileTypes and verbs with invocation details; capabilities do not determine UI by themselves.

Resolution pipeline (per file and verb)

  1. Determine fileType:
    • Match the file against fileTypes[].match. If multiple match, prefer a more specific match when determinable (for example, a single-extension type over a broader multi-extension type that also includes the same extension); otherwise tie-break by fileType id alphabetical.
    • Extension matching is case-insensitive.
  2. Collect routing rules:
    • Gather enabled fileAssociations rules where fileTypeRef equals the chosen fileType id.
  3. Aggregate handlers for the requested verb from those routing rules.
  4. Choose default handler:
    • Any handler with default: true.
    • Else highest routing rule priority (descending).
    • Else stable alphabetical tie-break by routing rule id (fallback to rule displayName when id is missing).
  5. Open With:
    • All handlers where showInOpenWith: true.
  6. Security gating:
    • Handlers referencing apps via appRef or targetPath require an enabled action: "allow" app policy that matches the executable; otherwise the handler is ignored.

Print

  • The Print action is available only when at least one routing rule provides verbs.print for the selected fileType.
  • If none provide verbs.print, Print is not offered.

Tie-break ordering within Policy scope

When multiple enabled allow policies match the same executable:

  • Sort by priority descending.
  • If ties remain, use stable alphabetical ordering by policy id.
  • Apply this order when merging policy-scope flags and arguments and when resolving launch profile conflicts.

Tie-breaks for file policies and routing rules

  • File policies (list/import/export/open/delete): Conflicts within the active policy resolve by rule priority (descending), then rule id alphabetical (fallback to displayName when id is missing).
  • File association rules: Primary selection uses explicit default: true within a rule and then rule priority. When a tie-break is needed across rules, use rule id alphabetical (fallback to displayName when id is missing).

UI vs device responsibilities

  • UI-level (routing): Print handlers defined in fileAssociations.verbs.print resolve like other verbs. Selection order is rule priority (descending), then rule id alphabetical; within a rule, default: true wins, else array order. If no applicable rule provides verbs.print, the Print action is not offered for those files.
  • Device-level (runtime): Printer availability inside applications is enforced by the runtime using environment-specific configuration carried as opaque strings via flags. These settings do not change routing selection; they control whether printers are available during app execution.

Precedence for device-level settings carried via runtime settings

  • Scope precedence: Launch Profile > Policy > Global
  • Runtime behavior: Scalars are last-wins by scope; arrays use last-wins replacement. See: Schema Reference

Security gating for routing

Routing entries reference applications by appRef or targetPath. A referenced app must be authorized:

  • There must be at least one enabled application policy with action: "allow" that matches the executable (including high-assurance matchers if present).
  • Otherwise that routing entry is ignored.

For routing semantics and examples, see: File Types & Routing

Troubleshooting precedence

  • “Flag didn’t take effect”: Check for a more specific scope overriding it (Profile usually wins). For keyed flags, verify the final key value.
  • “Arguments missing”: Look for replace at any scope; it overrides prepend/append. If none, verify the scope concatenation order.
  • “Wrong launch profile won”: Ensure unique launch profile id, or adjust policy priority/id to control tie-breaks.
  • “Unexpected file handler”: Confirm the chosen fileType, then inspect routing rule priority, default: true, and rule ids; also ensure security gating did not filter out another candidate.

Templates and precedence

  • Active Policy: Templates are defined and enforced inside the Active Policy (typically enterprise). See: Deployment and Active Policy Selection.
  • Authorization: The presence of templates does not bypass authorization. An app must still be discoverable and allowed by at least one enabled app policy with action: "allow". Templates constrain user-provided inputs (environment variables and mounts).
  • Merge interactions: Templates do not contribute runtime settings or arguments directly. Standard merges for runtime/arguments remain unchanged (Launch Profile > User Configuration > Policy > Global).
  • App linkage: Apps opt into templates via apps[].configurationTemplates. Multiple apps can reference the same template to share a constrained configuration surface.
  • Validation timing: Environment variables referenced inside patterns are resolved at validation time. Mount constraints in templates are applied to user configurations at validation time.

Next steps