Stop stealing conversation.hero.workspace slot with a null lock.

Default priority 0 lock displaced the shipped picker; clearing it left workspaces unselectable and blocked Session create in the DSH UI. Deny open-workspace with CSS and click guards only.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-16 23:22:18 +08:00
parent 91d2515205
commit 7c899942fb
2 changed files with 7 additions and 46 deletions

View file

@ -1981,51 +1981,14 @@ function reloadAfterLogin() {
event.stopPropagation() event.stopPropagation()
}, true) }, true)
let workspaceDispose = null // Do NOT register into conversation.hero.workspace. A null lock at the
const LockedWorkspace = function UdsAuthLockedWorkspace(props) { // default priority 0 steals the shipped picker (same single-slot clash as
React.useEffect(() => { // directoryFlow); clearing it never restores the occupant, so workspaces
if (props && props.open) { // cannot be selected and sessions cannot be created in the DSH UI.
try { props.onClose && props.onClose() } catch { /* ignore */ }
}
}, [props && props.open])
return null
}
const installWorkspaceLock = () => {
if (workspaceDispose) return
try {
workspaceDispose = ctx.slots.register({
name: 'conversation.hero.workspace',
id: 'uds-auth-workspace-lock',
order: 9999,
}, LockedWorkspace)
} catch { /* slot may be undeclared briefly */ }
}
const clearWorkspaceLock = () => {
if (workspaceDispose) {
try { workspaceDispose() } catch { /* ignore */ }
workspaceDispose = null
}
}
// Deny open-workspace by default until AuthBadge /api/me proves canCreateWorkspace.
freezeChoosers() freezeChoosers()
const onAuth = () => { freezeChoosers() }
const syncWorkspaceSlot = () => {
// Use AuthBadge DOM attrs only — no default /api/me.
const canCreate = document.documentElement.getAttribute('data-uds-can-create-ws') === '1'
if (canCreate) clearWorkspaceLock()
else installWorkspaceLock()
freezeChoosers()
}
let workspaceInjectOff = null
try {
workspaceInjectOff = ctx.slots.inject('conversation.hero.workspace', () => {
syncWorkspaceSlot()
})
} catch { /* ignore */ }
syncWorkspaceSlot()
const onAuth = () => { syncWorkspaceSlot() }
window.addEventListener('uds-auth-changed', onAuth) window.addEventListener('uds-auth-changed', onAuth)
const mo = new MutationObserver(() => { freezeChoosers(); syncWorkspaceSlot() }) const mo = new MutationObserver(() => { freezeChoosers() })
mo.observe(document.documentElement, { mo.observe(document.documentElement, {
childList: true, childList: true,
subtree: true, subtree: true,
@ -2039,8 +2002,6 @@ function reloadAfterLogin() {
document.removeEventListener('pointerdown', block, true) document.removeEventListener('pointerdown', block, true)
document.removeEventListener('mousedown', block, true) document.removeEventListener('mousedown', block, true)
window.removeEventListener('uds-auth-changed', onAuth) window.removeEventListener('uds-auth-changed', onAuth)
clearWorkspaceLock()
try { if (typeof workspaceInjectOff === 'function') workspaceInjectOff() } catch { /* ignore */ }
} }
}, 'uds-auth: workspace-click-lock') }, 'uds-auth: workspace-click-lock')
ctx.effect(() => { ctx.effect(() => {

View file

@ -1,6 +1,6 @@
{ {
"name": "uds-auth", "name": "uds-auth",
"version": "0.2.11", "version": "0.2.12",
"description": "UDS authentication plugin for DeepSeek Harness with multi-tenant session isolation", "description": "UDS authentication plugin for DeepSeek Harness with multi-tenant session isolation",
"type": "module", "type": "module",
"main": "lib/index.js", "main": "lib/index.js",