security(docs): prevent stale projection rendering

This commit is contained in:
2026-07-21 19:15:03 +02:00
parent 7cdd1e1c78
commit 901baf8352

View File

@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import { Link, useLocation } from "react-router-dom";
import { ChevronDown, ChevronRight, RefreshCw } from "lucide-react";
import {
@@ -67,20 +67,29 @@ export default function DocsPage({ settings }: { settings: ApiSettings }) {
const [context, setContext] = useState<DocsContext | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const loadSequence = useRef(0);
const [documentationType, setDocumentationType] = useState<DocumentationType>(() => documentationTypeFromSearch(location.search));
const [expandedNodes, setExpandedNodes] = useState<Set<string>>(() => new Set());
const locale = localeFromSearch(location.search) ?? language;
const adminDocs = documentationType === "admin";
async function load() {
const sequence = ++loadSequence.current;
setLoading(true);
setError("");
setContext(null);
try {
setContext(await fetchDocsContext(settings, { documentationType, locale }));
const nextContext = await fetchDocsContext(settings, { documentationType, locale });
if (sequence !== loadSequence.current) return;
if (nextContext.actor.documentation_type !== documentationType) {
throw new Error("Documentation response type did not match the requested projection.");
}
setContext(nextContext);
} catch (err) {
if (sequence !== loadSequence.current) return;
setError(adminErrorMessage(err));
} finally {
setLoading(false);
if (sequence === loadSequence.current) setLoading(false);
}
}