What
gate-54 relation-dialect check (b) flags any property with format: uuid whose description matches _RELATION_DESC_RE (reference to|verwijzing naar|uuid of the|fk to) and has no $ref. Check (f) then requires a string $ref to resolve to a schema key in the same register file set.
Those two rules leave no expressible form for a cross-app foreign key — an identifier that genuinely points at an object owned by a different Nextcloud app, over that app's REST API.
The measured case
ConductionNL/openbuild, lib/Settings/register.d/40-automations.json, at gate package 651e5c5bb3ba8764903e5d6fc5bac5a208bd67fc:
lib/Settings/register.d/40-automations.json: Automation.actions.items.templateId —
relation-shaped property (format:uuid + relation description) lacks canonical $ref (ADR-062 rule 7)
The property:
"templateId": {
"title": "Document Template",
"type": "string",
"format": "uuid",
"description": "generateDocument: UUID of the Docudesk template to render, picked from the same `GET /apps/docudesk/api/templates` list the Documents-section builder UI uses."
}
It is a UUID. Its description is accurate. But the object it names is a Docudesk template, fetched over Docudesk's own REST surface. It is not an object in OpenBuild's register and never will be.
Why the repo cannot honestly clear it
There are exactly two ways to make it green, and both are worse than the finding:
- Write some
$ref anyway — it cannot resolve to a schema key in the register file set, so check (f) turns one finding into a dangling-reference finding. Strictly worse.
- Reword the description until the regex stops matching — the schema is byte-for-byte as unhelpful as before and only the prose moved. That is comment-satisfaction, which the truthfulness programme forbids.
openbuild fixed the other gate-54 finding properly in ConductionNL/openbuild#158 (Automation.versionUuid → "$ref": "ApplicationVersion", verified to resolve and verified not to become a dangling ref when only that file is in scope). This one has no honest edit available, so the gate stays red on a correct schema.
Suggested fix
Give the dialect a way to say "this UUID belongs to another app". Something explicit and greppable, e.g.:
"x-external-ref": { "app": "docudesk", "resource": "template" }
…which check (b) accepts in place of $ref, and which check (f) does not attempt to resolve locally. That keeps the gate's real purpose intact — an intra-register relation must still carry a resolvable $ref — while letting a cross-app identifier declare itself rather than hide.
Positive control for the fix
A regression test should assert the gate still reports 1 for a format: uuid + relation-description property with neither $ref nor the new key, and 0 once the new key is present — so the escape cannot become a silent blanket.
What
gate-54 relation-dialectcheck (b) flags any property withformat: uuidwhose description matches_RELATION_DESC_RE(reference to|verwijzing naar|uuid of the|fk to) and has no$ref. Check (f) then requires a string$refto resolve to a schema key in the same register file set.Those two rules leave no expressible form for a cross-app foreign key — an identifier that genuinely points at an object owned by a different Nextcloud app, over that app's REST API.
The measured case
ConductionNL/openbuild,lib/Settings/register.d/40-automations.json, at gate package651e5c5bb3ba8764903e5d6fc5bac5a208bd67fc:The property:
It is a UUID. Its description is accurate. But the object it names is a Docudesk template, fetched over Docudesk's own REST surface. It is not an object in OpenBuild's register and never will be.
Why the repo cannot honestly clear it
There are exactly two ways to make it green, and both are worse than the finding:
$refanyway — it cannot resolve to a schema key in the register file set, so check (f) turns one finding into a dangling-reference finding. Strictly worse.openbuild fixed the other gate-54 finding properly in ConductionNL/openbuild#158 (
Automation.versionUuid→"$ref": "ApplicationVersion", verified to resolve and verified not to become a dangling ref when only that file is in scope). This one has no honest edit available, so the gate stays red on a correct schema.Suggested fix
Give the dialect a way to say "this UUID belongs to another app". Something explicit and greppable, e.g.:
…which check (b) accepts in place of
$ref, and which check (f) does not attempt to resolve locally. That keeps the gate's real purpose intact — an intra-register relation must still carry a resolvable$ref— while letting a cross-app identifier declare itself rather than hide.Positive control for the fix
A regression test should assert the gate still reports 1 for a
format: uuid+ relation-description property with neither$refnor the new key, and 0 once the new key is present — so the escape cannot become a silent blanket.