Skip to content

gate-54: no vocabulary for a forward reference to a schema owned by an unlanded change in the SAME register #311

Description

@rubenvdlinde

Summary

.github#286 gave gate-54 x-external-register for a reference to another app's register. The same unclosable shape exists within one app, for a reference whose target schema is owned by a change that has not landed yet, and x-external-register cannot express it honestly — the owner is the same app.

Measured on ConductionNL/decidesk at gate package 365fa31, NODE_PATH set (require.resolve('ajv').../node_modules/ajv/dist/ajv.js), 0-byte .err. All 7 of decidesk's gate-54 findings are this family. None is cross-app.

The three sub-shapes

(a) A $ref to a schema an unlanded change owns — 4 findings.

lib/Settings/register.d/49-vragenuur-interpellatie.json:

property $ref gate says
MondelingeVraag.fractie Fractie does not resolve (case-exact)
Interpellatieverzoek.fractie Fractie does not resolve
MondelingeVraag.vervolgSchriftelijkeVraag SchriftelijkeVraag does not resolve
MondelingeVraag.bronSchriftelijkeVraag SchriftelijkeVraag does not resolve

Neither key exists in the 81-schema register set. The properties say why, in their own descriptions:

"Reference to the submitter's Fractie (fractievoorzitter-fractie-koppeling — hard depends_on, that change owns the schema). Required. Seeded as a nil-UUID placeholder until that change lands (design D6)."

(b) A deliberately soft reference to an unlanded sibling capability — 2 findings.

  • 47-works-council-consultation.json: ConsultationRequest.achterbanraadpleging"Modelled as a plain uuid reference (not a hard $ref) so the traject degrades gracefully when the sibling capability is not installed… Never a $ref to keep the cross-capability dependency soft (constituency-consultation lands in any order)."
  • 51-raadsinformatiebrieven.json: Raadsinformatiebrief.relatedDossier"targets the ArchivalDossier planned in records-management-archiving. Nullable — until that change lands it degrades to a plain link."

These are already written the way the gate's $ref rule would push them, and are flagged anyway by check (b) "lacks canonical $ref".

(c) A polymorphic target — 1 finding.

61-appointments-and-terms.json: Voordracht.voordragendePartij.referentie"optionally points at a resolved Person or GovernanceBody". A single $ref cannot name two schemas, and composition keywords are rejected by OpenRegister registers.

Why it is unclosable

Exactly the #286 pincer, one level in:

  • With the $ref → check (f) "does not resolve to a schema key in the register set (case-exact)".
  • Without the $ref → check (b) "relation-shaped property … lacks canonical $ref (ADR-062 rule 7)".

x-external-register: decidesk would be false — the reference is not external, and _is_external_ref's docstring is explicit that the notion means "a schema owned by a different app". Using it here would be exactly the "reword until the regex stops matching" move #286 was written to stop.

The remaining route to green is to delete the documentation that makes _RELATION_DESC_RE match ("Reference to…"), which degrades the register to satisfy a checker.

Suggested fix

A narrow companion to x-external-register, suppressing the same two $ref rules and nothing else — e.g. x-pending-register: <change-name> for (a)/(b), naming the change that will own the schema so the marker is auditable and removable when that change lands. For (c), either an array form ($ref: [Person, GovernanceBody]) or a x-polymorphic-ref marker.

I have left all 7 red in decidesk rather than pick any of the dishonest routes.

Related: #286 (cross-app), #273 (gate-40 unclosable family).

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