Sync Repo-docs-SERVICE-DIRECTORY-CONCEPT from project files

2026-08-01 16:32:12 +02:00
parent b18ff1872b
commit 138c4c5f81
+27 -2
@@ -1,4 +1,4 @@
<!-- codex-wiki-sync:9875c2f0390afdffbaa765bc -->
<!-- codex-wiki-sync:e1694967845967ef7d99c03e -->
> Mirrored from `/mnt/DATA/git/govoplan-portal/docs/SERVICE_DIRECTORY_CONCEPT.md`.
> Origin: `repository`.
@@ -81,7 +81,7 @@ missing role, disabled module, tenant policy, missing connector, maintenance
mode, or unavailable external provider. It should hide only services that are
irrelevant or intentionally undiscoverable by policy.
## Implemented Headless Slice
## Implemented Slice
`portal.service_directory` consumes the optional `services.definitions`
capability. It returns only tenant-scoped definitions and distinguishes
@@ -106,3 +106,28 @@ capability requirements are checked against the active registry, and audience
requirements against the supplied actor projection. Unknown requirements fail
closed. Each requirement declares whether failure remains visible with an
explanation or makes the entry undiscoverable.
`GET /api/v1/portal/services` and the `/portal` WebUI expose this projection.
The API derives audience tokens from the authenticated principal instead of
accepting caller-provided audience claims. Generic `public` and `authenticated`
tokens are combined with stable account, identity, group, role, active function,
and organization-unit tokens. Function slugs are included only after the
optional Access semantic directory confirms an active, effective, same-tenant
assignment. Missing or failing directory providers narrow the result.
The WebUI provides bounded search, availability filtering, explanations, and
one launch action. `POST /api/v1/portal/services/{service_id}/launch` resolves
the entry again at launch time so a stale browser projection cannot bypass a
new audience, publication, effective-time, module, or capability restriction.
Direct URL entries return only validated local or credential-free HTTP(S)
redirects.
Case, form, and workflow bindings delegate to owner capabilities. Their launch result
must retain the exact Service reference, tenant, binding kind, target reference,
and replay-safe idempotency key. Portal never writes their tables. Missing
launchers produce `service.launcher.missing:<kind>` and make the entry visibly
unavailable. Forms Runtime now provides a definition-aware launcher when Forms
and Forms Runtime are active. It resolves an exact published
`<form-id>/<revision>`, validates launch values, and retains Service/binding
provenance. Reduced installations still fail closed rather than simulating a
submission in Portal.