Provide first system administrator authority

This commit is contained in:
2026-08-04 10:07:20 +02:00
parent e710cf5fb8
commit 668f7cf108
3 changed files with 263 additions and 2 deletions
+42
View File
@@ -9,6 +9,7 @@ from govoplan_core.core.access import (
CAPABILITY_ACCESS_ADMINISTRATION,
CAPABILITY_ACCESS_DIRECTORY,
CAPABILITY_ACCESS_EXPLANATION,
CAPABILITY_ACCESS_FIRST_ADMIN_PROVISIONER,
CAPABILITY_ACCESS_GOVERNANCE_MATERIALIZER,
CAPABILITY_ACCESS_PERMISSION_EVALUATOR,
CAPABILITY_ACCESS_PRINCIPAL_RESOLVER,
@@ -269,6 +270,39 @@ ADMIN_READ_SCOPES = (
)
ACCESS_DOCUMENTATION: tuple[DocumentationTopic, ...] = (
DocumentationTopic(
id="access.operator.enroll-first-administrator",
title="Enroll the first production administrator",
summary="A local operator can issue one expiring credential while no durable system administrator exists, then use it once to create the protected system owner and an initial tenant membership.",
body=(
"Run the Core first-admin issue command after migrations and after Access is installed. The command stores the random secret in a local mode-0600 artifact and prints only its path, fingerprint, and expiry. "
"The public bootstrap status endpoint exposes only minimum readiness. The enrollment endpoint accepts only the first account and initial tenant fields, creates one protected system owner plus one tenant-owner membership atomically, and retires the credential. "
"Identical retries return the completed account without creating another owner. Lost or expired material can be rotated only by the local recovery command and only while the durable-administrator check remains empty. Development bootstrap settings are a separate dev-only path and are never enabled by enrollment."
),
layer="always",
documentation_types=("admin",),
audience=("operator", "system_admin"),
order=10,
links=(
DocumentationLink(label="Bootstrap readiness API", href="/api/v1/bootstrap/status", kind="api"),
DocumentationLink(label="First-administrator enrollment API", href="/api/v1/bootstrap/first-admin", kind="api"),
),
metadata={
"kind": "operator_workflow",
"commands": [
"python -m govoplan_core.commands.first_admin status",
"python -m govoplan_core.commands.first_admin issue --reason 'initial production installation'",
"python -m govoplan_core.commands.first_admin recover --reason 'lost or expired handoff'",
],
"security_properties": [
"random expiring credential",
"mode-0600 local artifact",
"single-use idempotent enrollment",
"empty-install authority gate",
"hash-chained and audit evidence",
],
},
),
DocumentationTopic(
id="access.workflow.grant-user-access",
title="Grant a person access",
@@ -670,6 +704,13 @@ def _tenant_provisioner(context: ModuleContext) -> object:
return LegacyTenantAccessProvisioner()
def _first_admin_provisioner(context: ModuleContext) -> object:
del context
from govoplan_access.backend.tenancy.provisioning import LegacyFirstAdminProvisioner
return LegacyFirstAdminProvisioner()
def _access_administration(context: ModuleContext) -> object:
del context
from govoplan_access.backend.administration import SqlAccessAdministration
@@ -801,6 +842,7 @@ manifest = ModuleManifest(
CAPABILITY_ACCESS_SEMANTIC_DIRECTORY: _access_semantic_directory,
CAPABILITY_ACCESS_EXPLANATION: _access_explanation_service,
CAPABILITY_ACCESS_TENANT_PROVISIONER: _tenant_provisioner,
CAPABILITY_ACCESS_FIRST_ADMIN_PROVISIONER: _first_admin_provisioner,
CAPABILITY_ACCESS_ADMINISTRATION: _access_administration,
CAPABILITY_ACCESS_GOVERNANCE_MATERIALIZER: _governance_materializer,
CAPABILITY_ACCESS_PEOPLE_SEARCH: _people_search,