Skip to content

chore: bump release to v2026.08.9 - #42

Merged
sgort merged 19 commits into
accfrom
feature/rip-r21-signature-tag
Aug 29, 2026
Merged

chore: bump release to v2026.08.9#42
sgort merged 19 commits into
accfrom
feature/rip-r21-signature-tag

Conversation

@sgort

@sgort sgort commented Aug 29, 2026

Copy link
Copy Markdown
Owner

The first release cut under the acc supply-chain gate. The old flow —
git checkout acc && git merge --ff-only, then push — is rejected by the
ruleset, so releases land here now.

Six entries, thirty-two commits

Version Scope Theme
2026.08.9 Frontend Release tooling — ci commit type, ScopeBadge guard, ci/repo scopes, patched bump-release
2026.08.8 Full-stack Dependency currency and security — vite, axios, fast-xml-parser, concurrently, 23 backend deps, prettier reformat
2026.08.7 CI Supply-chain pinning enforced — 40 zizmor findings to 0, the gate, the Renovate config validator
2026.08.6 Repository R2.1 ValidSign signature, and the parity fix that completed it
2026.08.5 Full-stack RIP R2.2 VO deploy bundle (pre-existing entry, renumbered from .4 and extended 6 → 11 commits)
2026.08.4 Repository Earlier documentation and fixture repairs

Split by theme rather than cut as one block, following the ronl-business-api
precedent. The pre-existing Upcoming entry was renumbered .4.5: it was
never released, so no published version number changes, and the renumbering
keeps entries chronological — the documentation and fixture work genuinely
predates the R2.2 bundle.

Two new scope tags

Three of the six entries change neither deployable. ci covers pipeline
work and mirrors the tag ronl-business-api uses; repo covers changes that
ship no application code — documentation, and the Operaton deploy bundles under
examples/ and e2e-fixtures/, which the frontend does not serve (it has its
own copies under packages/frontend/public/examples/) and the backend reads
only from tests. Labelling any of it both would have claimed a release
touching only .github/ had changed application code.

A pre-existing defect this surfaced

feature/rip-r21-signature-tag had been failing its own example-fixture-parity
test since 8071778
— the ValidSign attribute was added to the e2e-fixtures/
mirror and not the examples/ source. The test and manifest are byte-identical
across the merge from acc, so this predates it. Fixed in 84493e3; the files
are now cmp-identical.

It went unnoticed because azure-backend-acc.yml triggers on push only, so no
pull request ever ran that test. Filed as follow-up #2.

Verification

npm run check-format exit 0
npm run lint pass
backend (Jest) 1134/1134
frontend (Vitest) 573/573
npm run build pass
npm ci --dry-run lockfile resolves
Changelog integrity all 32 cited SHAs resolve; none duplicated across entries

Versions set by hand in root, frontend and backend package.json plus the
four matching package-lock.json entries. npm version would have written
2026.8.9 — CalVer's zero-padded month is not a valid SemVer identifier.

Merge method

Merge commit only. Squash collapses the commits into one new commit and
rebase replays them as new commits, preserving the count while replacing every
hash — either leaves all 32 cited SHAs pointing at commits that do not exist on
acc. Squash and rebase are disabled repo-wide and the ruleset pins
allowed_merge_methods to ["merge"], so this is enforced rather than
remembered.

After the bump

a929250 deliberately follows the bump commit, so it opens the next release
range rather than arriving unlisted inside this one. It records the two CI gaps
this release exposed: check-format runs in no workflow, and the backend runs
no tests on a pull request.

sgort added 19 commits August 26, 2026 12:08
Turns examples/organizations/flevoland/rip-phases-left/R2 Planvoorbereiding/
R2_2 - VO.pdf (rev. 21-11-2024) into a specification for a bundle LDE can
import and deploy: a four-lane BPMN process with nine user tasks, nine
Camunda form-js forms, and five document templates — one per green "Format"
in the diagram, since a Format there and a .document here are the same thing.

Two design decisions worth flagging:

  - The cross-phase hand-offs to CO1 and JU3.5 are textAnnotations, not
    callActivities. Those processes do not exist as fixtures, so a
    callActivity would dangle at deploy time and fail the manifest's
    calledElement test. They are referenced by several phases and belong in
    a shared bundle of their own rather than being invented from R2.2's
    view of them.

  - Consequently all five branches of the opening parallel split rejoin the
    join gateway. The PDF does not draw it that way — it shows Inventariseren
    kabels en leidingen and Aanvragen raamvergunning leaving the pool and
    never returning, which as control flow deadlocks at the join. This is
    the one place the model deliberately diverges from the picture.

Also specifies renaming rip-phase1-swimlanes/ to rip-phase-21/. The suffix
distinguished it from a competing draft that b1b88a8 deleted, so it now
distinguishes nothing and no longer matches the process it holds. Verified
the only references are the descriptive source field in e2e-fixtures/
manifest.json and an entry in changelog.json; the backend tests use
RipR21Process as a process key, never as a path.

The bundle is authored under examples/ but registered in e2e-fixtures/
manifest.json, which is what import and deploy actually read. The five
existing tests in e2e-fixtures.test.ts then cover it with no new test code.
Six tasks: rename rip-phase1-swimlanes to rip-phase-21, add a parity
test, then the BPMN, the nine forms and the five documents, closing with
the changelog and a full verification pass.

Task 3 declares all fifteen files in the manifest up front, so the
fixture suite's file-existence test stays red through Tasks 3 and 4 and
turns green only at the end of Task 5. The plan flags that as the
expected state so nobody "fixes" it by trimming the manifest back.

Task 2 is an addition beyond the spec: a test asserting the examples/
and e2e-fixtures/ copies of each bundle are byte-identical. All sixteen
R2.1 files match today, so it starts green. It exists because 39a49bb
repaired the document zone keys in the fixtures copies alone and the
examples copies stayed broken until 44d1cb4 re-pasted them by hand -
nothing structural stopped that happening, and nothing stopped it
happening again.
The -swimlanes suffix distinguished this bundle from a competing
rip-phase1/ draft that b1b88a8 deleted, so it now distinguishes nothing,
and the directory name no longer matched the process it holds
(RipR21Process). Renaming it makes the incoming R2.2 bundle an obvious
sibling: rip-phase-21/ holds RipR21Process, rip-phase-22/ holds
RipR22Process.

Contents are untouched. Exactly one reference to the old path existed -
the source field of the RipR21Process entry in e2e-fixtures/manifest.json
- and it is repointed here. Nothing resolves this directory at runtime;
the app serves examples from packages/frontend/public/examples/, which
has never held the RIP bundles.

The spec and plan claimed two such references, the second being an entry
in changelog.json. There is no such entry: changelog.json mentions the
deleted rip-phase1/ directory and the RipPhase1Process -> RipR21Process
rename only inside historical release records, which describe what was
true when written and are not retro-edited. Both documents are corrected
here to say one reference, not two.
Each RIP bundle exists twice on disk: authored under examples/, imported
and deployed from e2e-fixtures/. Nothing stopped the two drifting, and
they have. 39a49bb repaired the document zone keys in the e2e-fixtures
copies only; the examples copies kept the dead "signoff" / "contactInfo"
keys until 44d1cb4 re-pasted them by hand. Anyone fixing one copy could
silently leave the other wrong again.

This asserts every file in a mirrored bundle is byte-identical to its
twin. New bundles opt in by adding an entry to MIRRORED_BUNDLES.
Four lanes and nine user tasks from R2_2 - VO.pdf (rev. 21-11-2024),
picking up where RipR21Process's "Fase 1 voltooid -> R2.2" end event
left off.

All five branches of the opening parallel split rejoin the join
gateway. The PDF does not draw it that way - it shows Inventariseren
kabels en leidingen and Aanvragen raamvergunning leaving the pool into
CO1 and JU3.5 and never coming back, which as control flow deadlocks at
the join. Those hand-offs are textAnnotations instead: CO1 and JU3.5 do
not exist as fixtures, so a callActivity would dangle at deploy time and
fail the manifest's calledElement test. They are referenced by several
phases and belong in a shared bundle of their own.

The manifest entry declares the nine forms and five documents that
follow in subsequent commits, so the fixture suite's file-existence test
stays red until the bundle is complete.
R2.1 wires each document template to the task that produces it with
ronl:documentRef - Task_AanvullenProjectplan2 -> rip-intake-report,
Task_AanvullenProjectplan4 -> rip-pdp, Task_UitvoerenPSU ->
rip-psu-report. That attribute is what renders the document badge on the
task in the Modeler. The R2.2 spec never mentioned it, so RipR22Process
shipped without it and the five templates Task 5 adds would have
imported but attached to nothing.

The attribute is single-valued: DocumentTemplateSelector writes one id
and BpmnCanvas reads a scalar, so a task can carry at most one template.
Four of the five bind:

  Task_VerzamelenKlanteisen    -> rip-kes
  Task_OpstellenConceptVO      -> rip-ontwerptoelichting
  Task_BesprekenConceptVO      -> rip-bevindingenformulier
  Task_OpstellenDefinitiefVO   -> rip-hoeveelheidsbepaling

rip-objectenboom stays unattached on purpose. It is the "Format
objectenboom (Relatics)" artifact, maintained in Relatics rather than
authored in this process, so no R2.2 task produces it.

Values are bare template ids with no .document suffix, matching R2.1.
Both the examples/ and e2e-fixtures/ copies are updated so the parity
test stays green. The spec and the plan are corrected too, so a future
executor does not repeat the omission.
One form per user task in RipR22Process, bound by camunda:formRef.
Field types stay inside the eight the R2.1 bundle already uses - text,
textarea, textfield, checkbox, datetime, select, radio, button - since
nothing else is exercised against this Camunda 7.21 stack.

The spec's conditional "LCC-raming (indien variantenafweging)" is a
checkbox plus a reference field on rip-concept-vo.form rather than an
artifact of its own; it only exists when a variant trade-off happened.

klicMeldingReferentie is collected only on
rip-inventariseren-kabels-leidingen.form. The concept VO task reads the
same information but does not also write it - two forms writing one
process variable means whichever task completes last silently wins.
One per green "Format ..." in R2_2 - VO.pdf: KES, Ontwerptoelichting,
Objectenboom, Bevindingenformulier and Hoeveelheidsbepaling. A Format in
the diagram and a .document in LDE are the same thing - a template with
bindings - so the mapping is direct, and the blue outputs beside them in
the spec are instances of these rather than artifacts of their own.

Zone keys are signOff and contactInformation, camelCase, from the start.
R2.1's templates shipped with "signoff" and "contactInfo", which are not
the keys DocumentZones declares, so their signature blocks never
rendered at all until 49832d2.

This completes the bundle: the manifest now declares nothing that does
not exist, and the fixture suite is green.
Records the RipR22Process bundle, the rip-phase1-swimlanes ->
rip-phase-21 rename, and the parity test now holding the examples/ and
e2e-fixtures/ copies of each bundle together.
Four findings from the whole-branch review of the R2.2 (VO) bundle:

- Dangling SHA: 39a49bb only survives on fix/rip-rebase-refs-and-live's
  sibling branch fix/rip-r21-document-fixtures, which is slated for
  deletion, so `git show 39a49bb` would stop resolving. Replaced with
  49832d2 everywhere it was cited — the parity test's doc comment, the
  e750f21 changelog entry, and (found while grepping repo-wide) three
  mentions in the R2.2 planning doc. Same reachable commit, same meaning:
  it repaired the document zone keys in the e2e-fixtures copies while the
  examples copies stayed broken until 44d1cb4.

- Dead binding: {{projectType}} was declared in the bindings array of all
  five .document templates but never placed in any zone's content — the
  only declared-and-unused placeholder in the bundle. Removed the
  projectType binding object from all five templates in both examples/
  and e2e-fixtures/, renumbering the remaining binding ids contiguously.
  projectNumber, projectName and vastgesteldProjectplan are untouched;
  those are placed in zone content and legitimately render empty pending
  R2.1's hand-off.

- Undocumented PDF divergence: the source PDF shows Inventariseren kabels
  en leidingen and Aanvragen raamvergunning leaving the pool into CO1/
  JU3.5 without returning; modelled literally that deadlocks
  Gateway_UitgangspuntenJoin, so all five branches return in this BPMN.
  That's explained in the spec and changelog but invisible to anyone
  opening the diagram in the Modeler. Added a fifth textAnnotation and
  association on the join gateway explaining the deliberate deviation,
  placed after every other flow element (BPMN's tProcess is ordered) with
  its own BPMNShape/BPMNEdge, in both copies.

- Inaccurate rationale: the spec and changelog justified leaving
  rip-objectenboom unattached by calling it Relatics-maintained with no
  producing task. Not quite right — rip-concept-vo.form collects
  objectenboomReferentie and Task_OpstellenConceptVO's template binds it,
  so that task does touch it. The real reason is ronl:documentRef is
  single-valued and that task's one slot went to rip-ontwerptoelichting
  instead. Reworded the rationale in the spec and the 8bd789d changelog
  entry; the wiring itself is unchanged.

Verification: backend parity/fixture suite 9/9 passed, check-format clean,
lint clean, no duplicate BPMN ids, all five .document pairs and the .bpmn
pair confirmed byte-identical between examples/ and e2e-fixtures/, and
39a49bb no longer appears anywhere in packages/ or docs/.
"het pool" -> "de pool" (pool is common-gender), and the subordinate
clause was missing "dat": the PDF shows THAT the two branches leave the
pool, not the branches themselves.

Text only. Both copies updated together so the parity test stays green.
Adds ronl:signatureRef="rip-pdp" to Task_AccorderenProjectplan4, the
"Accorderen Projectplan 4. Uitgangspunten VO-fase" task that closes R2.1.

This one attribute is the switch for the whole signing feature built in
ronl-business-api. The backend resolves ronl:signatureRef on a user task
and, when present, replaces that task's plain approval form with a
ValidSign signing ceremony: the phase document is rendered from its
deployed template, a signature package is created, and the Operaton task
completes only once the signature lands — carrying approvalStatus
through to Gateway_Akkoord4 exactly as the form did before.

Nothing else about the process changes. No flow, gateway, condition,
form reference or candidate group is touched, and Operaton ignores
unknown ronl: attributes, so this is a redeploy rather than a
restructure. Deleting the attribute and redeploying is the entire
rollback path.

It mirrors the ronl:documentRef="rip-pdp" already on
Task_AanvullenProjectplan4: one task produces the document, the other
signs it.

Task_AccorderenProjectplan2 — R2.1's other approval, with a
near-identical id — is deliberately left untagged. Only the phase exit
requires a signature for now.

xmlns:ronl was already declared for the existing documentRef
attributes, so no namespace change was needed; adding a namespaced
attribute without its declaration would fail XSD validation at deploy
time for the whole definition.

Verified with the e2e-fixtures suite (5 passed), whose artifact-order
test parses this file with libxml2 and so confirms it is still
well-formed.
RipR21Process.bpmn exists in two places that an example-fixture-parity test
locks together byte for byte: examples/organizations/flevoland/rip-phase-21/
is the authored source, e2e-fixtures/flevoland/ is the mirror.

The signature commit added ronl:signatureRef="rip-pdp" to Task_Accorderen-
Projectplan4 in the mirror only, leaving the source without it. The parity test
has been failing on this branch since then; it did not survive contact with the
merge from acc, it was already red.

Where it would otherwise have surfaced is worth noting: the backend workflow is
push-only, so no pull request runs these tests. The failure would have appeared
on acc after merge, where npm test gates the deploy step -- a red acceptance
branch and no deployment, for a defect that a pull-request test run would have
caught before it landed.

e2e-fixtures is the correct side, so the fix mirrors that file over the source.
The xmlns:ronl namespace was already declared in both, and the byte delta was
exactly 28 -- the length of ' ronl:signatureRef="rip-pdp"' and nothing else, so
this adds one attribute rather than reflowing the document. The two copies are
now cmp-identical with LF endings preserved.

Backend 1134/1134, including the four parity assertions.
…crashing the panel

Two changes to Changelog.tsx, both needed before the v2026.08.4 entry can be
written truthfully.

The commit-type union had no 'ci'. COMMIT_TYPE_META falls back to 'other' for
anything it does not recognise, so a ci entry would have rendered rather than
crashed -- but it would have rendered as a generic document icon, filing the
entire supply-chain pinning effort under "other". Four of the commits in the
next release are ci, and the pipeline work deserves to be findable by someone
scanning the changelog for why a release touched CI. It gets a lock icon and
amber, distinct from chore's broom.

ScopeBadge had no such fallback. changelog.json is imported as untyped JSON and
cast at the module boundary, so TypeScript never checks the scope strings the
data actually carries -- an unrecognised one reaches SCOPE_BADGE[scope] at
runtime, yields undefined, and takes the whole panel down on config.cls. The
type system cannot help here by construction, so the guard is the only thing
that can. It now falls back to the 'both' badge.

Committed before the release bump deliberately. The bump commit is the boundary
marker `git log --grep='^chore: bump release'` searches for and is never listed
in its own entry, so a source change folded into it ships undocumented.

Frontend 573/573, lint and check-format clean, build passes.
…te first

The command still described the pre-gate world. Two of its steps were not merely
out of date but impossible.

Step 7 said to run `git checkout acc && git merge --ff-only`, then reported that
it does not push and asked separately whether to. Both halves are now rejected:
acc gained the `acc supply-chain gate` ruleset on 2026-08-29, requiring a pull
request and a passing audit check. A locally created bump commit has never been
through CI, so the fast-forward cannot land. It is rewritten to push the working
branch, open a pull request, and let the human merge it -- with the note that
merging IS the push, so the separate ask is gone.

The merge method is called out because both alternatives silently break the
entry: it names every commit by SHA, and squash collapses them into one new
commit while rebase replays them as new commits, preserving the count and
replacing every hash. The repository already allows merge commits only, and the
ruleset pins allowed_merge_methods to ["merge"], so this is settled in settings
rather than left to memory -- but the reasoning belongs written down.

Step 0 is new. Enabling Renovate means dependency pull requests now arrive
continuously, and they rewrite package-lock.json -- the same file step 4 edits.
This release had to reconcile five of them first. Three lessons from doing that
are recorded: verify each one locally because the backend workflow is push-only
and no pull-request check runs its tests; include check-format in that
verification because it runs in no workflow at all, only the pre-push hook, and
prettier 3.9.6 reformatted five untouched files; and trial-merge before trusting
a stale branch, because Renovate rebases on conflict but not otherwise, and a
clean textual merge of two lockfile diffs can still produce a lockfile npm
rejects.

Also adds --no-merges to the range command, since every range now contains merge
commits that carry no changelog content; states that the range must be computed
only after the branch is up to date, because merging can add fix commits and
rebasing rewrites SHAs the entry cites; adds ci to the entry-shape type list;
and adds the remote-branch housekeeping check.
The scope field offered frontend, backend and both. Three entries in the
release that follows change no deployable's code at all, so none of the three
was true for them.

'ci' covers pipeline and supply-chain work -- .github/, renovate.json,
SECURITY-PIPELINE.md -- and mirrors the tag ronl-business-api already uses, so
the two repositories label the same kind of work the same way.

'repo' covers everything else that ships no application code: documentation,
and the Operaton deploy bundles under examples/ and e2e-fixtures/. Those
bundles are worth distinguishing from a frontend change, because the frontend
serves its own copies from packages/frontend/public/examples/ -- the root
directories are read only by the backend's tests and deployed to Operaton
separately.

Labelling any of this 'both' would have told a reader that a release touching
only .github/ had changed application code.

The ScopeBadge fallback added alongside the ci commit type means an
unrecognised scope degrades to a badge rather than an exception, so this is
additive rather than load-bearing -- but the badges should be right.
Six entries covering thirty-two commits, split by theme rather than cut as one
block: the earlier documentation and fixture repairs (.4), the RIP R2.2 VO
bundle (.5), the R2.1 ValidSign signature (.6), supply-chain pinning enforced
in CI (.7), dependency currency and security (.8), and release tooling (.9).

The pre-existing Upcoming entry was renumbered .4 to .5 and extended from six
commits to eleven. It was never released, so no published version number
changes; the renumbering keeps entries in chronological order, since the
documentation and fixture work genuinely predates the R2.2 bundle.

Two new scope tags were needed and are introduced by commits inside this
release: 'ci' for pipeline work and 'repo' for changes that ship no application
code. Three of the six entries change neither deployable, and calling any of
them 'both' would have told a reader that a release touching only .github/ had
changed application code.

Scope across the release is both, so root, frontend and backend package.json
are bumped together with the four matching package-lock.json entries. Set by
hand: npm version coerces to strict SemVer and would write 2026.8.9.

Verified: check-format 0, lint clean, backend 1134/1134, frontend 573/573,
build passes, npm ci --dry-run resolves. Every one of the thirty-two cited SHAs
was checked to resolve, with no commit appearing in two entries.

This is the first release cut under the acc supply-chain gate, so it lands
through a pull request rather than a local fast-forward.
Both were found while cutting the release and neither blocked it, so they are
filed rather than fixed in place.

check-format runs in no workflow at all -- only the pre-push hook -- so the rule
holds on a developer's machine and not on the shared branch. Prettier 3.9.6
arrived inside a twenty-three-package dependency update and reformatted five
untouched files; every CI check stayed green, and the symptom would have been
the next person's push failing on files they had never opened.

The backend runs no tests on a pull request. azure-backend-acc.yml triggers on
push only, so its 1130 tests run after the merge rather than before it: every
backend dependency update in this release had to be verified by hand, and a
parity-test failure sat on a pushed branch for days because no pull request
ever ran it. Bounded, because the deploy step follows npm test in the same job
-- a failure gives a red acc and no deployment rather than a broken backend.

Filed in docs/superpowers/plans/ rather than appended to SECURITY-PIPELINE.md,
which describes what the pipeline is rather than what it still lacks.

Deliberately committed after the release bump, so it opens the next release
range instead of arriving unlisted inside this one.
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://brave-bay-04f351e03-42.westeurope.4.azurestaticapps.net

@sgort
sgort merged commit 234a9ac into acc Aug 29, 2026
3 checks passed
@sgort
sgort deleted the feature/rip-r21-signature-tag branch August 29, 2026 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant