Files
computer-playbook/docs/requirements/027-integration-matrix.md
T
kevinveenbirkenbachandClaude Opus 5 bed4b3c84f refactor(docs): derive the role integration pages instead of freezing them
cli/build/docs/integration_matrix was 1189 lines a human ran through
'make integration-matrix', and its output sat frozen as a 125-line grid in
requirement 027. Its ENTITIES and EDGES lists were hand-maintained, so the
grid could only drift: it covered 84 entities while the tree holds 98 roles,
named two roles that no longer exist, and omitted sixteen current ones -
api, checkmk, docs, hermes, homeassistant, jellyfin, meta, mirror, openbao,
openclaw, penpot, pihole, s1, seaweedfs, seaweedfs-console and semaphore.

infinito_docs/generators/integrations.py replaces it and joins the nine
sibling generators in that package, so the overview, services and addons
pages are written into generated/integrations/ on every docs build rather
than when someone remembers the target. index.rst takes the overview and the
new docs/architecture/integrations.rst references the other two.
Requirement 027 becomes prose. The make target and its i8inma alias are
removed as a pair, which keeps the alias lints satisfied.

Coverage is not strictly larger. The removed EDGES list carried a curated
upstream project URL per integration, 96 of them, and the new edges have no
such field; only 48 of 159 addon declarations hold update.upstream_id or
config.repository, so about a third is re-derivable and the rest existed only
in that list. Its fourth field is no real loss - 57 entries read 'check', so
it was a near-constant rather than an axis. In exchange the old module had
zero tests, not one file under tests/ referenced it, and the generator ships
310 lines including generate().

Residuals: the HTML build runs without -W, but i18n.py:57 runs the gettext
builder with -W and check=True, and that build has never seen
integrations.rst - no catalog mentions generated/integrations. And
docs/requirements/036:72 still carries a checked criterion asserting a table
in 027 that no longer exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-02 18:22:04 +02:00

3.6 KiB
Raw Blame History

027 - Integration Matrix

Companion to 026-unified-addon-syntax.md: how a cross-role integration is declared, where its truth lives, and which ones are still open.

This page replaces the generated role×role grid that used to live here. The grid listed every pair of web-app-* and web-svc-* entity names, which grows with the square of the role count, and it was only refreshed when somebody ran its generator by hand. Nothing compared it against the repository, so it drifted silently: at the point of removal its hardcoded axes were missing fourteen roles, carried one role that no longer existed, and therefore dropped 84 of the 574 integration edges the repository actually declares.

Where the truth lives

An integration has exactly two possible homes, and both are machine-readable.

A service flag in the row role's meta/services.yml. The infinito-native integrations are plain service keys — sso (keycloak), matomo, prometheus, email (mailu), dashboard, css, logout, cdn, coturn, collabora, onlyoffice, libretranslate and litellm. Each is group-gated, so the flag tells you both that the integration exists and when it is active. lookup('roles_with_service', '<key>') answers "who consumes this" from the repository itself; no second list needs to agree with it.

An addon under the row role's meta/addons/. Everything that needs an upstream plugin lives there, with its mechanism and, for an in-repo partner, a bridges: entry resolving to the service key it wires. The addon contract and its lints are requirement 026.

A pair that appears in neither place has no integration. That is the whole state space, and it is queryable — which is why a frozen copy of it was worth less than the query.

Layers

Layer Meaning Where it is declared
Wired Active through an infinito-native service flag meta/services.yml of the row role
Declared Upstream plugin wired as an addon meta/addons/ of the row role
Open A verified upstream plugin exists, nothing declares it nowhere yet — this is the backlog
Paid Integration exists only behind a commercial tier nowhere; opt-in by the operator
None No known integration between the two roles nowhere

Integrations are directional: the row role hosts the flag or the plugin. A bidirectional pair such as nextcloud ↔ openproject is two declarations, one on each side.

Two classes need no declaration and are therefore never "open". Native ActivityPub federation between the fediverse roles (mastodon, peertube, pixelfed, funkwhale, mobilizon, bookwyrm, socialhome) works without a plugin. And ldap, redis and mariadb resolve to svc-db-* roles, which are infrastructure rather than integration partners.

Open work

The wired and declared layers are exhaustive by construction — they are read from the repository. The open layer is not: it grows as each role's upstream plugin ecosystem is surveyed. A MediaWiki survey, for example, surfaced DiscourseSsoConsumer, PeerTubeEmbed, MachineTranslation (libretranslate), Extension:AWS (minio) and an LLM editor (openwebui) — five integrations that no list had carried before someone looked.

Acceptance Criteria

  • Every web-app-* role has had its upstream plugin ecosystem surveyed once, and each integration found is either declared under meta/addons/ or recorded as deliberately skipped with a reason.
  • A reader can answer "does role A integrate role B" from the repository alone, without consulting a generated page.