Skip to content

Commit 7345ff2

Browse files
committed
feat(desktop,gateway): Phase 5 — docs reconcile + remove dead collision_client_id wiring
Signed-off-by: crimsonsunset <jsangio1@gmail.com>
1 parent 64db1c7 commit 7345ff2

11 files changed

Lines changed: 9 additions & 41 deletions

File tree

apps/desktop/src-tauri/src/commands/gateway.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,6 @@ fn map_domain_event_to_ui(event: &DomainEvent) -> (&'static str, serde_json::Val
816816
session_id,
817817
space_id,
818818
workspace_root,
819-
collision_client_id,
820819
space_locked,
821820
} => (
822821
"workspace-needs-binding",
@@ -825,7 +824,6 @@ fn map_domain_event_to_ui(event: &DomainEvent) -> (&'static str, serde_json::Val
825824
"session_id": session_id,
826825
"space_id": space_id,
827826
"workspace_root": workspace_root,
828-
"collision_client_id": collision_client_id,
829827
"space_locked": space_locked,
830828
}),
831829
),

apps/desktop/src/features/workspaces/workspace-binding-panel.component.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,6 @@ export function WorkspaceBindingPanel() {
308308
clientId: eventPayload.client_id,
309309
spaceId: eventPayload.space_id,
310310
spaceLocked: eventPayload.space_locked ?? false,
311-
collisionClientId: eventPayload.collision_client_id ?? undefined,
312311
});
313312
});
314313
}, [subscribe, open]);
@@ -812,9 +811,7 @@ export function WorkspaceBindingPanel() {
812811
mode === 'create'
813812
? t('panel.routingSubtitleCreate')
814813
: mode === 'create-from-live'
815-
? payload.collisionClientId
816-
? t('sheet.descCollision')
817-
: t('sheet.descNew')
814+
? t('sheet.descNew')
818815
: isEdit
819816
? t('panel.routingSubtitleRoutes', {
820817
featureSets:
@@ -854,14 +851,14 @@ export function WorkspaceBindingPanel() {
854851
badges={
855852
<>
856853
{mode === 'create-from-live' && (
857-
<Pill tone={payload.collisionClientId ? 'amber' : 'primary'}>
854+
<Pill tone="primary">
858855
<span className="inline-flex items-center gap-1">
859856
<Sparkles className="h-2.5 w-2.5" />
860-
{payload.collisionClientId ? t('sheet.badgeCollision') : t('sheet.badgeNew')}
857+
{t('sheet.badgeNew')}
861858
</span>
862859
</Pill>
863860
)}
864-
{mode === 'create-from-live' && !payload.collisionClientId && (
861+
{mode === 'create-from-live' && (
865862
<Pill tone="amber">{t('card.badgeLiveUnbound')}</Pill>
866863
)}
867864
{mode === 'edit' && binding && <Pill tone="neutral">{t('card.offline')}</Pill>}
@@ -887,7 +884,7 @@ export function WorkspaceBindingPanel() {
887884
</div>
888885
) : (
889886
<>
890-
{mode === 'create-from-live' && !payload.collisionClientId && (
887+
{mode === 'create-from-live' && (
891888
<div
892889
className="rounded-xl border border-amber-200/80 dark:border-amber-800/50 bg-amber-50/80 dark:bg-amber-900/15 p-4"
893890
data-testid="workspace-binding-no-tools-banner"

apps/desktop/src/lib/backend/events/useWorkspaceEvents.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ export interface WorkspaceNeedsBindingPayload {
3232
session_id: string;
3333
space_id: string;
3434
workspace_root: string;
35-
/** Set when another client's scoped binding blocked the global route. */
36-
collision_client_id?: string | null;
3735
/** When true, the Space picker is locked to `space_id`. */
3836
space_locked?: boolean;
3937
}

apps/desktop/src/locales/en/workspaces.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@
196196
"badgeCollision": "Client binding required",
197197
"badgeNew": "New workspace detected",
198198
"titleCollision": "Create a binding for this client",
199-
"titleNew": "This folder is using your Starter set",
199+
"titleNew": "Bind this folder to enable tools",
200200
"descCollision": "This path is already bound for another MCP client. Save a client-scoped binding so this machine gets its own tool set.",
201201
"descNew": "No backend tools are active on this session. Creating a binding enables tool access.",
202202
"noToolsBanner": "No backend tools are active on this session. Creating a binding enables tool access.",

apps/desktop/src/stores/bindingPanelStore.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ export interface BindingPanelPayload {
1616
clientId?: string;
1717
/** Hint for default space picker from the triggering event. */
1818
spaceId?: string;
19-
/** When set, header shows collision copy instead of new-connection badge. */
20-
collisionClientId?: string;
2119
/** When true, the Space picker is locked to `spaceId` (base-dir scoped folder). */
2220
spaceLocked?: boolean;
2321
/** Unmapped appearance icon from the card grid, seeds create-from-live icon state. */

crates/mcpmux-core/src/domain/event.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,6 @@ pub enum DomainEvent {
378378
session_id: String,
379379
space_id: Uuid,
380380
workspace_root: String,
381-
/// When set, a scoped binding for another OAuth client blocked the
382-
/// global binding on this path — the UI should offer to create a
383-
/// client-scoped binding for `client_id`.
384-
#[serde(default, skip_serializing_if = "Option::is_none")]
385-
collision_client_id: Option<String>,
386381
/// The folder is scoped to `space_id` by a Space base directory, so the
387382
/// mapping popup locks its Space field to it (the user only picks the
388383
/// FeatureSet). `false` for an ordinary unmapped folder, where the user
@@ -759,7 +754,6 @@ mod tests {
759754
session_id: "sess-1".to_string(),
760755
space_id: Uuid::new_v4(),
761756
workspace_root: "/proj/foo".to_string(),
762-
collision_client_id: None,
763757
space_locked: false,
764758
};
765759
assert!(!e.affects_mcp_capabilities());
@@ -786,12 +780,11 @@ mod tests {
786780
session_id: "s".into(),
787781
space_id: Uuid::nil(),
788782
workspace_root: "/r".into(),
789-
collision_client_id: Some("other-client".into()),
790783
space_locked: true,
791784
};
792785
let json = serde_json::to_string(&needs).unwrap();
793786
assert!(json.contains("\"type\":\"workspace_needs_binding\""));
794787
assert!(json.contains("\"session_id\":\"s\""));
795-
assert!(json.contains("\"collision_client_id\":\"other-client\""));
788+
assert!(json.contains("\"space_locked\":true"));
796789
}
797790
}

crates/mcpmux-gateway/src/admin/ui_events.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ pub fn map_domain_event_to_ui(event: &DomainEvent) -> (&'static str, Value) {
406406
session_id,
407407
space_id,
408408
workspace_root,
409-
collision_client_id,
410409
space_locked,
411410
} => (
412411
"workspace-needs-binding",
@@ -415,7 +414,6 @@ pub fn map_domain_event_to_ui(event: &DomainEvent) -> (&'static str, Value) {
415414
"session_id": session_id,
416415
"space_id": space_id,
417416
"workspace_root": workspace_root,
418-
"collision_client_id": collision_client_id,
419417
"space_locked": space_locked,
420418
}),
421419
),

crates/mcpmux-gateway/src/mcp/handler.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ impl McpMuxGatewayHandler {
165165
session_id: sid.to_string(),
166166
space_id,
167167
workspace_root: root.to_string(),
168-
collision_client_id: resolved.collision_client_id.clone(),
169168
space_locked,
170169
},
171170
);

crates/mcpmux-gateway/src/services/feature_set_resolver.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,6 @@ pub struct ResolvedFeatureSet {
150150
/// Resolved Space id. Used by the routing layer when filtering features.
151151
pub space_id: Option<Uuid>,
152152
pub source: ResolutionSource,
153-
/// When `source == Deny` because a global binding was blocked by another
154-
/// client's scoped binding on the same path, holds that client's id.
155-
pub collision_client_id: Option<String>,
156153
}
157154

158155
impl ResolvedFeatureSet {
@@ -306,7 +303,6 @@ impl FeatureSetResolverService {
306303
feature_set_ids: vec![],
307304
space_id: Some(space_id),
308305
source: ResolutionSource::Unbound,
309-
collision_client_id: None,
310306
}
311307
}
312308

@@ -336,7 +332,6 @@ impl FeatureSetResolverService {
336332
feature_set_ids: vec![],
337333
space_id: None,
338334
source: ResolutionSource::Deny,
339-
collision_client_id: None,
340335
});
341336
}
342337
};
@@ -389,7 +384,6 @@ impl FeatureSetResolverService {
389384
feature_set_ids: binding.feature_set_ids,
390385
space_id: Some(binding.space_id),
391386
source: ResolutionSource::WorkspaceBinding,
392-
collision_client_id: None,
393387
});
394388
}
395389
// Tier 1b: had roots, no binding. The folder is unmapped —
@@ -439,7 +433,6 @@ impl FeatureSetResolverService {
439433
feature_set_ids: vec![],
440434
space_id: Some(default_space_id),
441435
source: ResolutionSource::PendingRoots,
442-
collision_client_id: None,
443436
});
444437
}
445438
// Grace lapsed with no root in sight — deny by default. Go
@@ -480,7 +473,6 @@ impl FeatureSetResolverService {
480473
feature_set_ids: grants,
481474
space_id: Some(default_space_id),
482475
source: ResolutionSource::ClientGrant,
483-
collision_client_id: None,
484476
});
485477
}
486478
}

docs/guide/spaces.mdx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,7 @@ Each Space is an independent environment containing:
2929

3030
### Active Space
3131

32-
Only one Space can be **active** at a time. The active Space is the **fallback** for any session whose folder isn't mapped to a specific Space via a [Workspace](/docs/workspaces/) binding. It determines:
33-
34-
- Which servers the gateway connects to
35-
- Which tools an unmapped session sees (its active-Space FeatureSet)
36-
- Which credentials are injected into server connections
32+
Only one Space can be **active** at a time. The active Space sets the default gateway context — which servers are available and which credentials are injected when a session has a workspace binding. Unmapped folders get **no backend tools** by default; you must create an explicit [Workspace](/docs/workspaces/) binding to enable access. The Starter bundle is an opt-in default you can bind deliberately, not a silent fallback.
3733

3834
Switching the active Space immediately changes what servers and tools are available — no restart required.
3935

@@ -82,7 +78,7 @@ Navigate to **Spaces** in McpMux and click **Create Space**. Give it a name and
8278

8379
### Switching Active Space
8480

85-
Click on any Space to set it as active. The dashboard and server list update immediately to reflect the new context. Any session whose folder isn't mapped to a specific Space follows the active Space automatically.
81+
Click on any Space to set it as active. The dashboard and server list update immediately to reflect the new context. Unmapped folders stay denied until you bind them to a Space and FeatureSet.
8682

8783
### Deleting a Space
8884

0 commit comments

Comments
 (0)