Compare commits
4 Commits
901baf8352
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 511930ea56 | |||
| 4d36ab2747 | |||
| 94c000f351 | |||
| be52b716ca |
@@ -22,6 +22,14 @@ This repository owns:
|
|||||||
|
|
||||||
Core owns module discovery, configuration package loading, route registry, RBAC evaluation, capability registry, and shared WebUI shell behavior.
|
Core owns module discovery, configuration package loading, route registry, RBAC evaluation, capability registry, and shared WebUI shell behavior.
|
||||||
|
|
||||||
|
While Docs is installed, its managed `docs_reader` tenant role is an automatic
|
||||||
|
authenticated-member baseline. Access derives its narrow read grant from the
|
||||||
|
active Docs manifest without per-user assignments or authorization-time writes,
|
||||||
|
so ordinary users can open their configured handbook without an administrator
|
||||||
|
assigning documentation access one account at a time.
|
||||||
|
Administrative documentation remains separately protected by
|
||||||
|
`docs:documentation:admin` or the applicable administration scope.
|
||||||
|
|
||||||
## Documentation model
|
## Documentation model
|
||||||
|
|
||||||
The docs module should render documentation in three layers:
|
The docs module should render documentation in three layers:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ It should not start from a full product manual. The current tenant, installed
|
|||||||
modules, enabled routes, permissions, and configuration decide what is shown as
|
modules, enabled routes, permissions, and configuration decide what is shown as
|
||||||
the default path.
|
the default path.
|
||||||
|
|
||||||
Tracking issue: `add-ideas/govoplan-docs#15`.
|
Tracking issue: `GovOPlaN/govoplan-docs#15`.
|
||||||
|
|
||||||
## Editorial Pillars
|
## Editorial Pillars
|
||||||
|
|
||||||
@@ -255,6 +255,9 @@ Workflow topics:
|
|||||||
- keep each step actionable
|
- keep each step actionable
|
||||||
- mention blockers where the user would encounter them
|
- mention blockers where the user would encounter them
|
||||||
- link to field/reference topics instead of repeating field tables
|
- link to field/reference topics instead of repeating field tables
|
||||||
|
- for every user-facing workflow, declare one or more conditions and put
|
||||||
|
`required_scopes` or `any_scopes` on every condition alternative; the release
|
||||||
|
gate rejects an unscoped alternative
|
||||||
|
|
||||||
Reference topics:
|
Reference topics:
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,20 @@ documentation may show all layers plus route, permission, module, and capability
|
|||||||
diagnostics, but it requires the separate administrative documentation
|
diagnostics, but it requires the separate administrative documentation
|
||||||
authority.
|
authority.
|
||||||
|
|
||||||
|
The managed `docs_reader` role grants `docs:documentation:read` automatically
|
||||||
|
to every authenticated tenant membership while Docs is installed. This only
|
||||||
|
opens the user projection: each contributed workflow still needs its own
|
||||||
|
module, capability, permission, and runtime-policy conditions so baseline Help
|
||||||
|
Center access does not imply authority to perform every documented task.
|
||||||
|
|
||||||
|
This permission binding is a strict source contract. Every user workflow topic
|
||||||
|
must declare at least one `DocumentationCondition`, and every alternative in
|
||||||
|
its `conditions` tuple must include `required_scopes` or `any_scopes`. Module,
|
||||||
|
capability, or configuration conditions alone are not sufficient because topic
|
||||||
|
conditions are alternatives: one unscoped alternative would bypass all scoped
|
||||||
|
ones. Manifest validation blocks a release containing such a topic, and Docs
|
||||||
|
omits a non-compliant runtime-provider topic from the user projection.
|
||||||
|
|
||||||
## Conditions
|
## Conditions
|
||||||
|
|
||||||
Documentation topics can declare:
|
Documentation topics can declare:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/docs-webui",
|
"name": "@govoplan/docs-webui",
|
||||||
"version": "0.1.9",
|
"version": "0.1.10",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "webui/src/index.ts",
|
"main": "webui/src/index.ts",
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"README.md"
|
"README.md"
|
||||||
],
|
],
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.8",
|
"@govoplan/core-webui": "^0.1.10",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "govoplan-docs"
|
name = "govoplan-docs"
|
||||||
version = "0.1.9"
|
version = "0.1.10"
|
||||||
description = "GovOPlaN documentation module for configured-system, available, and evidence documentation."
|
description = "GovOPlaN documentation module for configured-system, available, and evidence documentation."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
authors = [{ name = "GovOPlaN" }]
|
authors = [{ name = "GovOPlaN" }]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"govoplan-core>=0.1.8",
|
"govoplan-core>=0.1.10",
|
||||||
"govoplan-access>=0.1.8",
|
"govoplan-access>=0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
__all__ = ["__version__"]
|
__all__ = ["__version__"]
|
||||||
|
|
||||||
__version__ = "0.1.9"
|
__version__ = "0.1.10"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from govoplan_core.core.modules import (
|
|||||||
ModuleManifest,
|
ModuleManifest,
|
||||||
NavItem,
|
NavItem,
|
||||||
PermissionDefinition,
|
PermissionDefinition,
|
||||||
|
user_workflow_scope_condition_issues,
|
||||||
)
|
)
|
||||||
from govoplan_core.core.registry import PlatformRegistry
|
from govoplan_core.core.registry import PlatformRegistry
|
||||||
from govoplan_core.db.session import get_database
|
from govoplan_core.db.session import get_database
|
||||||
@@ -46,78 +47,168 @@ def docs_context(
|
|||||||
visible_route_items = [item for item in route_items if item["visible"]]
|
visible_route_items = [item for item in route_items if item["visible"]]
|
||||||
documentation_layers = _documentation_layers(request, registry, principal, documentation_type=documentation_type, locale=resolved_locale)
|
documentation_layers = _documentation_layers(request, registry, principal, documentation_type=documentation_type, locale=resolved_locale)
|
||||||
if documentation_type == "admin":
|
if documentation_type == "admin":
|
||||||
visible_routes = visible_route_items
|
catalog = _admin_documentation_catalog(
|
||||||
modules = [_module_payload(manifest, technical=True) for manifest in registry.manifests()]
|
registry,
|
||||||
permissions = [_permission_payload(permission, principal) for permission in registry.permissions()]
|
principal,
|
||||||
available_routes = [item for item in route_items if not item["visible"]]
|
route_items=route_items,
|
||||||
optional_modules = _optional_module_evidence(registry.manifests())
|
visible_route_items=visible_route_items,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
|
catalog = _user_documentation_catalog(
|
||||||
|
registry,
|
||||||
|
visible_route_items=visible_route_items,
|
||||||
|
documentation_layers=documentation_layers,
|
||||||
|
)
|
||||||
|
topic_groups = _documentation_topic_groups(documentation_layers)
|
||||||
|
return {
|
||||||
|
"actor": _documentation_actor(
|
||||||
|
principal,
|
||||||
|
documentation_type=documentation_type,
|
||||||
|
locale=resolved_locale,
|
||||||
|
can_read_admin=can_read_admin_documentation,
|
||||||
|
),
|
||||||
|
"summary": _documentation_summary(
|
||||||
|
catalog,
|
||||||
|
documentation_layers=documentation_layers,
|
||||||
|
topic_groups=topic_groups,
|
||||||
|
),
|
||||||
|
"topic_groups": topic_groups,
|
||||||
|
"layers": _documentation_layer_payload(
|
||||||
|
catalog,
|
||||||
|
documentation_layers=documentation_layers,
|
||||||
|
include_evidence_sources=documentation_type == "admin",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _admin_documentation_catalog(
|
||||||
|
registry: PlatformRegistry,
|
||||||
|
principal: ApiPrincipal,
|
||||||
|
*,
|
||||||
|
route_items: list[dict[str, Any]],
|
||||||
|
visible_route_items: list[dict[str, Any]],
|
||||||
|
) -> dict[str, list[dict[str, Any]]]:
|
||||||
|
return {
|
||||||
|
"modules": [
|
||||||
|
_module_payload(manifest, technical=True)
|
||||||
|
for manifest in registry.manifests()
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
_permission_payload(permission, principal)
|
||||||
|
for permission in registry.permissions()
|
||||||
|
],
|
||||||
|
"visible_routes": visible_route_items,
|
||||||
|
"available_routes": [item for item in route_items if not item["visible"]],
|
||||||
|
"optional_modules": _optional_module_evidence(registry.manifests()),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _user_documentation_catalog(
|
||||||
|
registry: PlatformRegistry,
|
||||||
|
*,
|
||||||
|
visible_route_items: list[dict[str, Any]],
|
||||||
|
documentation_layers: Mapping[str, list[dict[str, Any]]],
|
||||||
|
) -> dict[str, list[dict[str, Any]]]:
|
||||||
visible_module_ids = {
|
visible_module_ids = {
|
||||||
*(str(item["module_id"]) for item in visible_route_items),
|
*(str(item["module_id"]) for item in visible_route_items),
|
||||||
*(str(topic["source_module_id"]) for topic in _all_documentation_topics(documentation_layers)),
|
*(
|
||||||
|
str(topic["source_module_id"])
|
||||||
|
for topic in _all_documentation_topics(documentation_layers)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
modules = [
|
return {
|
||||||
|
"modules": [
|
||||||
_module_payload(manifest, technical=False)
|
_module_payload(manifest, technical=False)
|
||||||
for manifest in registry.manifests()
|
for manifest in registry.manifests()
|
||||||
if manifest.id in visible_module_ids
|
if manifest.id in visible_module_ids
|
||||||
]
|
],
|
||||||
permissions = []
|
"permissions": [],
|
||||||
visible_routes = _user_route_payloads(visible_route_items)
|
"visible_routes": _user_route_payloads(visible_route_items),
|
||||||
available_routes = []
|
"available_routes": [],
|
||||||
optional_modules = []
|
"optional_modules": [],
|
||||||
documentation_count = sum(len(layer) for layer in documentation_layers.values())
|
}
|
||||||
topic_groups = _documentation_topic_groups(documentation_layers)
|
|
||||||
|
|
||||||
actor_payload: dict[str, Any] = {
|
|
||||||
|
def _documentation_actor(
|
||||||
|
principal: ApiPrincipal,
|
||||||
|
*,
|
||||||
|
documentation_type: DocumentationType,
|
||||||
|
locale: str,
|
||||||
|
can_read_admin: bool,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
actor: dict[str, Any] = {
|
||||||
"documentation_type": documentation_type,
|
"documentation_type": documentation_type,
|
||||||
"locale": resolved_locale,
|
"locale": locale,
|
||||||
"available_documentation_types": ["user", *(["admin"] if can_read_admin_documentation else [])],
|
"available_documentation_types": [
|
||||||
|
"user",
|
||||||
|
*(["admin"] if can_read_admin else []),
|
||||||
|
],
|
||||||
}
|
}
|
||||||
if documentation_type == "admin":
|
if documentation_type == "admin":
|
||||||
actor_payload.update(
|
actor.update(
|
||||||
tenant_id=principal.tenant_id,
|
tenant_id=principal.tenant_id,
|
||||||
user_id=principal.user.id,
|
user_id=principal.user.id,
|
||||||
scope_count=len(principal.scopes),
|
scope_count=len(principal.scopes),
|
||||||
)
|
)
|
||||||
|
return actor
|
||||||
|
|
||||||
|
|
||||||
|
def _documentation_summary(
|
||||||
|
catalog: Mapping[str, list[dict[str, Any]]],
|
||||||
|
*,
|
||||||
|
documentation_layers: Mapping[str, list[dict[str, Any]]],
|
||||||
|
topic_groups: Mapping[str, list[dict[str, Any]]],
|
||||||
|
) -> dict[str, int]:
|
||||||
|
permissions = catalog["permissions"]
|
||||||
return {
|
return {
|
||||||
"actor": actor_payload,
|
"module_count": len(catalog["modules"]),
|
||||||
"summary": {
|
"visible_route_count": len(catalog["visible_routes"]),
|
||||||
"module_count": len(modules),
|
"available_route_count": len(catalog["available_routes"]),
|
||||||
"visible_route_count": len(visible_routes),
|
|
||||||
"available_route_count": len(available_routes),
|
|
||||||
"permission_count": len(permissions),
|
"permission_count": len(permissions),
|
||||||
"granted_permission_count": sum(1 for item in permissions if item["granted"]),
|
"granted_permission_count": sum(
|
||||||
"optional_module_count": len(optional_modules),
|
1 for item in permissions if item["granted"]
|
||||||
"documentation_topic_count": documentation_count,
|
),
|
||||||
"configured_documentation_topic_count": len(documentation_layers["configured"]),
|
"optional_module_count": len(catalog["optional_modules"]),
|
||||||
|
"documentation_topic_count": sum(
|
||||||
|
len(layer) for layer in documentation_layers.values()
|
||||||
|
),
|
||||||
|
"configured_documentation_topic_count": len(
|
||||||
|
documentation_layers["configured"]
|
||||||
|
),
|
||||||
"workflow_topic_count": len(topic_groups["workflow"]),
|
"workflow_topic_count": len(topic_groups["workflow"]),
|
||||||
"reference_topic_count": len(topic_groups["reference"]),
|
"reference_topic_count": len(topic_groups["reference"]),
|
||||||
"pattern_topic_count": len(topic_groups["pattern"]),
|
"pattern_topic_count": len(topic_groups["pattern"]),
|
||||||
"system_topic_count": len(topic_groups["system"]),
|
"system_topic_count": len(topic_groups["system"]),
|
||||||
},
|
}
|
||||||
"topic_groups": topic_groups,
|
|
||||||
"layers": {
|
|
||||||
|
def _documentation_layer_payload(
|
||||||
|
catalog: Mapping[str, list[dict[str, Any]]],
|
||||||
|
*,
|
||||||
|
documentation_layers: Mapping[str, list[dict[str, Any]]],
|
||||||
|
include_evidence_sources: bool,
|
||||||
|
) -> dict[str, dict[str, object]]:
|
||||||
|
permissions = catalog["permissions"]
|
||||||
|
return {
|
||||||
"always": {
|
"always": {
|
||||||
"documentation": documentation_layers["always"],
|
"documentation": documentation_layers["always"],
|
||||||
},
|
},
|
||||||
"configured": {
|
"configured": {
|
||||||
"modules": modules,
|
"modules": catalog["modules"],
|
||||||
"routes": visible_routes,
|
"routes": catalog["visible_routes"],
|
||||||
"permissions": permissions,
|
"permissions": permissions,
|
||||||
"documentation": documentation_layers["configured"],
|
"documentation": documentation_layers["configured"],
|
||||||
},
|
},
|
||||||
"available": {
|
"available": {
|
||||||
"routes": available_routes,
|
"routes": catalog["available_routes"],
|
||||||
"permissions": [item for item in permissions if not item["granted"]],
|
"permissions": [item for item in permissions if not item["granted"]],
|
||||||
"documentation": documentation_layers["available"],
|
"documentation": documentation_layers["available"],
|
||||||
},
|
},
|
||||||
"evidence": {
|
"evidence": {
|
||||||
"optional_modules": optional_modules,
|
"optional_modules": catalog["optional_modules"],
|
||||||
"sources": _evidence_sources() if documentation_type == "admin" else [],
|
"sources": _evidence_sources() if include_evidence_sources else [],
|
||||||
"documentation": documentation_layers["evidence"],
|
"documentation": documentation_layers["evidence"],
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -362,6 +453,7 @@ def _collect_documentation_topics(
|
|||||||
topics: list[tuple[str, DocumentationTopic]] = []
|
topics: list[tuple[str, DocumentationTopic]] = []
|
||||||
for manifest in registry.manifests():
|
for manifest in registry.manifests():
|
||||||
for topic in manifest.documentation:
|
for topic in manifest.documentation:
|
||||||
|
if not user_workflow_scope_condition_issues(topic):
|
||||||
topics.append((manifest.id, topic))
|
topics.append((manifest.id, topic))
|
||||||
if not manifest.documentation_providers:
|
if not manifest.documentation_providers:
|
||||||
continue
|
continue
|
||||||
@@ -393,6 +485,7 @@ def _collect_documentation_topics(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
for topic in provided_topics:
|
for topic in provided_topics:
|
||||||
|
if not user_workflow_scope_condition_issues(topic):
|
||||||
topics.append((manifest.id, topic))
|
topics.append((manifest.id, topic))
|
||||||
return topics
|
return topics
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ def _route_factory(context: ModuleContext):
|
|||||||
manifest = ModuleManifest(
|
manifest = ModuleManifest(
|
||||||
id="docs",
|
id="docs",
|
||||||
name="Docs",
|
name="Docs",
|
||||||
version="0.1.9",
|
version="0.1.10",
|
||||||
required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR),
|
required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR),
|
||||||
optional_dependencies=("policy", "audit", "ops", "workflow", "search"),
|
optional_dependencies=("policy", "audit", "ops", "workflow", "search"),
|
||||||
permissions=(
|
permissions=(
|
||||||
@@ -63,8 +63,9 @@ manifest = ModuleManifest(
|
|||||||
RoleTemplate(
|
RoleTemplate(
|
||||||
slug="docs_reader",
|
slug="docs_reader",
|
||||||
name="Documentation reader",
|
name="Documentation reader",
|
||||||
description="Read the configured-system documentation browser.",
|
description="Read the configured-system documentation browser. This role is granted automatically to every authenticated tenant member while Docs is installed.",
|
||||||
permissions=(DOCS_READ_SCOPE,),
|
permissions=(DOCS_READ_SCOPE,),
|
||||||
|
default_authenticated=True,
|
||||||
),
|
),
|
||||||
RoleTemplate(
|
RoleTemplate(
|
||||||
slug="docs_admin",
|
slug="docs_admin",
|
||||||
|
|||||||
@@ -33,6 +33,18 @@ class FakePrincipal:
|
|||||||
|
|
||||||
|
|
||||||
class DocsContextTests(unittest.TestCase):
|
class DocsContextTests(unittest.TestCase):
|
||||||
|
def test_docs_reader_is_the_managed_authenticated_tenant_default(self) -> None:
|
||||||
|
manifest = get_docs_manifest()
|
||||||
|
roles = {template.slug: template for template in manifest.role_templates}
|
||||||
|
|
||||||
|
self.assertTrue(roles["docs_reader"].default_authenticated)
|
||||||
|
self.assertTrue(roles["docs_reader"].managed)
|
||||||
|
self.assertEqual(roles["docs_reader"].level, "tenant")
|
||||||
|
self.assertEqual(
|
||||||
|
roles["docs_reader"].permissions,
|
||||||
|
("docs:documentation:read",),
|
||||||
|
)
|
||||||
|
|
||||||
def test_topic_groups_preserve_layer_classification(self) -> None:
|
def test_topic_groups_preserve_layer_classification(self) -> None:
|
||||||
registry = PlatformRegistry()
|
registry = PlatformRegistry()
|
||||||
registry.register(get_tenancy_manifest())
|
registry.register(get_tenancy_manifest())
|
||||||
@@ -86,6 +98,55 @@ class DocsContextTests(unittest.TestCase):
|
|||||||
self.assertNotIn("access.workflow.grant-user-access", workflow_ids)
|
self.assertNotIn("access.workflow.grant-user-access", workflow_ids)
|
||||||
self.assertNotIn("access.workflow.grant-user-access", {topic["id"] for topic in layers["available"]})
|
self.assertNotIn("access.workflow.grant-user-access", {topic["id"] for topic in layers["available"]})
|
||||||
|
|
||||||
|
def test_user_projection_fails_closed_for_unscoped_workflow_topics(self) -> None:
|
||||||
|
unscoped_static_topic = DocumentationTopic(
|
||||||
|
id="example.workflow.unscoped-static",
|
||||||
|
title="Unscoped static task",
|
||||||
|
summary="This topic must not be rendered.",
|
||||||
|
documentation_types=("user",),
|
||||||
|
metadata={"kind": "workflow"},
|
||||||
|
)
|
||||||
|
unscoped_runtime_topic = DocumentationTopic(
|
||||||
|
id="example.workflow.unscoped-runtime",
|
||||||
|
title="Unscoped runtime task",
|
||||||
|
summary="This provider topic must not be rendered.",
|
||||||
|
documentation_types=("user",),
|
||||||
|
conditions=(DocumentationCondition(required_modules=("example",)),),
|
||||||
|
metadata={"kind": "workflow"},
|
||||||
|
)
|
||||||
|
scoped_runtime_topic = DocumentationTopic(
|
||||||
|
id="example.workflow.scoped-runtime",
|
||||||
|
title="Scoped runtime task",
|
||||||
|
summary="This provider topic remains visible.",
|
||||||
|
documentation_types=("user",),
|
||||||
|
conditions=(DocumentationCondition(required_scopes=("docs:documentation:read",)),),
|
||||||
|
metadata={"kind": "workflow"},
|
||||||
|
)
|
||||||
|
registry = PlatformRegistry()
|
||||||
|
registry.register(ModuleManifest(
|
||||||
|
id="example",
|
||||||
|
name="Example",
|
||||||
|
version="9.9.9",
|
||||||
|
documentation=(unscoped_static_topic,),
|
||||||
|
documentation_providers=(
|
||||||
|
lambda context: (unscoped_runtime_topic, scoped_runtime_topic),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
|
||||||
|
layers = _classify_documentation(
|
||||||
|
registry,
|
||||||
|
FakePrincipal({"docs:documentation:read"}),
|
||||||
|
settings=None,
|
||||||
|
session=None,
|
||||||
|
documentation_type="user",
|
||||||
|
locale="en",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[topic["id"] for topic in _documentation_topic_groups(layers)["workflow"]],
|
||||||
|
["example.workflow.scoped-runtime"],
|
||||||
|
)
|
||||||
|
|
||||||
def test_user_projection_is_a_bounded_safe_whitelist(self) -> None:
|
def test_user_projection_is_a_bounded_safe_whitelist(self) -> None:
|
||||||
registry = PlatformRegistry()
|
registry = PlatformRegistry()
|
||||||
registry.register(ModuleManifest(
|
registry.register(ModuleManifest(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/docs-webui",
|
"name": "@govoplan/docs-webui",
|
||||||
"version": "0.1.9",
|
"version": "0.1.10",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
@@ -13,11 +13,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.8",
|
"@govoplan/core-webui": "^0.1.10",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router-dom": "^7.1.1",
|
"react-router-dom": ">=7.18.2 <8",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.7.2",
|
||||||
"vite": "^6.0.6"
|
"vite": "^6.0.6"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const translations = {
|
|||||||
export const docsModule: PlatformWebModule = {
|
export const docsModule: PlatformWebModule = {
|
||||||
id: "docs",
|
id: "docs",
|
||||||
label: "i18n:govoplan-docs.docs.68a41942",
|
label: "i18n:govoplan-docs.docs.68a41942",
|
||||||
version: "0.1.9",
|
version: "0.1.10",
|
||||||
dependencies: ["access"],
|
dependencies: ["access"],
|
||||||
optionalDependencies: ["policy", "audit", "ops", "workflow", "search"],
|
optionalDependencies: ["policy", "audit", "ops", "workflow", "search"],
|
||||||
translations,
|
translations,
|
||||||
|
|||||||
Reference in New Issue
Block a user