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). |
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-160definesmount-points, requirestarget-path, permitsbind/volume/tmpfs, and exposes the topology enumnetwork-access-policy.Phantom.Workspaces.Llm.Core/Trust/TrustProfile.cs:7-43,75-80,96-121,128-152defines orderedTrustNetworkAccessPolicyand Docker-orientedTrustMountType;TrustMountPoint.TargetPathis required.Phantom.Workspaces.Llm.Core/Trust/TrustProfileEntityReader.cs:147-181collapses an absent network property toNoNetwork, so it cannot distinguish unconstrained networking from explicit no-network.Phantom.Workspaces.Llm.Core/Trust/TrustProfileComposer.cs:54-70,130-192composes networking with ordinalMath.Min/Math.Maxand 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
Phantom.Workspaces.Data.Core/JsonSchemas/llm-trust-profile.jsonPhantom.Workspaces.Llm.Core/Trust/TrustProfile.csTrustNetworkAccessPolicyandTrustMountType; add the new filesystem record, presence-aware capability property, and data-sharing model.Phantom.Workspaces.Llm.Core/Trust/TrustProfileEntityReader.csPhantom.Workspaces.Llm.Core/Trust/TrustProfileComposer.csPhantom.Workspaces.Llm.Core.Tests/TrustProfileComposerTests.csPhantom.Workspaces.Llm.Core.Tests/TrustProfileResolutionTests.csPhantom.Workspaces.Data.Core/JsonEntities/defaults/trust-profiles/*.jsonDesign / Fix
Runtime and JSON shape
Replace
mount-pointswithfilesystem-paths. Each entry has:{ "source-path": "C:\\work", "target-path": "C:\\work", "access-mode": "read-only" }target-pathis optional. Its effective value istarget-path ?? source-path. Remove thetypeproperty and removeTrustMountType; there is novolumeortmpfsrepresentation.Use a runtime record equivalent to:
Keep
target-pathonly so a future execution backend can express remapping. The MXC compiler in #1475 rejects normalizedEffectiveTargetPath != SourcePath; no layer silently rewrites or approximates remapping.Replace
network-access-policywith optionalnetwork-capabilities:Represent presence separately from the collection value, for example with nullable
IReadOnlyList<string>? NetworkCapabilitieswhere null means absent. Preserve exactly:[]: explicit no-network and does require containment;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-sharingproperty controlling copilot's access to persistent configuration (~/.copilot/, session directories, etc.):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:
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:
absent ∩ X = X);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 specifiesnone), 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, anddata-sharinginput must fail schema/reader validation as unknown or invalid input. Do not recognize or migrateno-network,local-network,natted-network,host-network,volume, ortmpfs. Update all checked-in defaults and test fixtures atomically.Expected Tests
Read_FilesystemTargetPathOmitted_UsesSourcePathTrustProfileResolutionTestsRead_FilesystemTypePresent_RejectsRemovedPropertyTrustProfileResolutionTeststypeproperty is not accepted.Read_LegacyNetworkAccessPolicy_RejectsRemovedPropertyTrustProfileResolutionTestsRead_NetworkCapabilitiesAbsent_PreservesUnconstrainedStateTrustProfileResolutionTestsRead_EmptyNetworkCapabilities_PreservesExplicitNoNetworkTrustProfileResolutionTestsRead_DuplicateNetworkCapability_RejectsProfileTrustProfileResolutionTestsRead_DataSharingAbsent_DefaultsToFullTrustProfileResolutionTestsFull.Read_DataSharingRegime_ParsesRegimeNameTrustProfileResolutionTestsRead_DataSharingNone_PreservesEphemeralModeTrustProfileResolutionTestsnoneis read as ephemeral.Compose_EquivalentImplicitAndExplicitTargets_MatchesFilesystemPathTrustProfileComposerTestsMergeRestrictive_NetworkCapabilities_IntersectsTrustProfileComposerTestsMergePermissive_NetworkCapabilities_UnionsTrustProfileComposerTestsMergeRestrictive_DataSharing_UsesMoreRestrictedTrustProfileComposerTestsnone>regime>full).MergePermissive_DataSharing_UsesLessRestrictedTrustProfileComposerTestsfull>regime>none).