Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Open Register drijft apps zoals OpenCatalogi, Procest, Pipelinq en Software Cata

Vrij en open source onder de EUPL-licentie.
]]></description>
<version>2.1.35-unstable.20261012153000</version>
<version>2.1.35-unstable.20261015190000</version>
<licence>EUPL-1.2</licence>
<author mail="info@conduction.nl" homepage="https://www.conduction.nl/">Conduction</author>
<namespace>OpenRegister</namespace>
Expand Down Expand Up @@ -404,6 +404,13 @@ Vrij en open source onder de EUPL-licentie.
1,664 tables, measured 2026-10-06). Last, after every step that
creates tasks. Idempotent. -->
<step>OCA\OpenRegister\Repair\BackfillTaskSubjectLocation</step>
<!-- Special rights are enforced (decision 239). Until then nobody's
agent_use or llm_use was read, so everybody could; the stored
lists say [] or ["admin"]. Writes "*" beside them, ONCE (an app
config flag), so nothing is refused until an administrator or
the owner narrows a list. Post-migration only: a fresh install's
organisations already default to "*". -->
<step>OCA\OpenRegister\Repair\OpenSpecialRightsToEveryone</step>
</post-migration>
<install>
<step>OCA\OpenRegister\Repair\ReconcileDeclaredBackgroundJobs</step>
Expand Down
75 changes: 48 additions & 27 deletions docs/Features/organisations.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ graph TB

### Authorization & RBAC (Role-Based Access Control)
- **Hierarchical Permissions**: Define CRUD permissions per entity type (register, schema, object, view, agent)
- **Special Rights**: Grant special permissions like object_publish, agent_use, dashboard_view, llm_use
- **Special Rights**: Grant special permissions: agent_use, llm_use and grant_manage
- **Group-Based**: Assign permissions to Nextcloud groups
- **Quick Authorization Checks**: Use singular entity names for efficient permission checking

Expand Down Expand Up @@ -301,9 +301,7 @@ The authorization field contains the complete RBAC configuration:
'update': ['admin'],
'delete': ['admin']
},
'object_publish': ['admin', 'publisher'],
'agent_use': ['admin', 'ai-user'],
'dashboard_view': ['admin', 'manager'],
'llm_use': ['admin', 'ai-user']
}
}
Expand Down Expand Up @@ -350,9 +348,7 @@ The authorization system uses **singular entity names** for easier permission ch
'update': ['admin', 'ai-specialist'],
'delete': ['admin']
},
'object_publish': ['admin', 'publisher'],
'agent_use': ['admin', 'ai-user', 'developer'],
'dashboard_view': ['admin', 'manager', 'viewer'],
'llm_use': ['admin', 'ai-user']
}
}
Expand All @@ -372,32 +368,59 @@ Each entity type has four standard CRUD permissions:

### Special Rights

Beyond CRUD operations, special rights grant additional capabilities:

| Right | Description | Common Groups |
|-------|-------------|---------------|
| **object_publish** | Publish objects to make them publicly available | 'publisher', 'editor', 'admin' |
| **agent_use** | Use AI agents for processing and analysis | 'ai-user', 'developer', 'admin' |
| **dashboard_view** | Access organisation dashboard and analytics | 'manager', 'admin', 'analyst' |
| **llm_use** | Use Large Language Model features | 'ai-user', 'researcher', 'admin' |
| **grant_manage** | List, add and remove the grants on records the holder does not own, and name their owning group. Enforced. An entry can be narrowed to a register and schemas. Only an administrator or the organisation's owner assigns it. | a service account's group |
Beyond CRUD operations, special rights grant additional capabilities. Each is a
list of Nextcloud group ids. `*` gives the right to every signed-in user (not
accepted under `grant_manage`). An administrator always holds every right. Only
an administrator or the organisation's owner may change who holds one: the API
answers anybody else with 403, and the editor's Special Rights tab is read-only
for them.

| Right | What it guards | Read from | Default |
|-------|----------------|-----------|---------|
| **agent_use** | Running an agent: a chat message in a conversation with an agent (`POST /api/chat/send`, `POST /api/chat/stream`), and an MCP session that declares an agent (`initialize`, `tools/list`, `tools/call`). Enforced. | The agent's organisation | `["*"]` |
| **llm_use** | Having a language model called on your behalf: every chat message (`POST /api/chat/send`, `POST /api/chat/stream`), including the title and summary calls it makes. Enforced. | The conversation's organisation | `["*"]` |
| **grant_manage** | List, add and remove the grants on records the holder does not own, and name their owning group. Enforced. An entry can be narrowed to a register and schemas. | The record's organisation | `[]` |

When the organisation an agent or conversation belongs to is not set, the
instance's default organisation is read. When there is no default organisation
either, nothing could have narrowed the right and it holds. A key the
organisation does not carry at all holds for everybody, except `grant_manage`.

**Upgrade.** Before this was enforced, every signed-in user could run agents and
use the language model, whatever the lists said (new organisations got `[]`,
most others `["admin"]`). On upgrade the repair step
`OpenSpecialRightsToEveryone` adds `*` to `agent_use` and `llm_use` in every
organisation, once, so nobody is refused. To narrow a right, take `*` out of
its list in the Special Rights tab. A narrowed right is not reopened by a
later upgrade.

**Retired rights.** `object_publish` and `dashboard_view` are retired. They
were stored and shown in the editor but never enforced: objects have no publish
action, and the dashboard API is administrator only. An organisation that still
has them in its authorization block loads as before; nothing reads them, and
new organisations, the editor and the upgrade no longer write them.

Semantic and hybrid search embed the query with an embedding model; that does
not need `llm_use`.

### Permission Check Example

A special right is read through `OrganisationSpecialRights`
(`lib/Service/Rbac/OrganisationSpecialRights.php`):

```php
// Quick authorization check using singular entity names
$canCreateRegister = $organisationService->hasPermission(
$organisation,
'register', // Entity type (singular)
'create', // Action
$userId
// May this user use something guarded by agent_use or llm_use?
$mayChat = $specialRights->mayUse(
right: OrganisationSpecialRights::LLM_USE,
userId: $userId,
organisationUuid: $conversation->getOrganisation()
);

// Check special right
$canPublish = $organisationService->hasSpecialRight(
$organisation,
'object_publish',
$userId
// Does this user hold grant_manage on this record?
$mayManageGrants = $specialRights->holdsOn(
right: OrganisationSpecialRights::GRANT_MANAGE,
userGroups: $userGroups,
object: $record
);
```

Expand Down Expand Up @@ -677,9 +700,7 @@ $organisation->setAuthorization([
'update' => ['lab-managers'],
'delete' => ['lab-managers'],
],
'object_publish' => ['lab-managers'],
'agent_use' => ['researchers', 'lab-managers'],
'dashboard_view' => ['lab-managers'],
'llm_use' => ['researchers', 'lab-managers'],
]);

Expand Down
8 changes: 4 additions & 4 deletions docs/features/organisation-roles.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ In addition to entity-type CRUD, organisations can define special action permiss

| Key | Controls |
|-----|---------|
| `object_publish` | Who can publish/depublish objects |
| `agent_use` | Who can execute agents |
| `dashboard_view` | Who can access the dashboard |
| `llm_use` | Who can use LLM features |
| `agent_use` | Who can run an agent, in a chat or as an MCP session (enforced; read from the agent's organisation) |
| `llm_use` | Who can have the language model called on their behalf in a chat (enforced; read from the conversation's organisation) |
| `grant_manage` | Who can manage the grants and the owning group of records they do not own (enforced; see `OrganisationSpecialRights`) |

`*` gives a right to every signed-in user (not under `grant_manage`); new organisations start with `*` under `agent_use` and `llm_use`. `object_publish` and `dashboard_view` are retired: they were never enforced, and a block that still holds them is read as before and ignored. Only an administrator or the organisation's owner may change special rights. See [Organisations](../Features/organisations.md#special-rights) for the upgrade behaviour.

### Nextcloud Groups on Organisations

Each organisation has a `groups` field — an array of Nextcloud group IDs associated with it:
Expand Down
2 changes: 1 addition & 1 deletion docs/l10n-ui-translation.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ harvested. The failures are not typos — they are correct translations of a
Recurring offenders, all confirmed in this app:

- **`Right`** — a permissions-table header (`EditOrganisation.vue`, the "Special
Rights" table listing `object_publish`). Sibling apps use the same English word
Rights" table listing `agent_use`). Sibling apps use the same English word
for text alignment, so the harvest yields "right-aligned" (`ru` "По правому
краю", `nl` "Rechts"). Needs the *legal/permission* sense: `Recht`, `Право`,
`Uprawnienie`, `Právo`.
Expand Down
2 changes: 1 addition & 1 deletion eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@
},
"src/modals/organisation/EditOrganisation.vue": {
"@nextcloud/l10n-enforce-ellipsis": {
"count": 8
"count": 6
},
"@nextcloud/no-deprecated-library-props": {
"count": 1
Expand Down
2 changes: 2 additions & 0 deletions l10n/be.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Усе",
"Only an administrator or the owner of this organisation can change its special rights.": "Толькі адміністратар або ўладальнік гэтай арганізацыі можа змяняць яе спецыяльныя правы.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Праграма, якая пастаўляе або валодае гэтай табліцай, напрыклад `dossiq`. Пуста для табліцы, створанай адміністратарам.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/bg.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Всички",
"Only an administrator or the owner of this organisation can change its special rights.": "Само администратор или собственикът на тази организация може да променя специалните ѝ права.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Приложението, което доставя или притежава тази таблица, например `dossiq`. Празно за таблица, създадена от администратор.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/bs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Svi",
"Only an administrator or the owner of this organisation can change its special rights.": "Samo administrator ili vlasnik ove organizacije može mijenjati njena posebna prava.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Aplikacija koja isporučuje ili posjeduje ovu tabelu, na primjer `dossiq`. Prazno za tabelu koju je napisao administrator.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/ca.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Tothom",
"Only an administrator or the owner of this organisation can change its special rights.": "Només un administrador o el propietari d'aquesta organització en pot canviar els drets especials.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Aplicació que subministra o posseeix aquesta taula, per exemple `dossiq`. Buit per a una taula creada per un administrador.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/cs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Všichni",
"Only an administrator or the owner of this organisation can change its special rights.": "Zvláštní práva této organizace může měnit pouze správce nebo její vlastník.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Aplikace, která tuto tabulku dodává nebo vlastní, například `dossiq`. Prázdné u tabulky, kterou vytvořil správce.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/da.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Alle",
"Only an administrator or the owner of this organisation can change its special rights.": "Kun en administrator eller ejeren af denne organisation kan ændre dens særlige rettigheder.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Appen, der leverer eller ejer denne tabel, for eksempel `dossiq`. Tom for en tabel, en administrator har oprettet.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/de.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Alle",
"Only an administrator or the owner of this organisation can change its special rights.": "Nur ein Administrator oder der Eigentümer dieser Organisation kann ihre Sonderrechte ändern.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "App, die diese Tabelle mitliefert oder besitzt, zum Beispiel `dossiq`. Leer bei einer Tabelle, die ein Administrator angelegt hat.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/el.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Όλοι",
"Only an administrator or the owner of this organisation can change its special rights.": "Μόνο ένας διαχειριστής ή ο κάτοχος αυτού του οργανισμού μπορεί να αλλάξει τα ειδικά δικαιώματά του.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Η εφαρμογή που παρέχει ή κατέχει αυτόν τον πίνακα, για παράδειγμα `dossiq`. Κενό για πίνακα που δημιούργησε διαχειριστής.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ OC.L10N.register(
"openregister",
{
"3": "3",
"Everyone": "Everyone",
"Only an administrator or the owner of this organisation can change its special rights.": "Only an administrator or the owner of this organisation can change its special rights.",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.",
"Connect a social or analytics account once. OpenRegister keeps the token and refreshes it, so apps never hold it.": "Connect a social or analytics account once. OpenRegister keeps the token and refreshes it, so apps never hold it.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/es.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Todos",
"Only an administrator or the owner of this organisation can change its special rights.": "Solo un administrador o el propietario de esta organización puede cambiar sus derechos especiales.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Aplicación que suministra o posee esta tabla, por ejemplo `dossiq`. Vacío para una tabla creada por un administrador.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/et.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Kõik",
"Only an administrator or the owner of this organisation can change its special rights.": "Selle organisatsiooni eriõigusi saab muuta ainult administraator või organisatsiooni omanik.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Rakendus, mis selle tabeli kaasa annab või omab, näiteks `dossiq`. Tühi, kui tabeli lõi administraator.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/fi.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Kaikki",
"Only an administrator or the owner of this organisation can change its special rights.": "Vain ylläpitäjä tai tämän organisaation omistaja voi muuttaa sen erityisoikeuksia.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Sovellus, joka toimittaa tai omistaa tämän taulukon, esimerkiksi `dossiq`. Tyhjä, jos ylläpitäjä on laatinut taulukon.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/fr.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Tout le monde",
"Only an administrator or the owner of this organisation can change its special rights.": "Seul un administrateur ou le propriétaire de cette organisation peut modifier ses droits spéciaux.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Application qui fournit ou possède cette table, par exemple `dossiq`. Vide pour une table créée par un administrateur.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/ga.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Gach duine",
"Only an administrator or the owner of this organisation can change its special rights.": "Ní féidir ach le riarthóir nó le húinéir na heagraíochta seo a cearta speisialta a athrú.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "An aip a sholáthraíonn nó a bhfuil úinéireacht aici ar an tábla seo, mar shampla `dossiq`. Folamh i gcás tábla a chruthaigh riarthóir.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/hr.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Svi",
"Only an administrator or the owner of this organisation can change its special rights.": "Samo administrator ili vlasnik ove organizacije može mijenjati njezina posebna prava.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Aplikacija koja isporučuje ili posjeduje ovu tablicu, na primjer `dossiq`. Prazno za tablicu koju je izradio administrator.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/hu.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Mindenki",
"Only an administrator or the owner of this organisation can change its special rights.": "Csak egy rendszergazda vagy a szervezet tulajdonosa módosíthatja a szervezet különleges jogait.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Az alkalmazás, amely ezt a táblázatot szállítja vagy birtokolja, például `dossiq`. Üres, ha a táblázatot egy rendszergazda hozta létre.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/is.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Allir",
"Only an administrator or the owner of this organisation can change its special rights.": "Aðeins stjórnandi eða eigandi þessarar stofnunar getur breytt sérréttindum hennar.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "Forritið sem útvegar eða á þessa töflu, til dæmis `dossiq`. Autt fyrir töflu sem stjórnandi bjó til.",
Expand Down
2 changes: 2 additions & 0 deletions l10n/it.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
OC.L10N.register(
"openregister",
{
"Everyone": "Tutti",
"Only an administrator or the owner of this organisation can change its special rights.": "Solo un amministratore o il proprietario di questa organizzazione può modificarne i diritti speciali.",
"3": "3",
"30": "30",
"App that ships or owns this table, for example `dossiq`. Empty for a table an administrator authored.": "App che fornisce o possiede questa tabella, per esempio `dossiq`. Vuoto per una tabella creata da un amministratore.",
Expand Down
Loading
Loading