Skip to content

gate-54 rule (f) makes an ADR-066 cross-app relation unrepresentable — a sanctioned relation cannot be declared without failing the gate #305

Description

@rubenvdlinde

Summary

gate-54 rule (f) $REF TARGETS requires that a string $ref "resolve to a schema key in the same register file set (case-exact)".

ADR-066 explicitly sanctions cross-app relations — a property on one app's schema that references an object owned by another app. By construction, that target is not in the referencing app's register file set. So rule (f) and ADR-066 contradict each other: a correctly-declared cross-app relation is a permanent gate-54 failure, and there is no dialect to express it.

Rule (b) RELATION SHAPE closes the other exit: a format: uuid property with a relation-shaped description and no $ref is also a finding. So for a cross-app relation the author can fail (f) by naming the foreign schema, or fail (b) by not naming it.

Measured on pipelinq (12 findings, 6 of them this shape)

Property Foreign owner Rule hit
lead.decisions$ref: 'Decision' decidesk (ADR-066; decidesk owns making + eIDAS signing) (f)
ticket.decisions$ref: 'Decision' decidesk (f)
ticket.contract$ref: 'Contract' Shillinq (owns contract lifecycle) (f)
ticket.caseReference Procest (the case it converted into) (b)
receiptTemplate.organizationId organisation, an OpenRegister concept (b)
posZReport.store the store plane — ADR-080 D2/D3 says store discovery is OpenRegister's (b)

Each description already names the owner explicitly, e.g.

"References decidesk Decision objects (ADR-066 cross-app relation); Decidesk owns the making and eIDAS signing."

So the intent is documented in-tree; there is simply no machine-readable way to say it.

Why "just drop the $ref" is the wrong fix

Deleting $ref: 'Decision' would silence rule (f) on ticket.contract/lead.decisions (they are not all format: uuid, so (b) would not always fire) — but it destroys the only structured statement of what the property points at, to satisfy a checker. That is the same trade as deleting an inconvenient @spec, and I have not done it in pipelinq#743.

⚠️ There is also a live trap for anyone tempted to "fix" it locally: pipelinq does have a local contract schema, so $ref: 'Contract'$ref: 'contract' makes gate-54 green in one character. It would also silently repoint a Shillinq relation at a different, local object. A case-insensitive-looking near-miss is exactly where this gate can be satisfied by making the data model wrong.

Suggested fix

A first-class cross-app form, so the relation stays declared and machine-readable, e.g.

{ "type": "string", "format": "uuid",
  "$ref": "decidesk:decision" }

or a sibling key (x-openregister-external-ref) carrying { "app": "decidesk", "schema": "decision" }, with rule (f) resolving app:schema against the declared app dependency set rather than the local register, and rule (b) accepting its presence as "has a canonical ref".

Until then rule (f) cannot be satisfied by any correct cross-app schema, which makes gate-54 unclosable for every app that has one — i.e. every app ADR-066 applies to.

What was fixed locally

pipelinq#743 fixes the 6 findings with genuine local targets (5 ticket relations gained $ref, and task.requestId was repointed from the retired request schema to its ticket successor) and leaves these 6 red with this reason.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions