Skip to content

[mxc] - Align trust-profile filesystem and network schema with MXC #1472

Description

@JoshuaRowePhantom

Part of #1471

Dependencies

None

Summary

Replace Phantom's Docker-oriented trust-profile filesystem and network schema with the model that the MXC compiler will consume. Add a declarative data-sharing model that controls copilot's access to persistent configuration and session state. No deployed trust profiles exist, so this is a direct schema replacement: do not add legacy parsing, migration, aliases, or backward-compatibility behavior. Filesystem entries become host-path grants with an optional target path, networking becomes a presence-aware set of validated MXC/AppContainer capabilities, and data-sharing specifies whether copilot accesses shared, regime-scoped, or ephemeral configuration.

Root Cause

The current persisted and runtime models encode Docker concepts that MXC cannot faithfully enforce:

  • Phantom.Workspaces.Data.Core/JsonSchemas/llm-trust-profile.json:47-62,125-160 defines mount-points, requires target-path, permits bind/volume/tmpfs, and exposes the topology enum network-access-policy.
  • Phantom.Workspaces.Llm.Core/Trust/TrustProfile.cs:7-43,75-80,96-121,128-152 defines ordered TrustNetworkAccessPolicy and Docker-oriented TrustMountType; TrustMountPoint.TargetPath is required.
  • Phantom.Workspaces.Llm.Core/Trust/TrustProfileEntityReader.cs:147-181 collapses an absent network property to NoNetwork, so it cannot distinguish unconstrained networking from explicit no-network.
  • Phantom.Workspaces.Llm.Core/Trust/TrustProfileComposer.cs:54-70,130-192 composes networking with ordinal Math.Min/Math.Max and identifies mounts by source/target/type.

MXC ProcessContainer grants access to host paths; it does not create Docker volume/tmpfs semantics or a mount namespace. MXC networking is expressed as AppContainer capability names, not a four-level topology enum. Copilot's data-access requirements (auth, cache, session state) need explicit control so different containment regimes can provide appropriate isolation without requiring overlays or proxies.

Affected Files

File Required Change
Phantom.Workspaces.Data.Core/JsonSchemas/llm-trust-profile.json Replace the old mount/network properties directly with the new host-path, capability, and data-sharing schemas.
Phantom.Workspaces.Llm.Core/Trust/TrustProfile.cs Remove TrustNetworkAccessPolicy and TrustMountType; add the new filesystem record, presence-aware capability property, and data-sharing model.
Phantom.Workspaces.Llm.Core/Trust/TrustProfileEntityReader.cs Read only the new schema and preserve absent/empty/populated network states; parse data-sharing mode.
Phantom.Workspaces.Llm.Core/Trust/TrustProfileComposer.cs Compose effective path grants, capability sets, and data-sharing mode with explicit restrictive/permissive rules.
Phantom.Workspaces.Llm.Core.Tests/TrustProfileComposerTests.cs Cover target defaulting, set composition, and data-sharing composition.
Phantom.Workspaces.Llm.Core.Tests/TrustProfileResolutionTests.cs Cover new-schema parsing, invalid old-schema rejection, and data-sharing values.
Phantom.Workspaces.Data.Core/JsonEntities/defaults/trust-profiles/*.json Rewrite shipped defaults to the new schema in the same commit.

Design / Fix

Runtime and JSON shape

Replace mount-points with filesystem-paths. Each entry has:

{
  "source-path": "C:\\work",
  "target-path": "C:\\work",
  "access-mode": "read-only"
}

target-path is optional. Its effective value is target-path ?? source-path. Remove the type property and remove TrustMountType; there is no volume or tmpfs representation.

Use a runtime record equivalent to:

public sealed record TrustFilesystemPath(
    string SourcePath,
    string? TargetPath,
    TrustFilesystemAccessMode AccessMode)
{
    public string EffectiveTargetPath => TargetPath ?? SourcePath;
}

Keep target-path only so a future execution backend can express remapping. The MXC compiler in #1475 rejects normalized EffectiveTargetPath != SourcePath; no layer silently rewrites or approximates remapping.

Replace network-access-policy with optional network-capabilities:

"network-capabilities": ["internetClient"]

Represent presence separately from the collection value, for example with nullable IReadOnlyList<string>? NetworkCapabilities where null means absent. Preserve exactly:

  • absent: unconstrained for this process-policy dimension and does not itself require containment;
  • []: explicit no-network and does require containment;
  • populated: containment with exactly those capabilities.

The reader validates JSON shape, rejects null/blank/duplicate values, and preserves capability spelling with ordinal comparison. MXC-specific capability support validation belongs to #1475 so it uses the pinned SDK and launch-host capabilities.

Data-sharing model

Add optional data-sharing property controlling copilot's access to persistent configuration (~/.copilot/, session directories, etc.):

"data-sharing": "full" | { "regime": "<name>" } | "none"

Semantics:

  • "full" (default if absent): Copilot accesses ~/.copilot/ and shared session directories with full read/write access. Auth tokens, cache, history, and session state are shared across all instances. Use for integrated, trusted environments.

  • { "regime": "<name>" }: Copilot accesses regime-scoped directories (~/.copilot/<regime>-session/, isolated session temp dirs). Each regime has independent auth, cache, and history. Use for sandboxed profiles, multi-tenant isolation, or different containment contexts.

  • "none": Copilot accesses only ephemeral temp directories with no persistent state. Each session is fresh; no auth tokens, cache, or history are retained. Use for untrusted models, one-shot execution, or privacy-critical scenarios.

Represent in runtime as:

public sealed record TrustDataSharing
{
    public static TrustDataSharing Full { get; } = new Full();
    public static TrustDataSharing None { get; } = new None();
    public static TrustDataSharing Regime(string regimeName) => new RegimeScoped(regimeName);
    
    public sealed record Full : TrustDataSharing { }
    public sealed record RegimeScoped(string RegimeName) : TrustDataSharing { }
    public sealed record None : TrustDataSharing { }
}

Use "full" as the default if data-sharing is absent.

Composition

Filesystem identity uses canonical source plus canonical effective target. An omitted target and an explicit target equal to source are identical. When the same grant appears in both profiles, restrictive composition chooses read-only if either side is read-only; permissive composition chooses read-write if either side is read-write. Preserve the repository's existing path-comparison policy until #1475 performs host-local canonicalization.

Networking is commutative:

  • restrictive: two present sets intersect; absent is the identity (absent ∩ X = X);
  • permissive: two present sets union; absent is unconstrained and dominates (absent ∪ X = absent).

Use ordinal set equality/de-duplication. Do not assign ordering or topology meaning to capability names.

Data-sharing composition (restrictive): later in the chain overrides earlier (last-write-wins). This reflects that different containment contexts (local vs. remote, untrusted vs. trusted) have different security postures. If composed profiles disagree (e.g., one specifies full, another specifies none), the more restrictive value (none) takes effect.

Direct replacement, no compatibility layer

Remove the old JSON properties, enums, parser branches, defaults, and tests. Old mount-points, type, network-access-policy, and data-sharing input must fail schema/reader validation as unknown or invalid input. Do not recognize or migrate no-network, local-network, natted-network, host-network, volume, or tmpfs. Update all checked-in defaults and test fixtures atomically.

Expected Tests

Test Name Class What It Verifies
Read_FilesystemTargetPathOmitted_UsesSourcePath TrustProfileResolutionTests An omitted target has an effective target equal to source.
Read_FilesystemTypePresent_RejectsRemovedProperty TrustProfileResolutionTests The removed Docker type property is not accepted.
Read_LegacyNetworkAccessPolicy_RejectsRemovedProperty TrustProfileResolutionTests The removed topology property is not parsed or migrated.
Read_NetworkCapabilitiesAbsent_PreservesUnconstrainedState TrustProfileResolutionTests Absence remains distinct from explicit no-network.
Read_EmptyNetworkCapabilities_PreservesExplicitNoNetwork TrustProfileResolutionTests An empty array remains present and empty.
Read_DuplicateNetworkCapability_RejectsProfile TrustProfileResolutionTests Duplicate capability names fail validation.
Read_DataSharingAbsent_DefaultsToFull TrustProfileResolutionTests Absent data-sharing is read as Full.
Read_DataSharingRegime_ParsesRegimeName TrustProfileResolutionTests Regime-scoped data-sharing is parsed with regime name.
Read_DataSharingNone_PreservesEphemeralMode TrustProfileResolutionTests Explicit none is read as ephemeral.
Compose_EquivalentImplicitAndExplicitTargets_MatchesFilesystemPath TrustProfileComposerTests Implicit-source and explicit-source targets compose as one grant.
MergeRestrictive_NetworkCapabilities_Intersects TrustProfileComposerTests Restrictive composition intersects present sets and treats absent as identity.
MergePermissive_NetworkCapabilities_Unions TrustProfileComposerTests Permissive composition unions present sets and treats absent as unconstrained.
MergeRestrictive_DataSharing_UsesMoreRestricted TrustProfileComposerTests Restrictive composition applies most restrictive data-sharing (none > regime > full).
MergePermissive_DataSharing_UsesLessRestricted TrustProfileComposerTests Permissive composition applies least restrictive data-sharing (full > regime > none).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingdiagnosedRoot cause identifiedverified-locallyImplementation has been verified locally

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions