From d44ed78e5ce13f2aead7af2b565077a48b2018e9 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Tue, 18 Aug 2026 21:32:25 +0200 Subject: [PATCH] feat: preserve full-page launch context --- docs/QUICK_ACCESS.md | 9 +++-- src/govoplan_quick_access/backend/manifest.py | 15 ++++++--- webui/src/components/QuickAccessRail.tsx | 33 +++++++++++++++++-- webui/src/styles/quick-access.css | 23 ++++++++++--- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/docs/QUICK_ACCESS.md b/docs/QUICK_ACCESS.md index 511e16c..0e079d0 100644 --- a/docs/QUICK_ACCESS.md +++ b/docs/QUICK_ACCESS.md @@ -37,5 +37,10 @@ owner module. Quick Access is not an authorization boundary. Every contribution keeps its own permission requirements and View surface. Full-page routes remain the -canonical fallback. Disabling this module removes the rail without making any -domain state unavailable through its owning module. +canonical fallback. Launch context version 1 contains only the tenant/account +identity, safe active-object reference, acting-assignment identifiers, +temporal selection, exact View identity, and return route. Cross-tenant object +references are discarded and unknown context versions are ignored. The +destination reauthorizes every read and effect. Disabling this module removes +the rail without making any domain state unavailable through its owning +module. diff --git a/src/govoplan_quick_access/backend/manifest.py b/src/govoplan_quick_access/backend/manifest.py index 48bc06c..e399a45 100644 --- a/src/govoplan_quick_access/backend/manifest.py +++ b/src/govoplan_quick_access/backend/manifest.py @@ -120,7 +120,10 @@ DOCUMENTATION = ( "Open a category on the right rail to use compact tools without leaving the current task. " "Messages combines enabled Mail, Postbox, and future chat contributions in one overlay. " "Personal settings can reorder or hide items that remain available under system, tenant, " - "permission, and View policy. Every item retains a link to its complete owning page." + "permission, and View policy. Every item retains a link to its complete owning page. " + "That launch carries a versioned, bounded reference to the current object, acting assignment, " + "temporal selection, View revision, and return location. The destination rechecks access, and " + "the breadcrumb return action restores the originating route without copying protected content." ), layer="configured", documentation_types=("user",), @@ -139,7 +142,9 @@ DOCUMENTATION = ( "body": ( "Eine Kategorie in der rechten Leiste oeffnet kompakte Werkzeuge, ohne die aktuelle Aufgabe zu verlassen. " "Nachrichten fuehrt Beitraege aus Mail, Postfach und kuenftigen Chat-Modulen in einer Einblendung zusammen. " - "Persoenliche Einstellungen koennen alle durch System, Mandant, Berechtigungen und Ansicht zugelassenen Eintraege ordnen oder ausblenden." + "Persoenliche Einstellungen koennen alle durch System, Mandant, Berechtigungen und Ansicht zugelassenen Eintraege ordnen oder ausblenden. " + "Beim Oeffnen der vollstaendigen Seite werden nur versionierte, begrenzte Verweise auf Objekt, handelnde Zuordnung, " + "Zeitbezug, Ansichtsversion und Ruecksprungort uebergeben. Das Ziel prueft den Zugriff erneut." ), } }, @@ -158,7 +163,8 @@ DOCUMENTATION = ( body=( "The catalogue follows installed module registrations. System settings constrain tenants; " "tenant settings constrain users. An item may remain available, be blocked, or be forced. " - "Views and permissions form additional ceilings and Quick Access never grants access to domain data." + "Views and permissions form additional ceilings and Quick Access never grants access to domain data. " + "Launch context version 1 rejects cross-tenant active-object references and unknown context versions fail closed." ), layer="configured", documentation_types=("admin",), @@ -170,7 +176,8 @@ DOCUMENTATION = ( "body": ( "Der Katalog folgt den Registrierungen installierter Module. Systemeinstellungen begrenzen Mandanten, " "Mandanteneinstellungen begrenzen Benutzer. Ein Eintrag kann verfuegbar, gesperrt oder erzwungen sein. " - "Ansichten und Berechtigungen bilden weitere Grenzen; Schnellzugriff erteilt selbst keinen Datenzugriff." + "Ansichten und Berechtigungen bilden weitere Grenzen; Schnellzugriff erteilt selbst keinen Datenzugriff. " + "Startkontext Version 1 verwirft mandantenfremde Objektverweise; unbekannte Versionen werden abgelehnt." ), } }, diff --git a/webui/src/components/QuickAccessRail.tsx b/webui/src/components/QuickAccessRail.tsx index af915fe..f5b3476 100644 --- a/webui/src/components/QuickAccessRail.tsx +++ b/webui/src/components/QuickAccessRail.tsx @@ -13,6 +13,9 @@ import { DismissibleAlert, IconButton, LoadingFrame, + dispatchQuickAccessResult, + quickAccessLaunchState, + useGuardedNavigate, usePlatformLanguage, usePlatformUiCapabilities, type QuickAccessRailProps, @@ -32,7 +35,7 @@ const iconByCategory: Record = { files: Files }; -export default function QuickAccessRail({ settings, auth, tools }: QuickAccessRailProps) { +export default function QuickAccessRail({ settings, auth, tools, launchContext }: QuickAccessRailProps) { const [effective, setEffective] = useState(null); const [activeCategoryId, setActiveCategoryId] = useState(null); const [loading, setLoading] = useState(true); @@ -40,6 +43,7 @@ export default function QuickAccessRail({ settings, auth, tools }: QuickAccessRa const drawerRef = useRef(null); const triggerRef = useRef(null); const location = useLocation(); + const navigate = useGuardedNavigate(); const contributions = usePlatformUiCapabilities("quickAccess.tools"); const { translateText } = usePlatformLanguage(); const renderers = useMemo( @@ -125,6 +129,11 @@ export default function QuickAccessRail({ settings, auth, tools }: QuickAccessRa setActiveCategoryId(category.id); } + function openFullPage(path: string) { + closeDrawer(false); + navigate(path, { state: quickAccessLaunchState(launchContext) }); + } + return ( <>