ADR-277: A head editor sees the usage of the groups assigned to him
- Status
-
Accepted
- Date
-
2026-11-10
- Authors
-
Netresearch DTT GmbH
Context
Who used how much AI at what estimated cost is visible to administrators
only. The Analytics module (ADR-029) is `access =>
admin and sits in the administrator-ADR-231 <adr-231>) refuse a
non-ADR-232 <adr-232>`).
Organisations asked for a head editor (Hauptredakteur) who answers for the AI cost of his team. Today that person must be made an administrator, which opens every provider, configuration, credential reference and the usage of every user with it.
TYPO3 has no ranking of backend groups. The only relation between groups is the subgroup: a group that lists another as a subgroup includes that group's permissions. Budgets are per user; group budgets do not exist.
Decision
1. A grant and an explicit assignment
- A new capability grant
usage_(view_ groups Backend), a custom permission option on backend groups like the other grants of ADR-130. Administrators hold it implicitly.User Grant:: USAGE_ VIEW_ GROUPS - A new field on
be_, AI usage visible for groups (groups tx_), a comma list of backend groups shaped like core'snrllm_ usage_ visible_ groups subgroupfield. It names whose usage the holders in this group may see. - A holder's assignment is the union of that field over every group he
resolves to — his own groups and the subgroups they include, hidden
groups left out by core. That is how TYPO3 merges
custom_, so the grant and the assignment may sit on different groups. Reading the assignment only from the group that carries the grant was the alternative; it gives a second, different rule for one feature and buys nothing, becauseoptions be_isgroups admin: only an administrator can set or widen an assignment, never the holder.Only
Neither half works alone. The grant without an assignment shows nobody; an assignment without the grant is denied.
2. Membership is TYPO3's
A user is a member of an assigned group G when G is one of his groups or
one of his groups includes G as a subgroup, recursively. This is
Group (present in TYPO3 13.4 and 14.3)
with core's default restrictions, which the billing report's
Editor already uses.
The task asked whether members of subgroups of an assigned group
count. Under TYPO3's semantics they do not: a subgroup passes its
permissions up to the groups that include it, so a member of G inherits
G's subgroups, while a member of a subgroup is not a member of G. Core's
own permission checks agree: a user's resolved group list
(user, which the page-permission check reads) holds his groups
and their subgroups, never the groups that include them. The
direction that does count is the reverse one — members of groups that
include G — and that is the reading the operator meets everywhere else in
TYPO3, so the feature follows it rather than inventing a hierarchy.
Consequence for operators: assigning a group that many others include (a base group carrying shared permissions) shows the members of all of them. The documentation says so with an example.
Never in an audience: administrators and command-line users (_cli_*),
as in Editor; disabled, deleted and expired users
and hidden or deleted groups, by core's restrictions; and be_,
the usage nobody is attributed to.
3. A module of its own, reusing the analytics code
A new module AI usage of my groups (nrllm_) in
the AI section with access => user, controller
Group. Reaching it takes the module ticked in the
group's module list and the grant, which the controller checks itself
(the pattern of ADR-131).
Opening the Analytics module to holders was rejected. It sits in the administrator-only Operation container, which drops it from a holder's menu, and its page also renders fallback rescues and provider health and links the billing report and export; each would need its own guard, and a missed one leaks. The new controller instead assigns only what a holder may see — data that is never computed cannot leak — and reuses everything else:
Usagereturns the same service restricted to a list of backend users. Every reader (KPI totals, trend, the four breakdowns, the grouped totals, the per-user list) goes through one window-and-restriction helper. An empty list matches no row; the restriction is never optional on a restricted instance, and only an administrator gets the unrestricted service.Analytics Service Interface:: for Users () - The KPI tiles, charts and tables moved from the Analytics template into
shared partials; both pages render the same markup and the same
Analytics..js
The group view has no export, no billing report, no fallback rescues, no provider health and no AJAX endpoint. The Analytics index action now refuses a non-administrator itself, as its billing and export actions already did. Administrators keep the full Analytics module unchanged; an administrator who opens the group view sees every user.
4. Personal data is the operator's decision
The feature makes personal cost data of employees visible to a non-administrator. Whether that is permitted is a question for the operator's works council and data protection officer, not for the extension. The documentation (AI usage of assigned groups) says so before it explains the setup, and the feature is off until an administrator sets both the grant and an assignment.
Consequences
Backendgains a case; theUser Grant @apisnapshot changes additively.be_gains a column; existing groups have it empty, so nothing changes on update.groups UsagegainsAnalytics Service Interface for. The interface carries noUsers () @apimarker and is not in the API snapshot; an implementation outside the extension would have to add the method.- A holder sees no usage of a departed (disabled or deleted) editor; an administrator still does in the Analytics module.
- Group budgets remain out of scope.