docs(search): add complete German workflow guidance
Module Package Release / publish-packages (push) Successful in 11s
Module Package Release / publish-packages (push) Successful in 11s
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/search-webui",
|
"name": "@govoplan/search-webui",
|
||||||
"version": "0.1.18",
|
"version": "0.1.19",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "webui/src/index.ts",
|
"main": "webui/src/index.ts",
|
||||||
|
|||||||
+2
-2
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "govoplan-search"
|
name = "govoplan-search"
|
||||||
version = "0.1.18"
|
version = "0.1.19"
|
||||||
description = "Permission-aware global and contextual search for GovOPlaN."
|
description = "Permission-aware global and contextual search for GovOPlaN."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
authors = [{ name = "GovOPlaN" }]
|
authors = [{ name = "GovOPlaN" }]
|
||||||
dependencies = ["govoplan-core>=0.1.18"]
|
dependencies = ["govoplan-core>=0.1.37"]
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
where = ["src"]
|
where = ["src"]
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"""GovOPlaN search module."""
|
"""GovOPlaN search module."""
|
||||||
|
|
||||||
__version__ = "0.1.18"
|
__version__ = "0.1.19"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from govoplan_core.core.module_guards import (
|
|||||||
)
|
)
|
||||||
from govoplan_core.core.modules import (
|
from govoplan_core.core.modules import (
|
||||||
CapabilityDocumentation,
|
CapabilityDocumentation,
|
||||||
|
DocumentationCondition,
|
||||||
DocumentationLink,
|
DocumentationLink,
|
||||||
DocumentationTopic,
|
DocumentationTopic,
|
||||||
FrontendModule,
|
FrontendModule,
|
||||||
@@ -39,7 +40,7 @@ from govoplan_search.backend.dsar_provider import (
|
|||||||
|
|
||||||
MODULE_ID = "search"
|
MODULE_ID = "search"
|
||||||
MODULE_NAME = "Search"
|
MODULE_NAME = "Search"
|
||||||
MODULE_VERSION = "0.1.18"
|
MODULE_VERSION = "0.1.19"
|
||||||
READ_SCOPE = "search:result:read"
|
READ_SCOPE = "search:result:read"
|
||||||
INDEX_SCOPE = "search:index:write"
|
INDEX_SCOPE = "search:index:write"
|
||||||
ADMIN_SCOPE = "search:index:admin"
|
ADMIN_SCOPE = "search:index:admin"
|
||||||
@@ -235,6 +236,56 @@ manifest = ModuleManifest(
|
|||||||
"search.data-subject-requests",
|
"search.data-subject-requests",
|
||||||
"search.admin.index",
|
"search.admin.index",
|
||||||
],
|
],
|
||||||
|
"consequence_classes": {
|
||||||
|
"purge_derived_index": (
|
||||||
|
"Deletes matching derived documents and queued changes idempotently."
|
||||||
|
),
|
||||||
|
"preserve_authoritative_source": (
|
||||||
|
"Does not correct or erase the authoritative object owned by its source module."
|
||||||
|
),
|
||||||
|
"review_acl_only_matches": (
|
||||||
|
"Requires source-authority review when only an ACL projection identifies the subject."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
translations={
|
||||||
|
"de": {
|
||||||
|
"title": "Datenschutzanfragen zum abgeleiteten Suchindex",
|
||||||
|
"summary": (
|
||||||
|
"Abgeleitete Indexkopien entfernen, ohne Search als führende Quelle "
|
||||||
|
"der indexierten Objekte zu behandeln."
|
||||||
|
),
|
||||||
|
"body": (
|
||||||
|
"Search gleicht innerhalb des exakten Mandanten nur ausdrückliche Index- "
|
||||||
|
"oder Änderungskennungen und quellanbietergeführte Referenzen ab. Selektoren "
|
||||||
|
"für Konten, Identitäten und Mitgliedschaften legen ausschließlich minimierte "
|
||||||
|
"Berechtigungsprojektionen offen und begründen niemals die Eigentümerschaft am "
|
||||||
|
"indexierten Quellobjekt. Indexierter Titel, Zusammenfassung, Inhalt, Suchtext, "
|
||||||
|
"URL, Schlüsselwörter, Metadaten, externe Referenzinhalte, Berechtigungswerte, "
|
||||||
|
"Prüfsummen, Cursor, eingereihte Dokumente und Fehler bleiben ausgeschlossen. "
|
||||||
|
"Abgeleitete Dokumente und eingereihte Änderungen können idempotent gelöscht "
|
||||||
|
"werden. Treffer allein über Berechtigungsprojektionen erfordern eine Prüfung "
|
||||||
|
"durch die führende Quelle. Berichtigung oder Löschung muss im Eigentümermodul "
|
||||||
|
"erfolgen, bevor Search neu aufgebaut wird; andernfalls darf die Quelle den "
|
||||||
|
"abgeleiteten Eintrag erneut veröffentlichen."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
structured_translation_version="1",
|
||||||
|
structured_translations={
|
||||||
|
"de": {
|
||||||
|
"consequence_classes": {
|
||||||
|
"purge_derived_index": (
|
||||||
|
"Löscht passende abgeleitete Dokumente und eingereihte Änderungen idempotent."
|
||||||
|
),
|
||||||
|
"preserve_authoritative_source": (
|
||||||
|
"Berichtigt oder löscht nicht das führende Objekt des jeweiligen Quellmoduls."
|
||||||
|
),
|
||||||
|
"review_acl_only_matches": (
|
||||||
|
"Erfordert eine Prüfung durch die führende Quelle, wenn die betroffene Person nur über eine Berechtigungsprojektion erkannt wird."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
links=(
|
links=(
|
||||||
DocumentationLink(
|
DocumentationLink(
|
||||||
@@ -270,14 +321,98 @@ manifest = ModuleManifest(
|
|||||||
documentation_types=("admin", "user"),
|
documentation_types=("admin", "user"),
|
||||||
audience=("administrator", "user"),
|
audience=("administrator", "user"),
|
||||||
related_modules=("connectors", "views"),
|
related_modules=("connectors", "views"),
|
||||||
|
conditions=(DocumentationCondition(required_scopes=(READ_SCOPE,)),),
|
||||||
metadata={
|
metadata={
|
||||||
"kind": "reference",
|
"kind": "workflow",
|
||||||
"help_contexts": [
|
"help_contexts": [
|
||||||
"search.global",
|
"search.global",
|
||||||
"search.results",
|
"search.results",
|
||||||
"search.filters",
|
"search.filters",
|
||||||
"search.admin.index",
|
"search.admin.index",
|
||||||
],
|
],
|
||||||
|
"purpose": (
|
||||||
|
"Find currently authorized native and connected objects without broadening source permissions."
|
||||||
|
),
|
||||||
|
"prerequisites": [
|
||||||
|
"The actor has Search read access and the source module authorizes each returned object now.",
|
||||||
|
"At least one enabled source provider has published or can supply a searchable projection.",
|
||||||
|
],
|
||||||
|
"steps": [
|
||||||
|
"Open Search from the title bar, F3, or Ctrl/Cmd+K and enter a precise term.",
|
||||||
|
"Narrow the result set by type, source, or context without changing source authorization.",
|
||||||
|
"Review partial-provider and quarantine diagnostics before relying on completeness.",
|
||||||
|
"Open an authorized result; Search rechecks the provider-owned object permission before disclosure.",
|
||||||
|
"Administrators may process queued changes, reconcile providers, or start a bounded rebuild when diagnostics require it.",
|
||||||
|
],
|
||||||
|
"limitations": [
|
||||||
|
"Search is a derived discovery layer and is never authoritative for source content or access decisions.",
|
||||||
|
"A provider failure can make results incomplete but never permits unsafe results to bypass ACL filtering.",
|
||||||
|
],
|
||||||
|
"operational_consequences": {
|
||||||
|
"process_queue": "Applies pending derived index changes under current tenant and provider boundaries.",
|
||||||
|
"reconcile": "Compares enabled source coverage and retains unresolved changes in quarantine.",
|
||||||
|
"rebuild": "Recreates bounded derived projections while source data remains authoritative.",
|
||||||
|
},
|
||||||
|
"verification": [
|
||||||
|
"Every displayed result names its source and remains openable by the current principal.",
|
||||||
|
"Partial-provider failures and quarantined changes remain visible as diagnostics.",
|
||||||
|
"Administrative rebuild status can be reconciled against the enabled provider inventory.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
translations={
|
||||||
|
"de": {
|
||||||
|
"title": "Globale und kontextbezogene Suche",
|
||||||
|
"summary": (
|
||||||
|
"Berechtigte native und angebundene Objekte über eine gemeinsame, "
|
||||||
|
"berechtigungsbewusste Oberfläche finden."
|
||||||
|
),
|
||||||
|
"body": (
|
||||||
|
"Search verwendet den eingebauten Datenbankindex und kann optionale Anbieter "
|
||||||
|
"zusammenführen. Quellmodule melden durchsuchbare Typen, Kontextbereiche und "
|
||||||
|
"berechtigungsgeprüfte Indexeinträge. Externe Suchmaschinen bleiben optionale "
|
||||||
|
"Adapter. Der Suchbefehl in der Titelleiste, F3 oder Strg/Cmd+K öffnet die per "
|
||||||
|
"Tastatur bedienbare Suchüberlagerung; Filter erweitern niemals die "
|
||||||
|
"Quellberechtigungen der aktuellen Person. Anbieterausfälle werden als partielle "
|
||||||
|
"Diagnosen angezeigt, ohne sichere Ergebnisse zu verwerfen. Administratoren "
|
||||||
|
"können die Abdeckung nativer Quellen prüfen, eingereihte Änderungen verarbeiten, "
|
||||||
|
"aktivierte Module abgleichen und begrenzte Neuaufbauten aus der Administration "
|
||||||
|
"starten. Änderungen in Quarantäne bleiben sichtbar, bis sie repariert und "
|
||||||
|
"abgeglichen wurden."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
structured_translation_version="1",
|
||||||
|
structured_translations={
|
||||||
|
"de": {
|
||||||
|
"purpose": (
|
||||||
|
"Aktuell berechtigte native und angebundene Objekte finden, ohne Quellberechtigungen zu erweitern."
|
||||||
|
),
|
||||||
|
"prerequisites": [
|
||||||
|
"Die handelnde Person darf Search lesen und das Quellmodul autorisiert jedes zurückgegebene Objekt weiterhin.",
|
||||||
|
"Mindestens ein aktivierter Quellanbieter hat eine durchsuchbare Projektion veröffentlicht oder kann sie bereitstellen.",
|
||||||
|
],
|
||||||
|
"steps": [
|
||||||
|
"Search über die Titelleiste, F3 oder Strg/Cmd+K öffnen und einen präzisen Suchbegriff eingeben.",
|
||||||
|
"Die Ergebnisse nach Typ, Quelle oder Kontext eingrenzen, ohne die Quellautorisierung zu verändern.",
|
||||||
|
"Diagnosen zu partiellen Anbieterausfällen und Quarantäne prüfen, bevor Vollständigkeit angenommen wird.",
|
||||||
|
"Ein berechtigtes Ergebnis öffnen; Search prüft vor der Offenlegung erneut die Berechtigung am quellengeführten Objekt.",
|
||||||
|
"Administratoren können bei entsprechenden Diagnosen eingereihte Änderungen verarbeiten, Anbieter abgleichen oder einen begrenzten Neuaufbau starten.",
|
||||||
|
],
|
||||||
|
"limitations": [
|
||||||
|
"Search ist eine abgeleitete Auffindbarkeitsschicht und niemals führend für Quellinhalte oder Zugriffsentscheidungen.",
|
||||||
|
"Ein Anbieterausfall kann Ergebnisse unvollständig machen, erlaubt aber niemals das Umgehen der Berechtigungsfilterung.",
|
||||||
|
],
|
||||||
|
"operational_consequences": {
|
||||||
|
"process_queue": "Verarbeitet ausstehende abgeleitete Indexänderungen innerhalb der aktuellen Mandanten- und Anbietergrenzen.",
|
||||||
|
"reconcile": "Vergleicht die Abdeckung aktivierter Quellen und hält ungeklärte Änderungen in Quarantäne.",
|
||||||
|
"rebuild": "Erstellt begrenzte abgeleitete Projektionen neu, während die Quelldaten führend bleiben.",
|
||||||
|
},
|
||||||
|
"verification": [
|
||||||
|
"Jedes angezeigte Ergebnis nennt seine Quelle und kann von der aktuellen Person weiterhin geöffnet werden.",
|
||||||
|
"Partielle Anbieterausfälle und Änderungen in Quarantäne bleiben als Diagnosen sichtbar.",
|
||||||
|
"Der administrative Neuaufbaustatus lässt sich mit dem Inventar aktivierter Anbieter abgleichen.",
|
||||||
|
],
|
||||||
|
}
|
||||||
},
|
},
|
||||||
links=(
|
links=(
|
||||||
DocumentationLink(
|
DocumentationLink(
|
||||||
@@ -295,10 +430,20 @@ manifest = ModuleManifest(
|
|||||||
maturity="vertical_slice",
|
maturity="vertical_slice",
|
||||||
documentation_ref="README.md",
|
documentation_ref="README.md",
|
||||||
test_ref="tests/test_postgres_search.py",
|
test_ref="tests/test_postgres_search.py",
|
||||||
known_limits=("The built-in PostgreSQL index is implemented; optional OpenSearch target evidence is not.",),
|
known_limits=(
|
||||||
|
"The built-in PostgreSQL index is implemented; optional OpenSearch target evidence is not.",
|
||||||
|
),
|
||||||
supported_authority_modes=("external_mirror",),
|
supported_authority_modes=("external_mirror",),
|
||||||
owned_concepts=("derived search index", "search ACL projection", "index change queue"),
|
owned_concepts=(
|
||||||
non_owned_concepts=("source object", "source authorization", "external search engine"),
|
"derived search index",
|
||||||
|
"search ACL projection",
|
||||||
|
"index change queue",
|
||||||
|
),
|
||||||
|
non_owned_concepts=(
|
||||||
|
"source object",
|
||||||
|
"source authorization",
|
||||||
|
"external search engine",
|
||||||
|
),
|
||||||
recovery_docs=("README.md",),
|
recovery_docs=("README.md",),
|
||||||
security_docs=("README.md",),
|
security_docs=("README.md",),
|
||||||
operations_docs=("README.md",),
|
operations_docs=("README.md",),
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from govoplan_core.core.modules import (
|
||||||
|
documentation_structured_translation_issues,
|
||||||
|
user_workflow_scope_condition_issues,
|
||||||
|
)
|
||||||
|
from govoplan_search.backend.manifest import manifest
|
||||||
|
|
||||||
|
|
||||||
|
class SearchDocumentationTests(unittest.TestCase):
|
||||||
|
def test_public_topics_have_complete_german_reference_content(self) -> None:
|
||||||
|
self.assertEqual(2, len(manifest.documentation))
|
||||||
|
for topic in manifest.documentation:
|
||||||
|
translation = topic.translations.get("de", {})
|
||||||
|
self.assertTrue(
|
||||||
|
all(translation.get(key) for key in ("title", "summary", "body"))
|
||||||
|
)
|
||||||
|
self.assertEqual((), documentation_structured_translation_issues(topic))
|
||||||
|
|
||||||
|
def test_documentation_has_scope_conditioned_workflow_and_reference(self) -> None:
|
||||||
|
kinds = {topic.metadata.get("kind") for topic in manifest.documentation}
|
||||||
|
self.assertIn("workflow", kinds)
|
||||||
|
self.assertIn("reference", kinds)
|
||||||
|
for topic in manifest.documentation:
|
||||||
|
self.assertEqual((), user_workflow_scope_condition_issues(topic))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/search-webui",
|
"name": "@govoplan/search-webui",
|
||||||
"version": "0.1.18",
|
"version": "0.1.19",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
Reference in New Issue
Block a user