From 5a3cfd809841d123b3aa3aa85c4998c2ead10471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Schultz=20Madsen?= Date: Sun, 13 Sep 2026 15:58:30 +0200 Subject: [PATCH] docs: map the dependency version spread across the container repos Four *-service-build jobs fail deterministically in work-items-planning-container. The cause is a runtime assembly mismatch, not a code or SDK-behaviour change: the service host loads plugins from /app/Plugins//, each plugin ships its own transitive DLLs there, and host and plugin were built against different versions. Traced to System.ComponentModel.Composition -- the host pins 10.0.10, timeplanning 10.0.11, items-planning 10.0.9, workflow 2010.2.11.1, and the runtime wanted assembly 10.0.0.12. The workflow pin is a 2010-era package whose version sorts highest by major, which is what anyone taking 'the latest version' naively would land on. Eleven repos ship in this container and span 17 versions of Microting.eForm, from 10.0.39 down to 10.0.22. eform-angular-frontend disagrees with itself across four: the host process is on 10.0.39 while the plugin mirrors bundled inside it sit on 10.0.35, 10.0.37 and 10.0.38. eform-debian-service carries stale plugin mirrors still pinning 10.0.4. Records current state, targets verified against nuget, and a per-repo action list ordered bases -> plugins -> hosts, because a host bumped before its plugins just relocates the mismatch. Nothing here catches the next occurrence: neither the plugin's CI nor the host's CI can see a mismatch that exists only once they are assembled. A check in the container repo comparing pins across the checked-out repos is the only thing that would. Co-Authored-By: Claude Opus 5 (1M context) --- .../2026-09-13-dependency-alignment-map.md | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 docs/superpowers/specs/2026-09-13-dependency-alignment-map.md diff --git a/docs/superpowers/specs/2026-09-13-dependency-alignment-map.md b/docs/superpowers/specs/2026-09-13-dependency-alignment-map.md new file mode 100644 index 00000000..f450564c --- /dev/null +++ b/docs/superpowers/specs/2026-09-13-dependency-alignment-map.md @@ -0,0 +1,213 @@ +# Dependency alignment map — the repos that ship in `work-items-planning-container` + +**Date:** 2026-09-13 +**Trigger:** four `*-service-build` jobs failing deterministically on +`work-items-planning-container` run 34753032043 (all four attempts). + +--- + +## 1. The failure, and why it is a version problem and not a code problem + +``` +Could not load file or assembly 'System.ComponentModel.Composition, Version=10.0.0.12, + Culture=neutral, PublicKeyToken=b77a5c561934e089' +Could not load file or assembly + '/app/Plugins/ServiceTimePlanningPlugin/System.ComponentModel.Composition.dll'. +The located assembly's manifest definition does not match the assembly reference. +``` + +The service host loads plugins out of `/app/Plugins//`. Each plugin ships its own +copy of its transitive dependencies into that directory. When the host and the plugin were +built against different versions of the same package, the host's reference and the DLL in +the plugin folder disagree and the load fails **at runtime** — nothing catches this at +compile time, and no unit test catches it either, because the assembly only has to resolve +once the two are combined in the container. + +Traced to the exact pins: + +| | `System.ComponentModel.Composition` | +|---|---| +| `eform-debian-service/MicrotingService/MicrotingService.csproj:44` (host) | **10.0.10** | +| `eform-service-timeplanning-plugin/ServiceTimePlanningPlugin/…csproj:20` (plugin) | **10.0.11** | +| `eform-service-items-planning-plugin` | **10.0.9** | +| `eform-service-workflow-plugin` | **2010.2.11.1** ← a 2010-era package | +| assembly the runtime actually demanded | **10.0.0.12** (i.e. package `10.0.12`) | + +Four different versions of one package across a host and the three plugins it loads, and +none of them is the one the runtime wanted. + +**`2010.2.11.1` deserves its own callout.** `System.ComponentModel.Composition` has an +ancient release whose version number sorts highest by major, so anything that picks "the +latest version" naively lands on a package from 2010. Whoever bumped +`eform-service-workflow-plugin` almost certainly did that. + +--- + +## 2. Scope: 11 repos ship together + +From `work-items-planning-container/.github/workflows/dotnet-core-docker.yml`: + +``` +eform-angular-frontend eform-debian-service +eform-angular-greate-belt-plugin eform-service-backendconfiguration-plugin +eform-angular-items-planning-plugin eform-service-items-planning-plugin +eform-angular-timeplanning-plugin eform-service-timeplanning-plugin +eform-angular-workflow-plugin eform-service-workflow-plugin +eform-backendconfiguration-plugin +``` + +These eleven must agree. The other ~35 repos in the workspace do not ship in this +container and are out of scope here. + +--- + +## 3. Current state + +### 3a. The two SDK packages + +| Repo | `Microting.eForm` | `Microting.eFormApi.BasePn` | +|---|---|---| +| **eform-angular-frontend** | **10.0.35, 10.0.37, 10.0.38, 10.0.39** | **10.0.29, 10.0.31, 10.0.32, 10.0.33** | +| eform-angular-greate-belt-plugin | 10.0.35 | 10.0.29 | +| eform-angular-items-planning-plugin | 10.0.35 | 10.0.29 | +| eform-angular-timeplanning-plugin | 10.0.39 *(on `stable`)* | 10.0.33 *(on `stable`)* | +| eform-angular-workflow-plugin | 10.0.35 | 10.0.29 | +| eform-backendconfiguration-plugin | 10.0.37, 10.0.38 | 10.0.31, 10.0.32 | +| eform-debian-service *(host csproj)* | 10.0.36 | — | +| eform-service-backendconfiguration-plugin | 10.0.38 | 10.0.32 | +| eform-service-items-planning-plugin | 10.0.35 | 10.0.29 | +| eform-service-timeplanning-plugin | 10.0.38 | 10.0.32 | +| **eform-service-workflow-plugin** | **10.0.22** | **10.0.21** | + +Spread: **17 versions** between the newest (`eFormAPI.Web` at 10.0.39) and the oldest +(`eform-service-workflow-plugin` at 10.0.22). + +### 3b. The host disagrees with itself + +`eform-angular-frontend` is the epicentre — the host process and the plugins bundled inside +it are built against four different SDKs: + +``` +eForm=10.0.39 BasePn=10.0.33 eFormAPI/eFormAPI.Web/eFormAPI.Web.csproj ← the host +eForm=10.0.38 BasePn=10.0.32 eFormAPI/Plugins/BackendConfiguration.Pn/… +eForm=10.0.37 BasePn=10.0.31 eFormAPI/Plugins/TimePlanning.Pn/… +eForm=10.0.35 BasePn=10.0.29 eFormAPI/Plugins/GreateBelt.Pn/… +eForm=10.0.35 BasePn=10.0.29 eFormAPI/Plugins/InsightDashboard.Pn/… +eForm=10.0.35 BasePn=10.0.29 eFormAPI/Plugins/ItemsPlanning.Pn/… +eForm=10.0.35 BasePn=10.0.29 eFormAPI/Plugins/OuterInnerResource.Pn/… +eForm=10.0.35 BasePn=10.0.29 eFormAPI/Plugins/Workflow.Pn/… +``` + +Note these are **devinstall mirrors**, not sources — but they are what the container builds, +so their pins are load-bearing. The same is true of +`eform-debian-service/Plugins/Service*Plugin/`, which holds stale copies of all four service +plugins pinning `Microting.eForm` **10.0.4** and `Microting.TimePlanningBase` **10.0.7**. + +### 3c. Runtime packages that actually broke the build + +| Package | Host | timeplanning | backendconfig | items-planning | workflow | **Target** | +|---|---|---|---|---|---|---| +| `System.ComponentModel.Composition` | 10.0.10 | 10.0.11 | 10.0.11 | 10.0.9 | **2010.2.11.1** | **10.0.12** | +| `Microsoft.Extensions.DependencyModel` | 10.0.10 | 10.0.11 | 10.0.11 | 10.0.9 | 10.0.7 | **10.0.12** | +| `Sentry` | 6.0.0 / 6.7.0 | 6.9.0 | 6.9.0 | 6.6.0 | 6.4.1 | **6.11.0** | + +These three are the ones with a proven runtime consequence. Others differ too +(`DocumentFormat.OpenXml`, `QuestPDF`, `SkiaSharp`, `HtmlToOpenXml`, `HarfBuzzSharp`, +`Google.Apis.Sheets.v4`) but only inside single plugins, so they cannot collide across the +host boundary the same way. + +--- + +## 4. Targets + +All are the latest published, verified against nuget.org on 2026-09-13: + +| Package | Target | Note | +|---|---|---| +| `Microting.eForm` | **10.0.39** | `eFormAPI.Web` is already here — this is catch-up, not a new bump | +| `Microting.eFormApi.BasePn` | **10.0.33** | ditto | +| `Microting.TimePlanningBase` | **10.0.62** | timeplanning already here | +| `Microting.ItemsPlanningBase` | **10.0.38** | | +| `Microting.EformAngularFrontendBase` | **10.0.37** | | +| `Microting.EformBackendConfigurationBase` | **10.0.50** | | +| `Microting.eFormWorkflowBase` | **10.0.35** | | +| `Microting.eFormCaseTemplateBase` | **10.0.36** | | +| `System.ComponentModel.Composition` | **10.0.12** | **NOT** `2010.2.11.1` — see §1 | +| `Microsoft.Extensions.DependencyModel` | **10.0.12** | ships on the .NET 10 servicing cadence | +| `Sentry` | **6.11.0** | | + +--- + +## 5. Per-repo actions + +Ordered by dependency: **bases → plugins → hosts.** A host bumped before its plugins just +moves the mismatch. + +### Wave 1 — base packages (publish first, plugins consume them) + +| Repo | eForm | BasePn | +|---|---|---| +| `eform-items-planning-base` | 10.0.36 → **10.0.39** | 10.0.30 → **10.0.33** | +| `eform-workflow-base` | 10.0.36 → **10.0.39** | 10.0.30 → **10.0.33** | +| `eform-angular-frontend-base` | 10.0.36 → **10.0.39** | 10.0.30 → **10.0.33** | +| `eform-timeplanning-base` | 10.0.38 → **10.0.39** | 10.0.32 → **10.0.33** | +| `eform-backendconfiguration-base` | 10.0.38 → **10.0.39** | 10.0.32 → **10.0.33** | + +Each needs a release so the plugins have something to reference. + +### Wave 2 — plugin repos + +| Repo | eForm | BasePn | Also | +|---|---|---|---| +| `eform-service-workflow-plugin` | 10.0.22 → **10.0.39** | 10.0.21 → **10.0.33** | `System.ComponentModel.Composition` **2010.2.11.1 → 10.0.12**; `DependencyModel` → 10.0.12; `Sentry` → 6.11.0. **Biggest jump — 17 versions. Expect real breakage; do this one alone.** | +| `eform-angular-workflow-plugin` | 10.0.35 → **10.0.39** | 10.0.29 → **10.0.33** | | +| `eform-angular-greate-belt-plugin` | 10.0.35 → **10.0.39** | 10.0.29 → **10.0.33** | | +| `eform-angular-items-planning-plugin` | 10.0.35 → **10.0.39** | 10.0.29 → **10.0.33** | | +| `eform-service-items-planning-plugin` | 10.0.35 → **10.0.39** | 10.0.29 → **10.0.33** | `Composition` 10.0.9 → 10.0.12; `DependencyModel` → 10.0.12; `Sentry` 6.6.0 → 6.11.0 | +| `eform-backendconfiguration-plugin` | 10.0.37/38 → **10.0.39** | 10.0.31/32 → **10.0.33** | unify its two internal versions first | +| `eform-service-backendconfiguration-plugin` | 10.0.38 → **10.0.39** | 10.0.32 → **10.0.33** | `Composition` → 10.0.12 | +| `eform-service-timeplanning-plugin` | 10.0.38 → **10.0.39** | 10.0.32 → **10.0.33** | `Composition` 10.0.11 → **10.0.12** ← *the one in the failing log* | +| `eform-angular-timeplanning-plugin` | ✅ 10.0.39 | ✅ 10.0.33 | already aligned on `stable` (commit `9e2ae84f`) | + +### Wave 3 — hosts + +| Repo | Action | +|---|---| +| `eform-debian-service` | `MicrotingService.csproj`: eForm 10.0.36 → **10.0.39**; `Composition` 10.0.10 → **10.0.12**; `DependencyModel` 10.0.10 → **10.0.12**; `Sentry` → **6.11.0**. Then refresh the stale `Plugins/Service*Plugin/` mirrors, which still pin eForm **10.0.4** / TimePlanningBase **10.0.7** | +| `eform-angular-frontend` | Unify **all eight** `eFormAPI/**/*.csproj` to eForm **10.0.39** / BasePn **10.0.33**. The host is already there; the seven bundled plugin mirrors are not | + +--- + +## 6. Preventing recurrence + +Bumping eleven repos by hand puts them back in step once; it does nothing about the twelfth +time. Two options, in order of preference: + +1. **Central Package Management.** A `Directory.Packages.props` per repo with + `true`, versions declared + once, and `` with no `Version` in the csprojs. Inside a + repo this makes an internal disagreement (like the frontend's four-way split) + *unrepresentable*. +2. **A CI check in the container repo** that fails the build when two checked-out repos pin + different versions of the same package. Cheap, and it catches the cross-repo case that + even per-repo CPM cannot: it is the combination that breaks, and only the container sees + the combination. + +The second is what would have caught this one. Neither the plugin's CI nor the host's CI can +see a mismatch that only exists once they are assembled. + +--- + +## 7. Related but separate + +Two other failures on the same run are **not** version problems: + +- **`timeplanning-pn-dotnet-unit-test`** — `playwright-tour-seed.spec.ts` fails because the + container repo's workflow copies the plugin's Angular sources (including the spec) without + copying `playwright/helpers/tour-seen.storage.json` or the `storageState` wiring in + `playwright.config.ts`. The plugin's own CI does copy them + (`dotnet-core-pr.yml:68-70`, `:134-137`), which is why it is green there. Introduced by + PR #1703. Fix: add the same two copy lines to the container workflow. +- **`timeplanning-pn-dotnet-test (b, …)`** — `Create_CreatesPictureSnapshot_WithFile` fails + with `HTTP 403 InvalidAccessKeyId` uploading to `microting-uploaded-data`. An expired or + missing AWS key in that repo's CI secrets. Nothing to do with packages.