Skip to content

[OpenSpec] 2026-06-15-softwarecatalog-contracts-to-decidesk #669

Description

@github-actions

⚠️ OpenSpec-managed issue — this content is automatically synced
from the openspec/ directory. Manual edits will be overwritten on next sync.

Artifacts

Summary

softwarecatalog owns a contract schema and a top-level Contracts nav
group (manifest pages Contracten index + ContractDetail detail). The
contract schema carries a status enum Actief / Verlopen / In onderhandeling
("Active / Expired / In negotiation"). The transition In onderhandeling
Actief
is an approval / sign-off decision: a human or governance body
deciding the contract terms are agreed and the contract may take effect. The
same is true for a renewal (re-approving an expiring contract).

Per cross-app interface contract #1, decidesk is the canonical decision
authority
and its hub is merged: a consuming app raises a Decision via the
ADR-019 integration registry (POST /api/v1/decisions with
decisionType: contract / contract-renewal + provenance fields) and
consumes the outcome (GET /api/v1/decisions/{id}/outcome, or a
push subscription), keeping its own domain record as a projection of that
outcome. softwarecatalog must NOT own a parallel approval/sign-off surface.

This change draws the boundary precisely:

  • Stays in softwarecatalog (contract RECORD / catalog metadata): the
    contract schema and its fields (dienst, gebruik, startDatum,
    eindDatum, contractNummer, contractType, kosten, kostenPeriode,
    contactpersoonAanbieder/Gebruiker, documentReferentie, opmerkingen),
    the Contracten index + ContractDetail pages, and the catalog need to
    know which contract governs which software/gebruik/dienst. The catalog
    must federate and export contracts with the rest of the GEMMA/VNG data model.
  • Delegated to decidesk (contract APPROVAL / sign-off / renewal DECISION):
    the act of approving an In onderhandeling contract into Actief, and the
    act of approving a renewal of an expiring contract. softwarecatalog raises a
    decidesk Decision and projects the outcome back onto the contract record;
    it never flips status to Actief on its own authority.

The status field becomes a projection of the decidesk outcome for the
approval transitions, plus the date-driven Actief → Verlopen expiry
transition (which is NOT a decision and stays catalog-local).

Specs

Tasks

  • 0.1 Confirm decidesk decision hub is reachable on the target instance:
  • 0.2 Confirm softwarecatalog has NO existing contract-approval capability
  • 0.3 Confirm this change does NOT contradict the in-flight
  • 0.4 Confirm the integration call goes through the ADR-019 integration
  • 1.1 In lib/Settings/register.d/*.json add to the contract schema:
  • 1.2 Document in the schema that approvalState is a PROJECTION of the
  • 2.1 Add a thin integration call (ADR-019 registry, resolve the decidesk
  • 2.2 Add a "Submit renewal" path that POSTs the same shape with
  • 2.3 On success, persist the returned decision id to
  • 2.4 Fail CLOSED: if no decidesk endpoint resolves or the call errors,
  • 2.5 Subscribe to the outcome via
  • 3.1 Add the SC outcome callback endpoint that receives the decidesk push,
  • 3.2 Add a daily reconcile job that polls
  • 3.3 Ensure the projection is idempotent (re-receiving the same outcome is
  • 4.1 Add a read-only Approval panel to the ContractDetail page
  • 4.2 Add a manual "refresh outcome" action that polls the outcome on demand.
  • 4.3 Do NOT move, rename, or unroute the Contracten nav entry, the
  • 4.4 NL + EN strings (English i18n keys) for all new labels.
  • 5.1 lib/Repair/* idempotent, fail-safe step backfills
  • 5.2 Tests: raise-decision call shape + provenance fields; fail-closed when
  • 5.3 cd softwarecatalog && openspec validate softwarecatalog-contracts-to-decidesk --strict passes.

Design

See design.md for technical design details.


Synced from openspec/changes/archive/2026-06-15-softwarecatalog-contracts-to-decidesk by OpenSpec workflow
App: stackiq

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions