Skip to content

The contract expiry warning never fires, and a contract can be set to Active without approval #1077

Description

@rubenvdlinde

What goes wrong

The contract-expiry warning can never fire, because it filters on a status value no contract can have. Separately, the rule that a contract only becomes Active after an approved decision is not enforced: anyone who can edit a contract can set it to Active in the form.

Evidence, re-read at c9760e0

Expiry warning, lib/Settings/softwarecatalogus_register.json:3252-3265 (catalogContract, x-openregister-notifications.contract-expiry):

  • The scheduled trigger filters "status": {"operator": "equals", "value": "Actief"} together with endDate withinNext P90D (:3255).
  • The status property allows only Active, Expired, In negotiation (:3428-3434). No contract can hold Actief, so the filter matches nothing.
  • The subject uses {{contractNummer}} and {{eindDatum}} (:3262-3263). The schema's fields are contractNumber and endDate; there is no contractNummer or eindDatum property, so even a matching contract would get a subject with empty placeholders.
  • The Contracts page quick filter "Expiring / expired" (src/manifest.json:527 page) is the only other expiry surface the matrix cites, and it filters on Expired only, so no page lists contracts that are about to expire.

Approval not enforced:

  • status (:3428) has no readOnly or hideOnForm, so it is editable in the generic create and edit form of the Contracts page (src/manifest.json:527).
  • approvalState comes from the overlay lib/Settings/register.d/contracts-to-decidesk.json:14 (merged by SettingsService.php:1653-1658). It is not readOnly either, although its own description says it is a projection of the decidiq outcome and that stackiq never sets Active on its own authority.
  • The only code path that sets Active is lib/Service/ContractApprovalService.php:432-437, on an approved outcome.
  • The declared x-openregister-lifecycle on the same schema (:3531-3560) uses In onderhandeling, Actief and Verlopen, which match none of the enum values, so it offers no transition either.

Why it matters

Admins get no warning before a contract lapses, and the contract approval workflow can be skipped by typing a status into a form, which undermines the audit value of the decidiq approval.

Needs a live check

Code reading. Whether OpenRegister dispatches scheduled notifications at all is outside this repo; the filter mismatch holds regardless.

Surfaced by the capability matrix in stackiq#1072 (merge 38b9938), rows ctr-expiry-alert and ctr-approval.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

triageAwaiting triage

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions