fix(auth): harden interactive diagnostic lifecycle

This commit is contained in:
2026-08-17 17:57:10 +02:00
parent ef244ab56d
commit af16464e68
9 changed files with 576 additions and 59 deletions
+15 -6
View File
@@ -85,6 +85,7 @@ export function WorkspaceManager({
const [authentication, setAuthentication] = useState<AuthDiagnostics>();
const [busyAction, setBusyAction] = useState<string>();
const operationEpochRef = useRef(0);
const diagnosticEpochRef = useRef(0);
const selectedIdRef = useRef(selectedId);
selectedIdRef.current = selectedId;
useEffect(() => () => { operationEpochRef.current += 1; }, []);
@@ -192,6 +193,7 @@ export function WorkspaceManager({
if (!detailQuery.data) return;
const guard = captureAuthOperation({ sessionId: selectedId, disposalEpoch: operationEpochRef.current });
if (!guard) return;
const diagnosticEpoch = ++diagnosticEpochRef.current;
setBusyAction("validate");
clearGlobalMessages();
setAuthentication(undefined);
@@ -199,15 +201,18 @@ export function WorkspaceManager({
setValidationDiagnostics([]);
try {
const result = await validateWorkspace(detailQuery.data.workspace);
if (!isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) return;
if (diagnosticEpoch !== diagnosticEpochRef.current ||
!isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) return;
setAuthentication(result.authentication);
setValidationNotice(result.activatable ? "Workspace source and authentication are valid." : "Workspace source is valid.");
} catch (error) {
if (isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) {
if (diagnosticEpoch === diagnosticEpochRef.current &&
isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) {
setValidationDiagnostics([publicError(error, "workspace_invalid: Workspace validation could not be completed")]);
}
} finally {
if (isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) setBusyAction(undefined);
if (diagnosticEpoch === diagnosticEpochRef.current &&
isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) setBusyAction(undefined);
}
}
@@ -216,6 +221,7 @@ export function WorkspaceManager({
const targetId = selectedId;
const guard = captureAuthOperation({ sessionId: targetId, disposalEpoch: operationEpochRef.current });
if (!guard) return;
const diagnosticEpoch = ++diagnosticEpochRef.current;
setBusyAction("test");
clearGlobalMessages();
setAuthentication(undefined);
@@ -223,7 +229,8 @@ export function WorkspaceManager({
setConnectionDiagnostics([]);
try {
const result = await testWorkspace(selectedId);
if (!isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) return;
if (diagnosticEpoch !== diagnosticEpochRef.current ||
!isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) return;
setAuthentication(result.authentication);
const issues = result.diagnostics.filter(({ level }) => level !== "info");
const informational = result.diagnostics.find(({ level }) => level === "info");
@@ -236,11 +243,13 @@ export function WorkspaceManager({
: "Workspace connection test completed.");
}
} catch (error) {
if (isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) {
if (diagnosticEpoch === diagnosticEpochRef.current &&
isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) {
setConnectionDiagnostics([publicError(error, "connector_unavailable: Workspace connections could not be tested")]);
}
} finally {
if (isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) setBusyAction(undefined);
if (diagnosticEpoch === diagnosticEpochRef.current &&
isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) setBusyAction(undefined);
}
}