feat(docs): grant handbook access to authenticated users
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ 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.
|
||||||
|
|
||||||
## 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"
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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,7 +13,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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",
|
||||||
|
|||||||
@@ -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