Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29a9aea3b1 | ||
|
|
b5f431c766 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@govoplan/policy-webui",
|
||||
"version": "0.1.18",
|
||||
"version": "0.1.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "webui/src/index.ts",
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "govoplan-policy"
|
||||
version = "0.1.20"
|
||||
version = "0.1.22"
|
||||
description = "GovOPlaN policy platform module."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
"""German translations for public structured documentation metadata."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
GERMAN_STRUCTURED_TRANSLATIONS: dict[str, dict[str, Any]] = {'policy.data-subject-requests': {'consequence_classes': {'export_policy_attribution': 'Returns '
|
||||
'minimiert '
|
||||
'Politik '
|
||||
'Aktivität '
|
||||
'für das '
|
||||
'genaue '
|
||||
'Konto.',
|
||||
'retain_policy_evidence': 'Bewahrt die '
|
||||
'politische '
|
||||
'Governance-Rechenschaftspflicht.'}},
|
||||
'policy.function-assignment-delegation-escalation': {'fields': [{'consequence': 'Erlaubt nur dann '
|
||||
'geregelte '
|
||||
'abgeleitete '
|
||||
'Zuweisungen, '
|
||||
'wenn '
|
||||
'Organisationen '
|
||||
'auch die '
|
||||
'Funktion '
|
||||
'delegierbar '
|
||||
'markieren.',
|
||||
'key': 'delegation_allowed'},
|
||||
{'consequence': 'Lehnt längere '
|
||||
'aktuelle Ketten '
|
||||
'ab, '
|
||||
'einschließlich '
|
||||
'Ketten, die vor '
|
||||
'einem engeren '
|
||||
'Limit akzeptiert '
|
||||
'wurden.',
|
||||
'key': 'maximum_delegation_depth'},
|
||||
{'consequence': 'Caps jedes '
|
||||
'delegierte '
|
||||
'Gültigkeitsfenster '
|
||||
'zusätzlich zu '
|
||||
'seinem '
|
||||
'Quellfenster.',
|
||||
'key': 'maximum_delegated_validity_days'},
|
||||
{'consequence': 'Pins eine '
|
||||
'Zielfunktion und '
|
||||
'Frist ohne '
|
||||
'Erteilung oder '
|
||||
'Ersatz '
|
||||
'Genehmigung.',
|
||||
'key': 'escalation.<step>'}]},
|
||||
'policy.hierarchy-overrides-and-retention': {'outcome': 'Der ausgewählte Berechtigungsumfang hat '
|
||||
'eine erklärbare Aufbewahrungsrichtlinie '
|
||||
'und jeder destruktiven Anwendung wird '
|
||||
'eine Dry-Run-Überprüfung vorausgegangen.',
|
||||
'prerequisites': ['Policy und Access sind aktiviert.',
|
||||
'Die handelnde Person kann die '
|
||||
'Richtlinieneinstellungen am '
|
||||
'ausgewählten Bereich lesen.'],
|
||||
'steps': ['Überprüfen Sie den effektiven Wert und '
|
||||
'seinen Policy Source Path.',
|
||||
'Schmale nur Felder, die die übergeordnete '
|
||||
'Richtlinie diesen Bereich außer Kraft '
|
||||
'setzt.',
|
||||
'Speichern Sie die Richtlinie und führen '
|
||||
'Sie dann einen System-Dry-Run aus, bevor '
|
||||
'Sie die Retention anwenden.',
|
||||
'Überprüfen Sie das Bounded Outcome und '
|
||||
'prüfen Sie den Nachweis nach einem '
|
||||
'angewandten Durchlauf.'],
|
||||
'verification': 'Laden Sie die Richtlinie neu, '
|
||||
'bestätigen Sie ihren Quellpfad und '
|
||||
'vergleichen Sie die Trockenlauf- '
|
||||
'oder angewandte Ergebnistabelle mit '
|
||||
'den Prüfungsnachweisen.'},
|
||||
'policy.impact-preview': {'limitations': ['Nicht verfügbare optionale Anbieter werden erklärt und '
|
||||
'niemals als Null-Auswirkungen behandelt.',
|
||||
'Ressourcendetails werden ohne policy:impact:details '
|
||||
'ausgeblendet.'],
|
||||
'steps': ['Wählen Sie eine explizite Impact-Provider-Population und ein '
|
||||
'begrenztes Limit.',
|
||||
'Preview und Inspect Outcome Counts, Coverage State und '
|
||||
'Provenienz.',
|
||||
'Reauthentifizieren, wenn eine systemweite Änderung als hohe '
|
||||
'Auswirkungen eingestuft wird.',
|
||||
'Speichern Sie erst, nachdem die Vorschau mit dem aktuellen '
|
||||
'Dirty Draft übereinstimmt.']},
|
||||
'policy.retention-execution-and-recovery': {'limitations': ['Die Anwendung kann gelöschte EML- '
|
||||
'oder Mock-Mailbox-Inhalte nicht '
|
||||
'wiederherstellen.',
|
||||
'Ein Trockenlauf ist eine Vorschau '
|
||||
'und reserviert den gemeldeten Satz '
|
||||
'nicht gegen gleichzeitige '
|
||||
'Änderungen.'],
|
||||
'outcome': 'Förderfähige Details werden redigiert und '
|
||||
'förderfähige generierte Artefakte werden '
|
||||
'mit begrenztem Ergebnis und '
|
||||
'Prüfungsnachweis gelöscht.',
|
||||
'prerequisites': ['Die handelnde Person kann '
|
||||
'Systemeinstellungen schreiben.',
|
||||
'Die vorgesehene '
|
||||
'Systemaufbewahrungsrichtlinie wird '
|
||||
'gespeichert und neu geladen.',
|
||||
'Recovery Evidenz ist aktuell für '
|
||||
'generierte Artefakte.'],
|
||||
'steps': ['Führen Sie einen Trockenlauf durch und '
|
||||
'überprüfen Sie jede Datenklasse und '
|
||||
'Ergebniszahl.',
|
||||
'Stoppen Sie, wenn Anbieter ausfallen, die '
|
||||
'Wiederherstellung blockiert wird oder '
|
||||
'Zählungen unerwartet sind.',
|
||||
'Bestätigen Sie den destruktiven Lauf erst '
|
||||
'nach einer Überprüfung der Politik und der '
|
||||
'Wiederherstellung.',
|
||||
'Vergleichen Sie das angewandte Ergebnis '
|
||||
'mit den Prüfungsnachweisen.'],
|
||||
'verification': 'Überprüfen Sie das neueste Ergebnis, '
|
||||
'die Fehler- und '
|
||||
'Wiederherstellungszahlen des '
|
||||
'Anbieters und suchen Sie dann den '
|
||||
'Auditdatensatz retention '
|
||||
'policy.run.'}}
|
||||
@@ -1,5 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from govoplan_core.core.modules import with_documentation_structured_translations
|
||||
from govoplan_policy.backend.german_structured_documentation import GERMAN_STRUCTURED_TRANSLATIONS
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from govoplan_core.core.access import (
|
||||
@@ -150,7 +153,7 @@ POLICY_IMPACT_DETAILS_SCOPE = "policy:impact:details"
|
||||
manifest = ModuleManifest(
|
||||
id="policy",
|
||||
name="Policy",
|
||||
version="0.1.20",
|
||||
version="0.1.22",
|
||||
permissions=(
|
||||
PermissionDefinition(
|
||||
scope=ACCESS_EXPLANATION_SUBJECT_SCOPE,
|
||||
@@ -230,6 +233,25 @@ manifest = ModuleManifest(
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("policy_admin", "data_steward", "auditor"),
|
||||
related_modules=("datasources", "access", "audit"),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Richtlinienebenen für die Sichtbarkeit von Datenquellen",
|
||||
"summary": (
|
||||
"Die von Datasources verwaltete Sichtbarkeit für ACLs, Felder und Zeilen durch referenzierte hierarchische "
|
||||
"Richtlinien weiter einschränken."
|
||||
),
|
||||
"body": (
|
||||
"Datasources besitzt die Durchsetzung und eine lokale Sichtbarkeitsgrundlage. Policy kann für das globale Ziel und "
|
||||
"einen ausdrücklich referenzierten Richtlinienschlüssel zusätzliche Ebenen auf System-, Mandanten-, Gruppen- oder "
|
||||
"Benutzerebene liefern. Jede passende Ebene wirkt als weitere Einschränkung und kann keine Quelle, kein Feld und keine "
|
||||
"Zeile wiederherstellen, die eine andere Ebene entfernt hat. Eine nicht auflösbare Referenz, fehlerhafte Nutzdaten oder "
|
||||
"eine nicht verfügbare Entscheidung schließen den Zugriff sicher. Entscheidungsnachweise enthalten Richtlinienkennungen, "
|
||||
"Geltungsbereiche, Revisionen und einen stabilen Hash, aber niemals Zeilen- oder Feldwerte, Connector-Endpunkte oder "
|
||||
"Zugangsdaten. Ist Policy nicht installiert und keine externe Richtlinienreferenz konfiguriert, setzt Datasources seine "
|
||||
"lokalen Regeln für Umfang, ACL, Projektion, Schwärzung und Zeilenfilterung weiterhin durch."
|
||||
),
|
||||
}
|
||||
},
|
||||
order=28,
|
||||
),
|
||||
DocumentationTopic(
|
||||
@@ -253,6 +275,23 @@ manifest = ModuleManifest(
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("user", "policy_admin", "privacy_officer", "auditor"),
|
||||
related_modules=("core", "access", "audit"),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Betroffenenanfragen für Richtlinien",
|
||||
"summary": (
|
||||
"Zuordnung von Richtlinienänderungen exportieren, ohne Richtliniendokumente oder eingegrenzte "
|
||||
"Betroffenenkennungen offenzulegen."
|
||||
),
|
||||
"body": (
|
||||
"Policy gleicht innerhalb des aktiven Mandanten nur eine exakte Kontokennung ab und kann eine bereits verifizierte Suche "
|
||||
"auf eine einzelne Überschreibung begrenzen. Ausgegeben werden minimierte Erstellungs- und Änderungsaktivitäten mit "
|
||||
"Richtlinienfamilie, Bereichstyp, Revision und Zeitpunkten. Richtlinienwerte, Ziel- und Bereichsschlüssel, "
|
||||
"Bereichskennungen und Entscheidungsherkunft sind nicht enthalten. Systemweite Überschreibungen werden nicht in eine "
|
||||
"Mandantenanfrage projiziert. Die Zuordnung von Richtlinienänderungen bleibt Governance-Nachweis und wird aufbewahrt, "
|
||||
"statt automatisch gelöscht zu werden."
|
||||
),
|
||||
}
|
||||
},
|
||||
metadata={
|
||||
"help_contexts": ["privacy.data-subject-requests"],
|
||||
"consequence_classes": {
|
||||
@@ -280,6 +319,22 @@ manifest = ModuleManifest(
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("user", "tenant_admin", "policy_admin"),
|
||||
related_modules=("access", "audit", "campaign", "files"),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Zielpersonen für Zugriffsdiagnosen auswählen",
|
||||
"summary": (
|
||||
"Policy beschränkt Zugriffserklärungen auf die angemeldete Person, sofern die handelnde Person nicht die Berechtigung "
|
||||
"zur Diagnose für ausgewählte Benutzende besitzt."
|
||||
),
|
||||
"body": (
|
||||
"Files und Campaign verwenden die gemeinsame Auswahl für Zugriffserklärungen. Ohne "
|
||||
"policy:access_explanation:select_user liefert Access nur die angemeldete Person und legt keine Metadaten des "
|
||||
"Mandantenverzeichnisses offen. Erlaubte Erklärungen für andere Personen bleiben auf den aktiven Mandanten begrenzt und "
|
||||
"werden als administrative Diagnose im Auditnachweis festgehalten. Die Berechtigung erweitert nur die Sichtbarkeit der "
|
||||
"Diagnose; sie gewährt keinen Zugriff auf die erklärte Ressource."
|
||||
),
|
||||
}
|
||||
},
|
||||
metadata={
|
||||
"kind": "reference",
|
||||
"help_contexts": ["access.resource-explanation.subject"],
|
||||
@@ -296,6 +351,23 @@ manifest = ModuleManifest(
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("system_admin", "tenant_admin", "policy_admin"),
|
||||
related_modules=("views", "admin", "access"),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "View-Verfügbarkeit und -Aktionen steuern",
|
||||
"summary": (
|
||||
"View-Richtlinien begrenzen verfügbare Definitionen und Oberflächen sowie die View-Aktionen, die untergeordnete "
|
||||
"Ebenen ausführen dürfen."
|
||||
),
|
||||
"body": (
|
||||
"View-Richtlinien auf System-, Mandanten-, Gruppen- und Benutzerebene bilden eine einschränkende Hierarchie. Jede Ebene "
|
||||
"kann Anzeigen, Auswählen, Zuweisen, Bearbeiten, Ableiten und Workflow-Aktivierung erben, erlauben oder blockieren. "
|
||||
"Optionale Obergrenzen für View- und Oberflächenkennungen werden entlang der Hierarchie geschnitten, sodass eine "
|
||||
"untergeordnete Ebene einen darüber ausgeschlossenen Eintrag nicht wiederherstellen kann. Verfügbare, standardmäßige "
|
||||
"und verpflichtende View-Zuweisungen gehören weiterhin Views; Policy liefert die Aktions- und Katalogobergrenze und "
|
||||
"zeichnet Herkunft sowie Diagnosen fehlerhafter Richtlinien auf."
|
||||
),
|
||||
}
|
||||
},
|
||||
metadata={
|
||||
"kind": "reference",
|
||||
"help_contexts": [
|
||||
@@ -316,7 +388,31 @@ manifest = ModuleManifest(
|
||||
),
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("tenant_admin", "policy_admin", "access_admin", "user"),
|
||||
related_modules=("idm", "organizations", "workflow_engine", "notifications", "audit"),
|
||||
related_modules=(
|
||||
"idm",
|
||||
"organizations",
|
||||
"workflow_engine",
|
||||
"notifications",
|
||||
"audit",
|
||||
),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Funktionsdelegation und Prüfeskalation steuern",
|
||||
"summary": (
|
||||
"Policy begrenzt vollständige Delegationsketten und definiert ausdrückliche Zielfunktionen für überfällige "
|
||||
"Zuweisungsprüfungen."
|
||||
),
|
||||
"body": (
|
||||
"Mandantenstandards und Funktionseinstellungen können Delegation erlauben, Kettentiefe und Gültigkeit begrenzen und "
|
||||
"eine Prüfungsfrist für Inhaber, verantwortliche Stelle oder empfangende Person mit exakter Eskalations-Zielfunktion "
|
||||
"festlegen. IDM prüft die vollständige aktuelle Kette und die wirksame Policy bei Einreichung, jeder Entscheidung, "
|
||||
"Wiederherstellung und Anwendung erneut. Eine verschärfte Grenze verwirft einen älteren Weg mit Begründung. Eine "
|
||||
"Fristüberschreitung erzeugt einen sichtbaren eskalierten Zustand, ersetzt aber keine freigebende Person und schließt "
|
||||
"die Prüfung nicht ab; eine aktuelle Inhaberin oder ein aktueller Inhaber der Zielfunktion muss ausdrücklich entscheiden. "
|
||||
"Fehlerhafte oder unvollständige Eskalationsregeln schließen sicher."
|
||||
),
|
||||
}
|
||||
},
|
||||
metadata={
|
||||
"kind": "reference",
|
||||
"help_contexts": [
|
||||
@@ -324,10 +420,22 @@ manifest = ModuleManifest(
|
||||
"idm.field.escalation",
|
||||
],
|
||||
"fields": [
|
||||
{"key": "delegation_allowed", "consequence": "Allows governed derived assignments only when Organizations also marks the function delegable."},
|
||||
{"key": "maximum_delegation_depth", "consequence": "Rejects longer current chains, including chains accepted before a tighter limit."},
|
||||
{"key": "maximum_delegated_validity_days", "consequence": "Caps each delegated validity window in addition to its source window."},
|
||||
{"key": "escalation.<step>", "consequence": "Pins a target function and deadline without granting or substituting approval."},
|
||||
{
|
||||
"key": "delegation_allowed",
|
||||
"consequence": "Allows governed derived assignments only when Organizations also marks the function delegable.",
|
||||
},
|
||||
{
|
||||
"key": "maximum_delegation_depth",
|
||||
"consequence": "Rejects longer current chains, including chains accepted before a tighter limit.",
|
||||
},
|
||||
{
|
||||
"key": "maximum_delegated_validity_days",
|
||||
"consequence": "Caps each delegated validity window in addition to its source window.",
|
||||
},
|
||||
{
|
||||
"key": "escalation.<step>",
|
||||
"consequence": "Pins a target function and deadline without granting or substituting approval.",
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
@@ -338,6 +446,21 @@ manifest = ModuleManifest(
|
||||
body="A lower scope may narrow an inherited ceiling but cannot silently loosen a stronger system or tenant rule. Consuming modules remain responsible for enforcing the returned decision and displaying its reason. Malformed explicit policy fails closed for the affected governed action rather than being treated as absent.",
|
||||
documentation_types=("user",),
|
||||
audience=("user", "tenant_admin", "policy_admin"),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Wirksame Richtlinienentscheidungen verstehen",
|
||||
"summary": (
|
||||
"Richtlinienentscheidungen erläutern, ob eine Aktion erlaubt, begrenzt, geerbt oder nicht verfügbar ist, und nennen "
|
||||
"die Quellen des Ergebnisses."
|
||||
),
|
||||
"body": (
|
||||
"Eine untergeordnete Ebene darf eine geerbte Obergrenze verschärfen, aber eine stärkere System- oder Mandantenregel "
|
||||
"nicht stillschweigend lockern. Die nutzenden Module bleiben dafür verantwortlich, die gelieferte Entscheidung "
|
||||
"durchzusetzen und ihre Begründung anzuzeigen. Eine ausdrücklich konfigurierte fehlerhafte Richtlinie schließt die "
|
||||
"betroffene gesteuerte Aktion sicher, statt als nicht vorhanden zu gelten."
|
||||
),
|
||||
}
|
||||
},
|
||||
metadata={"kind": "reference"},
|
||||
),
|
||||
DocumentationTopic(
|
||||
@@ -365,6 +488,26 @@ manifest = ModuleManifest(
|
||||
documentation_types=("admin",),
|
||||
audience=("system_admin", "tenant_admin", "policy_admin"),
|
||||
related_modules=("admin", "audit", "views"),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Richtlinienauswirkung vor dem Speichern prüfen",
|
||||
"summary": (
|
||||
"Aktuelle und vorgeschlagene wirksame Richtlinie über ausdrücklich ausgewählte, begrenzte Provider-Populationen "
|
||||
"vergleichen, ohne den Vorschlag zu speichern."
|
||||
),
|
||||
"body": (
|
||||
"Die Policy-Auswirkungsvorschau gruppiert neu erlaubte, neu verweigerte, unveränderte und unbestimmte Wirkungen und "
|
||||
"hält Regel-, Quellen- und Bereichsherkunft fest. Aufrufende müssen eine bis zehn Provider-Populationen und je Population "
|
||||
"eine Grenze von höchstens 500 Subjekten wählen; Policy durchsucht die Plattform niemals implizit. Der "
|
||||
"Populationsnachweis kennzeichnet Ergebnisse als vollständig, stichprobenartig, abgeschnitten oder nicht verfügbar. "
|
||||
"Mit Leseberechtigung für Richtlinien sind aggregierte Anzahlen sichtbar, während policy:impact:details "
|
||||
"Ressourcenkennungen und -bezeichnungen steuert. Jede Vorschau wird mit Vorschlagshash und begrenzten Anzahlen auditiert. "
|
||||
"Systemweite View-Richtlinienänderungen verlangen eine Authentifizierung innerhalb der letzten 15 Minuten und behalten "
|
||||
"ihre vorhandenen Audit- und Konfigurationsfreigabenachweise. Optionale Module liefern Subjekte über den Core-Providervertrag; "
|
||||
"Policy importiert weder ihre Modelle noch ihre Dienste."
|
||||
),
|
||||
}
|
||||
},
|
||||
metadata={
|
||||
"kind": "workflow",
|
||||
"route": "/admin?section=system-view-policy",
|
||||
@@ -406,6 +549,23 @@ manifest = ModuleManifest(
|
||||
"campaign_manager",
|
||||
),
|
||||
related_modules=("campaign", "audit", "access"),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Verschlüsselung von Campaign-Archiven steuern",
|
||||
"summary": (
|
||||
"Formate passwortgeschützter Campaign-ZIP-Dateien und Übertragungskanäle für Passwörter über eine erklärbare "
|
||||
"Hierarchie einschränken."
|
||||
),
|
||||
"body": (
|
||||
"Die sichere Grundlage erlaubt nur AES. Eine berechtigte Richtlinienadministration kann das veraltete ZipCrypto auf "
|
||||
"Systemebene ausdrücklich zulassen; Regeln auf Mandanten-, Eigentümergruppen-, Benutzer- und Campaign-Ebene dürfen die "
|
||||
"geerbten Methoden anschließend nur weiter einschränken. Derselbe Schnitt steuert getrennt den Kanal zur Übermittlung "
|
||||
"eines Passworts. Policy zeichnet den vollständigen Quellenpfad und einen stabilen Richtlinienhash auf; fehlerhafte "
|
||||
"Konfiguration schließt sicher. Richtlinienänderungen schreiben alte Erstellungsnachweise niemals um, während Campaign "
|
||||
"einen eingereihten oder versandten Build zurückweist, wenn dessen wirksame Richtlinie inzwischen strenger ist."
|
||||
),
|
||||
}
|
||||
},
|
||||
metadata={
|
||||
"kind": "reference",
|
||||
"help_contexts": [
|
||||
@@ -720,5 +880,10 @@ manifest = ModuleManifest(
|
||||
)
|
||||
|
||||
|
||||
manifest = with_documentation_structured_translations(
|
||||
manifest, locale="de", translations=GERMAN_STRUCTURED_TRANSLATIONS
|
||||
)
|
||||
|
||||
|
||||
def get_manifest() -> ModuleManifest:
|
||||
return manifest
|
||||
|
||||
@@ -26,6 +26,18 @@ ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
class PolicyModuleContractTests(unittest.TestCase):
|
||||
def test_all_static_topics_have_complete_german_content(self) -> None:
|
||||
for topic in manifest.documentation:
|
||||
german = (topic.translations or {}).get("de", {})
|
||||
self.assertEqual(
|
||||
{"title", "summary", "body"},
|
||||
set(german),
|
||||
topic.id,
|
||||
)
|
||||
self.assertTrue(
|
||||
all(str(value).strip() for value in german.values()), topic.id
|
||||
)
|
||||
|
||||
def test_policy_package_does_not_hard_require_access(self) -> None:
|
||||
project = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))[
|
||||
"project"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@govoplan/policy-webui",
|
||||
"version": "0.1.20",
|
||||
"version": "0.1.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
|
||||
Reference in New Issue
Block a user