elsa-core/doc/adr/2026-08-25-date-prefixed-adr-identifiers.md
Sipke Schoorstra f6d2d38536
test(user-tasks): add a persistence conformance suite with fault injection (#7986)
Runs one suite unchanged against every implementation of IUserTaskRepository,
IUserTaskGuestSessionIssuer, and IUserTaskInvitationOutbox, plus a fault-injection
suite driving the real DefaultUserTaskManager and DefaultUserTaskInvitationService
against a real store. Gated providers report as skipped with a reason rather than
passing vacuously; ConformanceCoverageTests fails when a provider that must run is
unreachable or its variable is set but empty.

The suite found three defects, fixed here:

- VNextUserTaskRepository supplied no index values for WorkflowDefinitionId,
  WorkflowInstanceId, ActivityInstanceId, CreatedAt, or CompletedAt, all declared by
  its own schema provider, so every write through the VNext provider threw.
- The same provider resolved invitation token hashes by scanning on Status alone,
  which matched no declared index, so anonymous invitation verification always threw.
- EFCoreUserTaskInvitationOutbox persisted the delivery recipient but never read it
  back, so durably queued invitations reached the dispatcher with no address.

Also switches new ADRs to date-prefixed identifiers and generates doc/adr/toc.md via
scripts/adr/generate-toc.sh, with a --check mode and pull-request workflow so the
index is never hand-edited again.
2026-08-25 04:36:18 +02:00

2.3 KiB

Identify new ADRs by date instead of a sequential number

Date: 2026-08-25

Status

Accepted

Context

doc/adr/ numbered records sequentially with no reservation step, so every branch that wrote an ADR guessed the same next number as every other branch in flight. The User Tasks records were renumbered twice across two consecutive merges from main0011/0012 to 0014/0015, then to 0026/0027 — as the output-converter and external-authentication records landed ahead of them. Each renumber meant renaming files, editing the # NN. heading inside each one, rebuilding toc.md by hand, and re-checking for stale links. None of that work said anything about the decisions themselves.

The index made it worse. Because toc.md was retyped by hand on every collision, it drifted from the documents it indexed: the titles recorded for records 11 through 27 no longer matched their own headings.

Renaming all 27 existing records to a new scheme would remove the mixed convention, but it would also break every existing link and conflict with any ADR branch currently open — paying the merge-friction cost one more time to stop paying it.

Decision

New ADRs are named YYYY-MM-DD-slug.md and their heading carries the title alone, with no numeric prefix. Records 0001 through 0027 keep their existing names, headings, and links; they are not renumbered.

doc/adr/toc.md is generated by scripts/adr/generate-toc.sh and is never hand-edited. It takes each title from that document's own # heading, lists the numbered records first and the dated ones after — every dated record postdates every numbered one, so one flat list stays chronological — and supports --check so CI can fail a pull request whose index is stale.

Consequences

Two branches can now add an ADR on the same day without colliding, and a same-day collision resolves by renaming one file rather than renumbering a chain of them. ADRs are no longer referable by a short ordinal; they are referred to by filename or title, and cross-references between records must use the filename.

The directory carries two identifier styles until the numbered records are superseded, which is a visible seam but a self-limiting one. Regenerating the index corrected the titles of records 11 through 27 to match their documents, which is the last hand-edit toc.md should ever need.