<workflowJob _class='org.jenkinsci.plugins.workflow.job.WorkflowJob'><action></action><action></action><action></action><action></action><action></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.JobDisplayAction'><displayUrl>https://jenkins.younex.de/job/blut24-landing/</displayUrl></action><action></action><action></action><action _class='com.cloudbees.plugins.credentials.ViewCredentialsAction'><stores></stores></action><description>blut24-landing — push to main deploys to 192.168.12.81:/var/www/blut24.com/web (zero downtime). Pipeline is defined by the Jenkinsfile in the repo.</description><displayName>blut24-landing</displayName><fullDisplayName>blut24-landing</fullDisplayName><fullName>blut24-landing</fullName><name>blut24-landing</name><url>https://jenkins.younex.de/job/blut24-landing/</url><buildable>true</buildable><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>15</buildNumber><marked><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#15 49f3d63</displayName><duration>30604</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #15 49f3d63</fullDisplayName><id>15</id><keepLog>false</keepLog><number>15</number><queueId>5476</queueId><result>SUCCESS</result><timestamp>1785257388243</timestamp><url>https://jenkins.younex.de/job/blut24-landing/15/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/locales/de.ts</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>server/api/registration/confirm.post.ts</affectedPath><affectedPath>server/utils/i18n.ts</affectedPath><affectedPath>app/locales/en.ts</affectedPath><affectedPath>README.md</affectedPath><commitId>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</commitId><timestamp>1785257378000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval

HANDOFF §4 (ERP repo, reference/blut24/HANDOFF.md). needs_manual_approval gated
nothing: couriers and no-domain clinics — exactly the registrations nothing
could verify — were auto-onboarded into iDempiere with live credentials mailed,
while form, confirmation mail and welcome mail promised a manual review.
confirm.post.ts now skips onboarding for them and records erp_status
'manual-approval'; the operator provisions them by hand. Verified and test
registrations stay fully automatic.

Copy made truthful: the test-domain notice no longer claims "marked for manual
approval" (test domains auto-activate; they are marked internally as test
registrations), and the manual-review texts are courier-neutral instead of
explaining a clinic-only domain lookup.

alreadyConfirmed now returns credentialsSent, read from the stored ERP payload
(setErpResult persists it).

README: the ERP auth section described a Bearer scheme the code never uses —
the token travels as the logship_it cookie, and the ERP's send-credentials
route is now gated on exact equality with the instance's IDEMPIERETOKEN, so
ERP_SERVICE_TOKEN must be exactly that value.

test-registration.mjs: courier confirm asserts needsManualApproval,
credentialsSent=false and erp_status 'manual-approval' (83/83 green).

Co-Authored-By: Claude Opus 4.8 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 18:49:38 +0200</date><id>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</id><msg>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval</msg><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>edit</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>server/api/registration/confirm.post.ts</file></path><path><editType>edit</editType><file>server/utils/i18n.ts</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><previousBuild><number>14</number><url>https://jenkins.younex.de/job/blut24-landing/14/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>14</buildNumber><marked><SHA1>49c9f2a18725f35f7caed718f3cd9669ca7b5048</SHA1><branch><SHA1>49c9f2a18725f35f7caed718f3cd9669ca7b5048</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>49c9f2a18725f35f7caed718f3cd9669ca7b5048</SHA1><branch><SHA1>49c9f2a18725f35f7caed718f3cd9669ca7b5048</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>49c9f2a18725f35f7caed718f3cd9669ca7b5048</SHA1><branch><SHA1>49c9f2a18725f35f7caed718f3cd9669ca7b5048</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#14 49c9f2a</displayName><duration>27282</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #14 49c9f2a</fullDisplayName><id>14</id><keepLog>false</keepLog><number>14</number><queueId>5471</queueId><result>SUCCESS</result><timestamp>1785247787466</timestamp><url>https://jenkins.younex.de/job/blut24-landing/14/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>.env.example</affectedPath><affectedPath>server/utils/mail.ts</affectedPath><affectedPath>app/components/SectionHero.vue</affectedPath><affectedPath>server/api/registration/submit.post.ts</affectedPath><affectedPath>server/api/registration/confirm.post.ts</affectedPath><affectedPath>app/components/SectionRegistration.vue</affectedPath><affectedPath>README.md</affectedPath><affectedPath>app/locales/en.ts</affectedPath><affectedPath>server/utils/registrationTypes.ts</affectedPath><affectedPath>app/locales/de.ts</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>server/utils/registrationValidation.ts</affectedPath><affectedPath>app/composables/useRegistrationDialog.ts</affectedPath><affectedPath>server/utils/registrationDb.ts</affectedPath><affectedPath>server/utils/erpOnboarding.ts</affectedPath><affectedPath>app/components/RegistrationForm.vue</affectedPath><affectedPath>server/utils/i18n.ts</affectedPath><commitId>49c9f2a18725f35f7caed718f3cd9669ca7b5048</commitId><timestamp>1785247772000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>Fixes
</comment><date>2026-07-28 16:09:32 +0200</date><id>49c9f2a18725f35f7caed718f3cd9669ca7b5048</id><msg>Fixes</msg><path><editType>edit</editType><file>server/api/registration/confirm.post.ts</file></path><path><editType>edit</editType><file>server/utils/erpOnboarding.ts</file></path><path><editType>edit</editType><file>app/components/RegistrationForm.vue</file></path><path><editType>edit</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>.env.example</file></path><path><editType>edit</editType><file>app/components/SectionHero.vue</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>add</editType><file>server/utils/registrationTypes.ts</file></path><path><editType>edit</editType><file>server/utils/registrationDb.ts</file></path><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>server/api/registration/submit.post.ts</file></path><path><editType>edit</editType><file>app/composables/useRegistrationDialog.ts</file></path><path><editType>edit</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>server/utils/i18n.ts</file></path><path><editType>edit</editType><file>server/utils/registrationValidation.ts</file></path><path><editType>edit</editType><file>server/utils/mail.ts</file></path><path><editType>edit</editType><file>app/components/SectionRegistration.vue</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>15</number><url>https://jenkins.younex.de/job/blut24-landing/15/</url></nextBuild><previousBuild><number>13</number><url>https://jenkins.younex.de/job/blut24-landing/13/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>13</buildNumber><marked><SHA1>595e2c473bdb201384ea147d00098a5c8786b811</SHA1><branch><SHA1>595e2c473bdb201384ea147d00098a5c8786b811</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>595e2c473bdb201384ea147d00098a5c8786b811</SHA1><branch><SHA1>595e2c473bdb201384ea147d00098a5c8786b811</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>595e2c473bdb201384ea147d00098a5c8786b811</SHA1><branch><SHA1>595e2c473bdb201384ea147d00098a5c8786b811</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#13 595e2c4</displayName><duration>26227</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #13 595e2c4</fullDisplayName><id>13</id><keepLog>false</keepLog><number>13</number><queueId>5469</queueId><result>SUCCESS</result><timestamp>1785239626779</timestamp><url>https://jenkins.younex.de/job/blut24-landing/13/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/components/LangFlag.vue</affectedPath><affectedPath>app/components/SectionHero.vue</affectedPath><affectedPath>app/locales/de.ts</affectedPath><affectedPath>app/components/RegistrationDialog.vue</affectedPath><affectedPath>app/components/SiteHeader.vue</affectedPath><affectedPath>app/locales/en.ts</affectedPath><commitId>595e2c473bdb201384ea147d00098a5c8786b811</commitId><timestamp>1785239613000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>Language switch becomes a borderless flag menu; free-of-charge block moves into the dialog

The switch showed both languages permanently inside a bordered group, spending
header width and visual weight on a control almost nobody touches. It is now a
borderless trigger carrying only the CURRENT language — flag, code and a caret —
that opens a small menu with the alternatives and a tick against the active one.
Chrome appears only on hover, focus or open.

Still two real buttons, so the site-wide focus ring and keyboard operation are
unchanged; aria-haspopup/aria-expanded describe the menu and each entry carries
aria-current. The menu closes on outside click, on Escape and after choosing, and
both listeners are attached only while it is open and removed on unmount.

Flags moved into their own LangFlag component: the Union Jack needs a clipPath and
the glyph now renders up to three times on one page, so a shared literal id would
have made every instance clip against the first one's rect. Drawn as SVG rather
than flag emoji, which do not render as flags on Windows at all.

The free-of-charge block moves out of the hero and into the foot of the
registration dialog, after the form — the cost question is what someone asks once
they have seen how much they are being asked for. Its copy moved from hero.* to
dialog.* to match. The dialog's header subtitle said the same thing directly under
a heading that already reads "Kostenlos … registrieren", so it is dropped rather
than repeated twice in one panel.

Hero grid switched from items-center to items-start, so the "Blutkonserven-Plattform"
eyebrow and the top edge of the stock-matrix card now share a top line.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 13:53:33 +0200</date><id>595e2c473bdb201384ea147d00098a5c8786b811</id><msg>Language switch becomes a borderless flag menu; free-of-charge block moves into the dialog</msg><path><editType>add</editType><file>app/components/LangFlag.vue</file></path><path><editType>edit</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>app/components/SectionHero.vue</file></path><path><editType>edit</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>app/components/RegistrationDialog.vue</file></path><path><editType>edit</editType><file>app/components/SiteHeader.vue</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>14</number><url>https://jenkins.younex.de/job/blut24-landing/14/</url></nextBuild><previousBuild><number>12</number><url>https://jenkins.younex.de/job/blut24-landing/12/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>12</buildNumber><marked><SHA1>992a7b175443cc5ffeadaac8c785d913ecc1b57d</SHA1><branch><SHA1>992a7b175443cc5ffeadaac8c785d913ecc1b57d</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>992a7b175443cc5ffeadaac8c785d913ecc1b57d</SHA1><branch><SHA1>992a7b175443cc5ffeadaac8c785d913ecc1b57d</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>992a7b175443cc5ffeadaac8c785d913ecc1b57d</SHA1><branch><SHA1>992a7b175443cc5ffeadaac8c785d913ecc1b57d</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#12 992a7b1</displayName><duration>27710</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #12 992a7b1</fullDisplayName><id>12</id><keepLog>false</keepLog><number>12</number><queueId>5466</queueId><result>SUCCESS</result><timestamp>1785238671688</timestamp><url>https://jenkins.younex.de/job/blut24-landing/12/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/components/SiteHeader.vue</affectedPath><affectedPath>app/assets/css/main.css</affectedPath><affectedPath>app/components/SectionHero.vue</affectedPath><commitId>992a7b175443cc5ffeadaac8c785d913ecc1b57d</commitId><timestamp>1785238658000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>Flag-led language switch; move the free-of-charge message under the stock matrix

The language toggle filled its active half with --color-blood-700 — the same red as
the primary "Registrieren" button — so two red elements sat side by side in the
header and the switch competed with the one action that matters. It is now
flag-led: the flag carries the meaning, selection is shown by saturation plus a
neutral tinted background, and red goes back to belonging to the CTA alone.

The DE/EN code stays beside each flag deliberately. A flag denotes a country
rather than a language, and the Union Jack for "English" is a convention rather
than a fact, so the text is what actually disambiguates; both buttons keep their
aria-label and gain a title.

The free-of-charge block moves out of the hero's left column to sit under the
stock matrix, so the reader meets it right after seeing what the product does
rather than beside the headline. Recoloured red to green: red is the blood and
brand colour and made a reassurance read like an alert. Green is the conventional
"no cost" signal and nothing else on the page uses it, so it stands out without
competing. Added as contrast-checked --color-free-* tokens rather than stock
emerald, matching how the rest of the palette is defined.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 13:37:38 +0200</date><id>992a7b175443cc5ffeadaac8c785d913ecc1b57d</id><msg>Flag-led language switch; move the free-of-charge message under the stock matrix</msg><path><editType>edit</editType><file>app/components/SiteHeader.vue</file></path><path><editType>edit</editType><file>app/components/SectionHero.vue</file></path><path><editType>edit</editType><file>app/assets/css/main.css</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>13</number><url>https://jenkins.younex.de/job/blut24-landing/13/</url></nextBuild><previousBuild><number>11</number><url>https://jenkins.younex.de/job/blut24-landing/11/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>11</buildNumber><marked><SHA1>1b159ec466b3092fcd9e053fc84a89b6f54023fb</SHA1><branch><SHA1>1b159ec466b3092fcd9e053fc84a89b6f54023fb</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>1b159ec466b3092fcd9e053fc84a89b6f54023fb</SHA1><branch><SHA1>1b159ec466b3092fcd9e053fc84a89b6f54023fb</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>1b159ec466b3092fcd9e053fc84a89b6f54023fb</SHA1><branch><SHA1>1b159ec466b3092fcd9e053fc84a89b6f54023fb</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#11 1b159ec</displayName><duration>25732</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #11 1b159ec</fullDisplayName><id>11</id><keepLog>false</keepLog><number>11</number><queueId>5464</queueId><result>SUCCESS</result><timestamp>1785238001631</timestamp><url>https://jenkins.younex.de/job/blut24-landing/11/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>server/utils/mail.ts</affectedPath><affectedPath>app/components/SectionWaste.vue</affectedPath><affectedPath>app/pages/bestaetigung.vue</affectedPath><affectedPath>server/api/registration/submit.post.ts</affectedPath><affectedPath>app/components/SiteFooter.vue</affectedPath><affectedPath>app/components/SiteHeader.vue</affectedPath><affectedPath>server/api/registration/confirm.post.ts</affectedPath><affectedPath>app/components/SectionRegistration.vue</affectedPath><affectedPath>app/pages/datenschutz.vue</affectedPath><affectedPath>app/locales/en.ts</affectedPath><affectedPath>app/composables/useLocale.ts</affectedPath><affectedPath>nuxt.config.ts</affectedPath><affectedPath>app/components/SectionBenefit.vue</affectedPath><affectedPath>app/locales/de.ts</affectedPath><affectedPath>server/utils/registrationValidation.ts</affectedPath><affectedPath>app/components/SectionFeatures.vue</affectedPath><affectedPath>app/composables/useRegistrationDialog.ts</affectedPath><affectedPath>app/locales/detect.ts</affectedPath><affectedPath>app/components/AndroidBadge.vue</affectedPath><affectedPath>app/locales/index.ts</affectedPath><affectedPath>app/components/RegistrationForm.vue</affectedPath><affectedPath>server/utils/i18n.ts</affectedPath><affectedPath>app/components/SectionProof.vue</affectedPath><affectedPath>app/components/StockMatrixPreview.vue</affectedPath><affectedPath>app/components/LegalTranslationNotice.vue</affectedPath><affectedPath>app/pages/index.vue</affectedPath><affectedPath>app/app.vue</affectedPath><affectedPath>app/components/SectionHero.vue</affectedPath><affectedPath>README.md</affectedPath><affectedPath>app/components/SectionCourier.vue</affectedPath><affectedPath>app/components/SectionHowItWorks.vue</affectedPath><affectedPath>app/components/SectionApp.vue</affectedPath><affectedPath>app/components/RegistrationDialog.vue</affectedPath><affectedPath>app/pages/impressum.vue</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>server/utils/registrationDb.ts</affectedPath><commitId>1b159ec466b3092fcd9e053fc84a89b6f54023fb</commitId><timestamp>1785237988000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>Full DE/EN with runtime switch, benefit-led section, free-of-charge messaging

English translation with a language switch in the header. Uses a typed message
catalogue plus a small composable rather than @nuxtjs/i18n: the site is 12
components and 4 pages, and i18n would add vue-i18n plus a build transform and
want to own the URL space (/en/...), breaking every in-page anchor and every link
already shared. Both languages live on one URL, so a shared link always works.
en.ts is typed against de.ts, so a missing key fails the type check.

Locale precedence is ?lang= then the b24_lang cookie then Accept-Language, with
German winning on absence, ties, wildcards and unparsable input. It is resolved
once on the server and carried through the payload, so hydration cannot disagree.
Confirmation, welcome and duplicate mails follow the language stored on the
registration row rather than the language of whoever triggered them; the internal
ops mail stays German.

Impressum and Datenschutz are translated for comprehension only — the English
pages carry a notice that the German version is solely authoritative and link
back to it. "Freiberufler" is left untranslated with a gloss because the English
options all name different legal statuses, and German statute short names are
kept. The privacy notice now discloses the b24_lang cookie.

"Verfall &amp; Kosten" becomes "Ihr Vorteil" / "Your benefit", led by the gain rather
than the loss. The worked example stays labelled as our own assumption — no
invented statistics. #vorteil is the new anchor and #verfall still resolves.

Free registration and use is stated in the hero, the proof band, the registration
CTA and the dialog header, claiming only what is actually free.

Fixes the dialog keeping the last confirmation screen: reopening after a completed
submission resets the form, while dismissing mid-typing keeps every keystroke,
because the reset runs on open and only when the previous run finished. Replaces
"Weitere Einrichtung registrieren" with a plain close action.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 13:26:28 +0200</date><id>1b159ec466b3092fcd9e053fc84a89b6f54023fb</id><msg>Full DE/EN with runtime switch, benefit-led section, free-of-charge messaging</msg><path><editType>edit</editType><file>app/components/AndroidBadge.vue</file></path><path><editType>edit</editType><file>app/components/SectionHero.vue</file></path><path><editType>add</editType><file>server/utils/i18n.ts</file></path><path><editType>edit</editType><file>server/utils/mail.ts</file></path><path><editType>add</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>edit</editType><file>app/components/RegistrationDialog.vue</file></path><path><editType>edit</editType><file>app/components/RegistrationForm.vue</file></path><path><editType>edit</editType><file>app/components/SectionFeatures.vue</file></path><path><editType>delete</editType><file>app/components/SectionWaste.vue</file></path><path><editType>edit</editType><file>server/utils/registrationValidation.ts</file></path><path><editType>add</editType><file>app/locales/index.ts</file></path><path><editType>edit</editType><file>server/api/registration/confirm.post.ts</file></path><path><editType>edit</editType><file>server/utils/registrationDb.ts</file></path><path><editType>add</editType><file>app/locales/detect.ts</file></path><path><editType>edit</editType><file>app/components/SectionCourier.vue</file></path><path><editType>edit</editType><file>app/components/SiteFooter.vue</file></path><path><editType>edit</editType><file>app/components/SectionHowItWorks.vue</file></path><path><editType>edit</editType><file>app/pages/index.vue</file></path><path><editType>add</editType><file>app/components/LegalTranslationNotice.vue</file></path><path><editType>edit</editType><file>app/components/StockMatrixPreview.vue</file></path><path><editType>edit</editType><file>app/composables/useRegistrationDialog.ts</file></path><path><editType>edit</editType><file>app/components/SectionApp.vue</file></path><path><editType>edit</editType><file>nuxt.config.ts</file></path><path><editType>add</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>app/components/SiteHeader.vue</file></path><path><editType>edit</editType><file>app/pages/bestaetigung.vue</file></path><path><editType>edit</editType><file>app/components/SectionProof.vue</file></path><path><editType>edit</editType><file>app/pages/datenschutz.vue</file></path><path><editType>edit</editType><file>app/pages/impressum.vue</file></path><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>server/api/registration/submit.post.ts</file></path><path><editType>edit</editType><file>app/components/SectionRegistration.vue</file></path><path><editType>edit</editType><file>app/app.vue</file></path><path><editType>add</editType><file>app/components/SectionBenefit.vue</file></path><path><editType>add</editType><file>app/composables/useLocale.ts</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>12</number><url>https://jenkins.younex.de/job/blut24-landing/12/</url></nextBuild><previousBuild><number>10</number><url>https://jenkins.younex.de/job/blut24-landing/10/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>10</buildNumber><marked><SHA1>a5ea20018abc28385336941df5780f7d1753e72e</SHA1><branch><SHA1>a5ea20018abc28385336941df5780f7d1753e72e</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>a5ea20018abc28385336941df5780f7d1753e72e</SHA1><branch><SHA1>a5ea20018abc28385336941df5780f7d1753e72e</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>a5ea20018abc28385336941df5780f7d1753e72e</SHA1><branch><SHA1>a5ea20018abc28385336941df5780f7d1753e72e</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#10 a5ea200</displayName><duration>26200</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #10 a5ea200</fullDisplayName><id>10</id><keepLog>false</keepLog><number>10</number><queueId>5461</queueId><result>SUCCESS</result><timestamp>1785232956187</timestamp><url>https://jenkins.younex.de/job/blut24-landing/10/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>scripts/test-registration.mjs</affectedPath><commitId>a5ea20018abc28385336941df5780f7d1753e72e</commitId><timestamp>1785232944000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>test: courier freemail is now accepted, not rejected

The suite still asserted the old rule and failed on the previous commit — I
pushed without reading the result. The assertion now matches the intended
behaviour and explains why, so it does not read as a weakened check: couriers are
not tied to a clinic domain and are reviewed manually, while the freemail block
for clinics is asserted separately and unchanged.

38 checks, 0 failures.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 12:02:24 +0200</date><id>a5ea20018abc28385336941df5780f7d1753e72e</id><msg>test: courier freemail is now accepted, not rejected</msg><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>11</number><url>https://jenkins.younex.de/job/blut24-landing/11/</url></nextBuild><previousBuild><number>9</number><url>https://jenkins.younex.de/job/blut24-landing/9/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>9</buildNumber><marked><SHA1>f182d455db3a8ce7361ae7d2e691c06efffe267b</SHA1><branch><SHA1>f182d455db3a8ce7361ae7d2e691c06efffe267b</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>f182d455db3a8ce7361ae7d2e691c06efffe267b</SHA1><branch><SHA1>f182d455db3a8ce7361ae7d2e691c06efffe267b</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>f182d455db3a8ce7361ae7d2e691c06efffe267b</SHA1><branch><SHA1>f182d455db3a8ce7361ae7d2e691c06efffe267b</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#9 f182d45</displayName><duration>26078</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #9 f182d45</fullDisplayName><id>9</id><keepLog>false</keepLog><number>9</number><queueId>5459</queueId><result>SUCCESS</result><timestamp>1785232906182</timestamp><url>https://jenkins.younex.de/job/blut24-landing/9/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>server/utils/mail.ts</affectedPath><affectedPath>server/api/registration/submit.post.ts</affectedPath><affectedPath>app/components/RegistrationForm.vue</affectedPath><affectedPath>server/utils/registrationValidation.ts</affectedPath><commitId>f182d455db3a8ce7361ae7d2e691c06efffe267b</commitId><timestamp>1785232895000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>registration: switching type must not carry the other branch's data

Reported from real use: pick a clinic, switch to "Kurierdienst", register — and
the confirmation mail arrived as "Medizinischer Kurierdienst / Einrichtung:
Facharztklinik Hamburg / Anschrift: Martinistraße 78". There was no watcher on
form.type at all, so stoid/orgName/street/plz/city kept the clinic's values and
the courier branch submits those fields verbatim. Switching type now clears the
clinic selection, the address fields and the related errors.

Couriers may register with any address, freemail included — they are not tied to
a clinic domain and every courier registration is reviewed manually anyway. The
block stays for clinics, where the domain is what proves the registrant belongs
to the Standort they picked. Enforced on the server too, not just in the form.

The confirmation mail is now written per type: a courier is not a clinic, so it
gets its own description (orders on the phone, confirm pickup/delivery in the
app, free, manual review) and the detail row reads "Unternehmen" rather than
"Einrichtung". Both the HTML and the plain-text alternative.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 12:01:35 +0200</date><id>f182d455db3a8ce7361ae7d2e691c06efffe267b</id><msg>registration: switching type must not carry the other branch's data</msg><path><editType>edit</editType><file>server/api/registration/submit.post.ts</file></path><path><editType>edit</editType><file>server/utils/mail.ts</file></path><path><editType>edit</editType><file>app/components/RegistrationForm.vue</file></path><path><editType>edit</editType><file>server/utils/registrationValidation.ts</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>10</number><url>https://jenkins.younex.de/job/blut24-landing/10/</url></nextBuild><previousBuild><number>8</number><url>https://jenkins.younex.de/job/blut24-landing/8/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>8</buildNumber><marked><SHA1>b1a7c4026f44521453558a428303a0537697beda</SHA1><branch><SHA1>b1a7c4026f44521453558a428303a0537697beda</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>b1a7c4026f44521453558a428303a0537697beda</SHA1><branch><SHA1>b1a7c4026f44521453558a428303a0537697beda</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>b1a7c4026f44521453558a428303a0537697beda</SHA1><branch><SHA1>b1a7c4026f44521453558a428303a0537697beda</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#8 b1a7c40</displayName><duration>26057</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #8 b1a7c40</fullDisplayName><id>8</id><keepLog>false</keepLog><number>8</number><queueId>5457</queueId><result>SUCCESS</result><timestamp>1785232726165</timestamp><url>https://jenkins.younex.de/job/blut24-landing/8/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>.env.example</affectedPath><affectedPath>app/components/RegistrationForm.vue</affectedPath><affectedPath>nuxt.config.ts</affectedPath><commitId>b1a7c4026f44521453558a428303a0537697beda</commitId><timestamp>1785232713000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>registration: the FORM also has to know about the test domains

A whitelisted address was still rejected with "Die Domain gehört nicht zu …".
The server accepted it — I had only ever tested the server with curl, which
bypasses the form entirely. The browser does its own domain check for instant
feedback and knew nothing about REGISTRATION_TEST_DOMAINS, so it blocked the
submit before the request was ever sent. Verified the wrong layer, missed the bug.

The list is now mirrored into runtimeConfig.public and consulted by both the
submit guard and the blur handler. Publishing it is acceptable: it is a temporary
operator feature (empty in real production) and a bypassed registration still has
to confirm a mail delivered to that domain, so knowing the name grants nothing.

The blur notice does NOT claim the domain "matches the Standort" — that would be
untrue. It says it is a test domain and that the registration is flagged for
manual approval.

Note the two-name trap, documented in .env.example: REGISTRATION_TEST_DOMAINS is
read server-side, NUXT_PUBLIC_REGISTRATION_TEST_DOMAINS by the browser. Set both
or the form and the server disagree — which is exactly this bug.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 11:58:33 +0200</date><id>b1a7c4026f44521453558a428303a0537697beda</id><msg>registration: the FORM also has to know about the test domains</msg><path><editType>edit</editType><file>app/components/RegistrationForm.vue</file></path><path><editType>edit</editType><file>nuxt.config.ts</file></path><path><editType>edit</editType><file>.env.example</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>9</number><url>https://jenkins.younex.de/job/blut24-landing/9/</url></nextBuild><previousBuild><number>7</number><url>https://jenkins.younex.de/job/blut24-landing/7/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>7</buildNumber><marked><SHA1>4476c9c4298767c7d1e75e392fda5233727c5d91</SHA1><branch><SHA1>4476c9c4298767c7d1e75e392fda5233727c5d91</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>4476c9c4298767c7d1e75e392fda5233727c5d91</SHA1><branch><SHA1>4476c9c4298767c7d1e75e392fda5233727c5d91</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>4476c9c4298767c7d1e75e392fda5233727c5d91</SHA1><branch><SHA1>4476c9c4298767c7d1e75e392fda5233727c5d91</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#7 4476c9c</displayName><duration>26829</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #7 4476c9c</fullDisplayName><id>7</id><keepLog>false</keepLog><number>7</number><queueId>5453</queueId><result>SUCCESS</result><timestamp>1785228855796</timestamp><url>https://jenkins.younex.de/job/blut24-landing/7/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/components/SectionCourier.vue</affectedPath><affectedPath>app/components/SectionHowItWorks.vue</affectedPath><affectedPath>app/components/SectionHero.vue</affectedPath><affectedPath>app/components/SiteFooter.vue</affectedPath><affectedPath>app/components/SectionRegistration.vue</affectedPath><affectedPath>app/components/SectionProof.vue</affectedPath><commitId>4476c9c4298767c7d1e75e392fda5233727c5d91</commitId><timestamp>1785228842000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>landing: copy pass — courier value proposition, step 4, spacing, footer

- Step 4 now says what actually happens: if the other clinic is on Blut24 too,
  order, delivery note and unit data stay inside the system with nothing retyped
  or faxed; DGTI-Lieferschein, PDF and e-mail remain available for houses that
  are not yet connected, rather than being the default path.
- Courier section rewritten around the app: orders arrive on the phone, pickup
  and delivery are confirmed there, and participation is free so a courier can
  win additional runs without buying software. Kept strictly to goods transport
  wording - no patient-transport terms.
- "dauerhaft kostenlos" -&gt; "für Kliniken kostenlos" everywhere.
- Tightened the gap between the header and the hero headline on both breakpoints.
- Dropped the Bundes-Klinik-Atlas source line from the footer.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 10:54:02 +0200</date><id>4476c9c4298767c7d1e75e392fda5233727c5d91</id><msg>landing: copy pass — courier value proposition, step 4, spacing, footer</msg><path><editType>edit</editType><file>app/components/SectionHowItWorks.vue</file></path><path><editType>edit</editType><file>app/components/SectionProof.vue</file></path><path><editType>edit</editType><file>app/components/SectionRegistration.vue</file></path><path><editType>edit</editType><file>app/components/SectionHero.vue</file></path><path><editType>edit</editType><file>app/components/SectionCourier.vue</file></path><path><editType>edit</editType><file>app/components/SiteFooter.vue</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>8</number><url>https://jenkins.younex.de/job/blut24-landing/8/</url></nextBuild><previousBuild><number>6</number><url>https://jenkins.younex.de/job/blut24-landing/6/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>6</buildNumber><marked><SHA1>2264c156533706f135d03479119c61e6af91fa0d</SHA1><branch><SHA1>2264c156533706f135d03479119c61e6af91fa0d</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>2264c156533706f135d03479119c61e6af91fa0d</SHA1><branch><SHA1>2264c156533706f135d03479119c61e6af91fa0d</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>2264c156533706f135d03479119c61e6af91fa0d</SHA1><branch><SHA1>2264c156533706f135d03479119c61e6af91fa0d</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#6 2264c15</displayName><duration>26542</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #6 2264c15</fullDisplayName><id>6</id><keepLog>false</keepLog><number>6</number><queueId>5451</queueId><result>SUCCESS</result><timestamp>1785228290744</timestamp><url>https://jenkins.younex.de/job/blut24-landing/6/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/pages/datenschutz.vue</affectedPath><commitId>2264c156533706f135d03479119c61e6af91fa0d</commitId><timestamp>1785228279000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>datenschutz: name the actual controller, matching the Impressum

Both pages must name the same responsible party or they contradict each other,
so the Verantwortlicher section now carries the same operator data as the
Impressum (Younes Kalakhi, IT Beratung &amp; Dienstleistung, Lahnau) instead of
bracketed placeholders.

Two judgement calls, both noted in the file:
- the e-mail is still a placeholder because it is obfuscated on the source page
  and could not be read; Art. 13 DSGVO requires a contact route, so it must be
  filled before this is treated as live
- no Datenschutzbeauftragter is claimed - a freelancer of this size is generally
  not required to appoint one under § 38 BDSG, and asserting one that does not
  exist would be worse than saying none is appointed

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 10:44:39 +0200</date><id>2264c156533706f135d03479119c61e6af91fa0d</id><msg>datenschutz: name the actual controller, matching the Impressum</msg><path><editType>edit</editType><file>app/pages/datenschutz.vue</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>7</number><url>https://jenkins.younex.de/job/blut24-landing/7/</url></nextBuild><previousBuild><number>5</number><url>https://jenkins.younex.de/job/blut24-landing/5/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>5</buildNumber><marked><SHA1>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</SHA1><branch><SHA1>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</SHA1><branch><SHA1>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</SHA1><branch><SHA1>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#5 9d95707</displayName><duration>26645</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #5 9d95707</fullDisplayName><id>5</id><keepLog>false</keepLog><number>5</number><queueId>5449</queueId><result>SUCCESS</result><timestamp>1785227610682</timestamp><url>https://jenkins.younex.de/job/blut24-landing/5/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>deploy/README.md</affectedPath><affectedPath>app/app.vue</affectedPath><affectedPath>app/components/SectionHero.vue</affectedPath><affectedPath>server/api/registration/submit.post.ts</affectedPath><affectedPath>app/components/SiteFooter.vue</affectedPath><affectedPath>app/components/SiteHeader.vue</affectedPath><affectedPath>app/components/SectionRegistration.vue</affectedPath><affectedPath>app/pages/datenschutz.vue</affectedPath><affectedPath>README.md</affectedPath><affectedPath>app/components/SectionCourier.vue</affectedPath><affectedPath>.idea/vcs.xml</affectedPath><affectedPath>app/components/SectionApp.vue</affectedPath><affectedPath>app/components/RegistrationDialog.vue</affectedPath><affectedPath>server/utils/registrationValidation.ts</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>app/composables/useRegistrationDialog.ts</affectedPath><affectedPath>server/utils/registrationDb.ts</affectedPath><affectedPath>app/components/AndroidBadge.vue</affectedPath><affectedPath>app/components/AppIcon.vue</affectedPath><affectedPath>app/components/RegistrationForm.vue</affectedPath><affectedPath>deploy/nginx-blut24.conf</affectedPath><affectedPath>app/components/SectionProof.vue</affectedPath><commitId>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</commitId><timestamp>1785227601000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>landing: modal registration, value-led proof band, autocomplete fix, APK live

- Registration moved into a native &lt;dialog&gt; modal driven from every CTA, with
  focus trap/return, scroll lock, backdrop + ESC dismissal, full-screen sheet on
  mobile and prefers-reduced-motion respected.
- Replaced the data-source stats ("Quelle: Bundes-Klinik-Atlas", 293, 906) with
  three statements of what the product actually does. No invented metrics: the
  only figure left is the real 1.581 Klinik-Atlas count that was already there.
- Fixed the autocomplete staying open after a clinic was picked. Root cause was
  watch(query): selecting wrote the label back into the field, which the watcher
  read as a new search and reopened the list ~220ms later. The input is now
  :value + @input so a programmatic write cannot be a search intent, with a
  pendingQuery flag gating every path that opens the list.
- Removed Anrede end-to-end. The DB column is deliberately NOT migrated: it keeps
  its NOT NULL DEFAULT '' so inserts that omit it stay valid on existing databases.
- Android badge switched live: the APK is published at
  https://blut24.com/downloads/blut24-mobile.apk and served from disk by nginx
  with the correct package MIME type.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 10:33:21 +0200</date><id>9d957078b237f5dd9f22e2d14badac3ff8e33bd6</id><msg>landing: modal registration, value-led proof band, autocomplete fix, APK live</msg><path><editType>edit</editType><file>app/components/AppIcon.vue</file></path><path><editType>edit</editType><file>app/components/SectionHero.vue</file></path><path><editType>edit</editType><file>app/components/SiteFooter.vue</file></path><path><editType>edit</editType><file>app/components/SiteHeader.vue</file></path><path><editType>edit</editType><file>server/utils/registrationValidation.ts</file></path><path><editType>edit</editType><file>app/app.vue</file></path><path><editType>edit</editType><file>app/components/SectionCourier.vue</file></path><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>deploy/README.md</file></path><path><editType>edit</editType><file>app/components/RegistrationForm.vue</file></path><path><editType>add</editType><file>.idea/vcs.xml</file></path><path><editType>edit</editType><file>app/components/SectionProof.vue</file></path><path><editType>add</editType><file>app/components/RegistrationDialog.vue</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>edit</editType><file>app/components/SectionApp.vue</file></path><path><editType>edit</editType><file>app/pages/datenschutz.vue</file></path><path><editType>edit</editType><file>deploy/nginx-blut24.conf</file></path><path><editType>add</editType><file>app/composables/useRegistrationDialog.ts</file></path><path><editType>edit</editType><file>server/api/registration/submit.post.ts</file></path><path><editType>edit</editType><file>app/components/SectionRegistration.vue</file></path><path><editType>edit</editType><file>server/utils/registrationDb.ts</file></path><path><editType>edit</editType><file>app/components/AndroidBadge.vue</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>6</number><url>https://jenkins.younex.de/job/blut24-landing/6/</url></nextBuild><previousBuild><number>4</number><url>https://jenkins.younex.de/job/blut24-landing/4/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>4</buildNumber><marked><SHA1>88fb8db79ff790ff6f298d61b279dade9abc8b3b</SHA1><branch><SHA1>88fb8db79ff790ff6f298d61b279dade9abc8b3b</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>88fb8db79ff790ff6f298d61b279dade9abc8b3b</SHA1><branch><SHA1>88fb8db79ff790ff6f298d61b279dade9abc8b3b</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>88fb8db79ff790ff6f298d61b279dade9abc8b3b</SHA1><branch><SHA1>88fb8db79ff790ff6f298d61b279dade9abc8b3b</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#4 88fb8db</displayName><duration>26252</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #4 88fb8db</fullDisplayName><id>4</id><keepLog>false</keepLog><number>4</number><queueId>5446</queueId><result>SUCCESS</result><timestamp>1785223605276</timestamp><url>https://jenkins.younex.de/job/blut24-landing/4/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/components/SiteFooter.vue</affectedPath><affectedPath>app/components/AndroidBadge.vue</affectedPath><affectedPath>app/components/SectionApp.vue</affectedPath><commitId>88fb8db79ff790ff6f298d61b279dade9abc8b3b</commitId><timestamp>1785223594000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>landing: proper Android download badge, reused in the footer

Replaces the flat outline-icon button with a badge in the visual language people
actually recognise: dark pill, mark on the left, small kicker over a bold line,
and the Android robot drawn inline in its own green (#3DDC84).

Deliberately NOT the official "Get it on Google Play" badge. That artwork is
Google's trademark and licensed only for links pointing at a Play Store listing;
this link is a direct APK download, so copying it would be both a trademark
problem and a false claim to the visitor. Same recognition, honest wording
("Direkt-Download / Android APK").

Extracted as AndroidBadge.vue with a `compact` variant so the app section and the
footer cannot drift apart. Until an APK exists the badge renders as a disabled
span (not a dead link) with its own aria-label; set `available` to switch it on.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 09:26:34 +0200</date><id>88fb8db79ff790ff6f298d61b279dade9abc8b3b</id><msg>landing: proper Android download badge, reused in the footer</msg><path><editType>add</editType><file>app/components/AndroidBadge.vue</file></path><path><editType>edit</editType><file>app/components/SiteFooter.vue</file></path><path><editType>edit</editType><file>app/components/SectionApp.vue</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>5</number><url>https://jenkins.younex.de/job/blut24-landing/5/</url></nextBuild><previousBuild><number>3</number><url>https://jenkins.younex.de/job/blut24-landing/3/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause><cause _class='hudson.triggers.SCMTrigger$SCMTriggerCause'><shortDescription>Started by an SCM change</shortDescription></cause><cause _class='hudson.triggers.SCMTrigger$SCMTriggerCause'><shortDescription>Started by an SCM change</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>3</buildNumber><marked><SHA1>3365492e0eebdab580a2e8c2b0c0eea00e89d606</SHA1><branch><SHA1>3365492e0eebdab580a2e8c2b0c0eea00e89d606</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>3365492e0eebdab580a2e8c2b0c0eea00e89d606</SHA1><branch><SHA1>3365492e0eebdab580a2e8c2b0c0eea00e89d606</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>3365492e0eebdab580a2e8c2b0c0eea00e89d606</SHA1><branch><SHA1>3365492e0eebdab580a2e8c2b0c0eea00e89d606</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#3 3365492</displayName><duration>32350</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #3 3365492</fullDisplayName><id>3</id><keepLog>false</keepLog><number>3</number><queueId>5444</queueId><result>SUCCESS</result><timestamp>1785220314292</timestamp><url>https://jenkins.younex.de/job/blut24-landing/3/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>.env.example</affectedPath><affectedPath>server/utils/registrationValidation.ts</affectedPath><affectedPath>server/api/registration/submit.post.ts</affectedPath><commitId>d91c3a46ec2b1420a63ba8ecab63a9cb21593616</commitId><timestamp>1785219798000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>registration: operator test domains may register for any clinic

Adds REGISTRATION_TEST_DOMAINS (comma-separated). Addresses on those domains skip
the "e-mail domain belongs to the chosen Standort" check, so the flow can be
exercised end-to-end against arbitrary clinics.

That check is the only thing preventing a stranger from registering someone else's
hospital, so it is never relaxed for real users. The bypass therefore:
  - does not exist at all when the variable is empty or unset (the default)
  - never counts as domain-verified (domain_verified stays 0)
  - forces needs_manual_approval and prefixes the note with [TESTREGISTRIERUNG via &lt;domain&gt;]
  - leaves the freemail blocklist and the per-Standort duplicate guard intact

Verified: younex.de/it-beratung.it accepted for a non-matching Charité Standort;
a non-whitelisted business domain and a freemail address both still rejected; and
with the variable unset younex.de is rejected again.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 08:23:18 +0200</date><id>d91c3a46ec2b1420a63ba8ecab63a9cb21593616</id><msg>registration: operator test domains may register for any clinic</msg><path><editType>edit</editType><file>server/utils/registrationValidation.ts</file></path><path><editType>edit</editType><file>server/api/registration/submit.post.ts</file></path><path><editType>edit</editType><file>.env.example</file></path></item><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>Jenkinsfile</affectedPath><affectedPath>deploy/deploy.sh</affectedPath><commitId>3365492e0eebdab580a2e8c2b0c0eea00e89d606</commitId><timestamp>1785220306000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>ci: move the deploy concurrency guard from Jenkins to the target

Every build after the first sat in the queue as a BlockedItem and never started
until Jenkins was restarted - observed three times on this controller. The only
plausible cause was disableConcurrentBuilds(), so it is removed.

The race it guarded against is two deploys swapping the `current` symlink at the
same time. That resource lives on the TARGET, not on Jenkins, so deploy.sh now
takes an flock on /var/lock/blut24-landing-deploy.lock for the whole run. That is
strictly better: it also covers deploys started by hand or from another controller,
which the Jenkins-side option never did.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 08:31:46 +0200</date><id>3365492e0eebdab580a2e8c2b0c0eea00e89d606</id><msg>ci: move the deploy concurrency guard from Jenkins to the target</msg><path><editType>edit</editType><file>Jenkinsfile</file></path><path><editType>edit</editType><file>deploy/deploy.sh</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>4</number><url>https://jenkins.younex.de/job/blut24-landing/4/</url></nextBuild><previousBuild><number>2</number><url>https://jenkins.younex.de/job/blut24-landing/2/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause><cause _class='hudson.triggers.SCMTrigger$SCMTriggerCause'><shortDescription>Started by an SCM change</shortDescription></cause><cause _class='hudson.triggers.SCMTrigger$SCMTriggerCause'><shortDescription>Started by an SCM change</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>2</buildNumber><marked><SHA1>679906e5db227bfa0d8a3ca5800418269ab474e8</SHA1><branch><SHA1>679906e5db227bfa0d8a3ca5800418269ab474e8</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>679906e5db227bfa0d8a3ca5800418269ab474e8</SHA1><branch><SHA1>679906e5db227bfa0d8a3ca5800418269ab474e8</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>679906e5db227bfa0d8a3ca5800418269ab474e8</SHA1><branch><SHA1>679906e5db227bfa0d8a3ca5800418269ab474e8</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#2 679906e</displayName><duration>32750</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #2 679906e</fullDisplayName><id>2</id><keepLog>false</keepLog><number>2</number><queueId>5442</queueId><result>SUCCESS</result><timestamp>1785218932906</timestamp><url>https://jenkins.younex.de/job/blut24-landing/2/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>deploy/deploy.sh</affectedPath><affectedPath>deploy/bootstrap-server.sh</affectedPath><affectedPath>deploy/ecosystem.config.cjs</affectedPath><commitId>679906e5db227bfa0d8a3ca5800418269ab474e8</commitId><timestamp>1785218244000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@logyou.de</authorEmail><comment>deploy: pin Node v22.22.3, self-heal the install, realign bootstrap to ISPConfig

The first Jenkins build logged EBADENGINE warnings: several transitive deps
(@babel/*, undici) require Node ^22.18 / &gt;=22.19 while the pin was v22.14.0.
Bumped to v22.22.3 — same NODE_MODULE_VERSION 127, so the better-sqlite3 native
build stays compatible and no rebuild-from-scratch is forced.

deploy.sh now runs `nvm install` rather than `nvm use`, so bumping the pin in git
is sufficient; previously a new version would have failed the deploy outright with
"N/A: version not yet installed". It also ensures pm2 exists for that Node build.

bootstrap-server.sh still carried the pre-ISPConfig layout and, worse, would have
written a standalone nginx vhost with the same server_name as the ISPConfig-generated
one - a collision that ISPConfig would regenerate away. It now creates the real
layout (code in the docroot, secrets and SQLite in the site's private/ dir) and only
REPORTS on the proxy block instead of fighting the panel for ownership.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 07:57:24 +0200</date><id>679906e5db227bfa0d8a3ca5800418269ab474e8</id><msg>deploy: pin Node v22.22.3, self-heal the install, realign bootstrap to ISPConfig</msg><path><editType>edit</editType><file>deploy/deploy.sh</file></path><path><editType>edit</editType><file>deploy/bootstrap-server.sh</file></path><path><editType>edit</editType><file>deploy/ecosystem.config.cjs</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><nextBuild><number>3</number><url>https://jenkins.younex.de/job/blut24-landing/3/</url></nextBuild><previousBuild><number>1</number><url>https://jenkins.younex.de/job/blut24-landing/1/</url></previousBuild></build><build _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>1</buildNumber><marked><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><branch><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><branch><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><branch><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#1 091770a</displayName><duration>30254</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #1 091770a</fullDisplayName><id>1</id><keepLog>false</keepLog><number>1</number><queueId>5439</queueId><result>SUCCESS</result><timestamp>1785192514932</timestamp><url>https://jenkins.younex.de/job/blut24-landing/1/</url><inProgress>false</inProgress><nextBuild><number>2</number><url>https://jenkins.younex.de/job/blut24-landing/2/</url></nextBuild></build><color>blue</color><firstBuild _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>1</buildNumber><marked><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><branch><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><branch><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><branch><SHA1>091770a6c5138113b51582d5bd5e86c607cbe262</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#1 091770a</displayName><duration>30254</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #1 091770a</fullDisplayName><id>1</id><keepLog>false</keepLog><number>1</number><queueId>5439</queueId><result>SUCCESS</result><timestamp>1785192514932</timestamp><url>https://jenkins.younex.de/job/blut24-landing/1/</url><inProgress>false</inProgress><nextBuild><number>2</number><url>https://jenkins.younex.de/job/blut24-landing/2/</url></nextBuild></firstBuild><healthReport><description>Build stability: No recent builds failed.</description><iconClassName>icon-health-80plus</iconClassName><iconUrl>health-80plus.png</iconUrl><score>100</score></healthReport><keepDependencies>false</keepDependencies><lastBuild _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>15</buildNumber><marked><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#15 49f3d63</displayName><duration>30604</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #15 49f3d63</fullDisplayName><id>15</id><keepLog>false</keepLog><number>15</number><queueId>5476</queueId><result>SUCCESS</result><timestamp>1785257388243</timestamp><url>https://jenkins.younex.de/job/blut24-landing/15/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/locales/de.ts</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>server/api/registration/confirm.post.ts</affectedPath><affectedPath>server/utils/i18n.ts</affectedPath><affectedPath>app/locales/en.ts</affectedPath><affectedPath>README.md</affectedPath><commitId>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</commitId><timestamp>1785257378000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval

HANDOFF §4 (ERP repo, reference/blut24/HANDOFF.md). needs_manual_approval gated
nothing: couriers and no-domain clinics — exactly the registrations nothing
could verify — were auto-onboarded into iDempiere with live credentials mailed,
while form, confirmation mail and welcome mail promised a manual review.
confirm.post.ts now skips onboarding for them and records erp_status
'manual-approval'; the operator provisions them by hand. Verified and test
registrations stay fully automatic.

Copy made truthful: the test-domain notice no longer claims "marked for manual
approval" (test domains auto-activate; they are marked internally as test
registrations), and the manual-review texts are courier-neutral instead of
explaining a clinic-only domain lookup.

alreadyConfirmed now returns credentialsSent, read from the stored ERP payload
(setErpResult persists it).

README: the ERP auth section described a Bearer scheme the code never uses —
the token travels as the logship_it cookie, and the ERP's send-credentials
route is now gated on exact equality with the instance's IDEMPIERETOKEN, so
ERP_SERVICE_TOKEN must be exactly that value.

test-registration.mjs: courier confirm asserts needsManualApproval,
credentialsSent=false and erp_status 'manual-approval' (83/83 green).

Co-Authored-By: Claude Opus 4.8 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 18:49:38 +0200</date><id>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</id><msg>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval</msg><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>edit</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>server/api/registration/confirm.post.ts</file></path><path><editType>edit</editType><file>server/utils/i18n.ts</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><previousBuild><number>14</number><url>https://jenkins.younex.de/job/blut24-landing/14/</url></previousBuild></lastBuild><lastCompletedBuild _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>15</buildNumber><marked><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#15 49f3d63</displayName><duration>30604</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #15 49f3d63</fullDisplayName><id>15</id><keepLog>false</keepLog><number>15</number><queueId>5476</queueId><result>SUCCESS</result><timestamp>1785257388243</timestamp><url>https://jenkins.younex.de/job/blut24-landing/15/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/locales/de.ts</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>server/api/registration/confirm.post.ts</affectedPath><affectedPath>server/utils/i18n.ts</affectedPath><affectedPath>app/locales/en.ts</affectedPath><affectedPath>README.md</affectedPath><commitId>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</commitId><timestamp>1785257378000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval

HANDOFF §4 (ERP repo, reference/blut24/HANDOFF.md). needs_manual_approval gated
nothing: couriers and no-domain clinics — exactly the registrations nothing
could verify — were auto-onboarded into iDempiere with live credentials mailed,
while form, confirmation mail and welcome mail promised a manual review.
confirm.post.ts now skips onboarding for them and records erp_status
'manual-approval'; the operator provisions them by hand. Verified and test
registrations stay fully automatic.

Copy made truthful: the test-domain notice no longer claims "marked for manual
approval" (test domains auto-activate; they are marked internally as test
registrations), and the manual-review texts are courier-neutral instead of
explaining a clinic-only domain lookup.

alreadyConfirmed now returns credentialsSent, read from the stored ERP payload
(setErpResult persists it).

README: the ERP auth section described a Bearer scheme the code never uses —
the token travels as the logship_it cookie, and the ERP's send-credentials
route is now gated on exact equality with the instance's IDEMPIERETOKEN, so
ERP_SERVICE_TOKEN must be exactly that value.

test-registration.mjs: courier confirm asserts needsManualApproval,
credentialsSent=false and erp_status 'manual-approval' (83/83 green).

Co-Authored-By: Claude Opus 4.8 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 18:49:38 +0200</date><id>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</id><msg>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval</msg><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>edit</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>server/api/registration/confirm.post.ts</file></path><path><editType>edit</editType><file>server/utils/i18n.ts</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><previousBuild><number>14</number><url>https://jenkins.younex.de/job/blut24-landing/14/</url></previousBuild></lastCompletedBuild><lastStableBuild _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>15</buildNumber><marked><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#15 49f3d63</displayName><duration>30604</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #15 49f3d63</fullDisplayName><id>15</id><keepLog>false</keepLog><number>15</number><queueId>5476</queueId><result>SUCCESS</result><timestamp>1785257388243</timestamp><url>https://jenkins.younex.de/job/blut24-landing/15/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/locales/de.ts</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>server/api/registration/confirm.post.ts</affectedPath><affectedPath>server/utils/i18n.ts</affectedPath><affectedPath>app/locales/en.ts</affectedPath><affectedPath>README.md</affectedPath><commitId>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</commitId><timestamp>1785257378000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval

HANDOFF §4 (ERP repo, reference/blut24/HANDOFF.md). needs_manual_approval gated
nothing: couriers and no-domain clinics — exactly the registrations nothing
could verify — were auto-onboarded into iDempiere with live credentials mailed,
while form, confirmation mail and welcome mail promised a manual review.
confirm.post.ts now skips onboarding for them and records erp_status
'manual-approval'; the operator provisions them by hand. Verified and test
registrations stay fully automatic.

Copy made truthful: the test-domain notice no longer claims "marked for manual
approval" (test domains auto-activate; they are marked internally as test
registrations), and the manual-review texts are courier-neutral instead of
explaining a clinic-only domain lookup.

alreadyConfirmed now returns credentialsSent, read from the stored ERP payload
(setErpResult persists it).

README: the ERP auth section described a Bearer scheme the code never uses —
the token travels as the logship_it cookie, and the ERP's send-credentials
route is now gated on exact equality with the instance's IDEMPIERETOKEN, so
ERP_SERVICE_TOKEN must be exactly that value.

test-registration.mjs: courier confirm asserts needsManualApproval,
credentialsSent=false and erp_status 'manual-approval' (83/83 green).

Co-Authored-By: Claude Opus 4.8 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 18:49:38 +0200</date><id>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</id><msg>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval</msg><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>edit</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>server/api/registration/confirm.post.ts</file></path><path><editType>edit</editType><file>server/utils/i18n.ts</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><previousBuild><number>14</number><url>https://jenkins.younex.de/job/blut24-landing/14/</url></previousBuild></lastStableBuild><lastSuccessfulBuild _class='org.jenkinsci.plugins.workflow.job.WorkflowRun'><action _class='hudson.model.CauseAction'><cause _class='com.cloudbees.jenkins.GitHubPushCause'><shortDescription>Started by GitHub push by younex1</shortDescription></cause></action><action></action><action _class='org.jenkinsci.plugins.workflow.libs.LibrariesAction'></action><action></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>15</buildNumber><marked><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain></buildsByBranchName><lastBuiltRevision><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><branch><SHA1>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/younex1/blut24-landing.git</remoteUrl><scmName></scmName></action><action></action><action _class='org.jenkinsci.plugins.workflow.cps.EnvActionImpl'></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><action _class='org.jenkinsci.plugins.pipeline.modeldefinition.actions.RestartDeclarativePipelineAction'></action><action></action><action _class='org.jenkinsci.plugins.workflow.job.views.FlowGraphAction'></action><action></action><action></action><action></action><building>false</building><displayName>#15 49f3d63</displayName><duration>30604</duration><estimatedDuration>28038</estimatedDuration><fullDisplayName>blut24-landing #15 49f3d63</fullDisplayName><id>15</id><keepLog>false</keepLog><number>15</number><queueId>5476</queueId><result>SUCCESS</result><timestamp>1785257388243</timestamp><url>https://jenkins.younex.de/job/blut24-landing/15/</url><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>app/locales/de.ts</affectedPath><affectedPath>scripts/test-registration.mjs</affectedPath><affectedPath>server/api/registration/confirm.post.ts</affectedPath><affectedPath>server/utils/i18n.ts</affectedPath><affectedPath>app/locales/en.ts</affectedPath><affectedPath>README.md</affectedPath><commitId>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</commitId><timestamp>1785257378000</timestamp><author><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></author><authorEmail>info@younex.de</authorEmail><comment>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval

HANDOFF §4 (ERP repo, reference/blut24/HANDOFF.md). needs_manual_approval gated
nothing: couriers and no-domain clinics — exactly the registrations nothing
could verify — were auto-onboarded into iDempiere with live credentials mailed,
while form, confirmation mail and welcome mail promised a manual review.
confirm.post.ts now skips onboarding for them and records erp_status
'manual-approval'; the operator provisions them by hand. Verified and test
registrations stay fully automatic.

Copy made truthful: the test-domain notice no longer claims "marked for manual
approval" (test domains auto-activate; they are marked internally as test
registrations), and the manual-review texts are courier-neutral instead of
explaining a clinic-only domain lookup.

alreadyConfirmed now returns credentialsSent, read from the stored ERP payload
(setErpResult persists it).

README: the ERP auth section described a Bearer scheme the code never uses —
the token travels as the logship_it cookie, and the ERP's send-credentials
route is now gated on exact equality with the instance's IDEMPIERETOKEN, so
ERP_SERVICE_TOKEN must be exactly that value.

test-registration.mjs: courier confirm asserts needsManualApproval,
credentialsSent=false and erp_status 'manual-approval' (83/83 green).

Co-Authored-By: Claude Opus 4.8 &lt;noreply@anthropic.com&gt;
</comment><date>2026-07-28 18:49:38 +0200</date><id>49f3d63e2f1169fda0b321572605cb5f9b6fcd5e</id><msg>registration: keep the manual-review promise — gate ERP onboarding on needs_manual_approval</msg><path><editType>edit</editType><file>scripts/test-registration.mjs</file></path><path><editType>edit</editType><file>app/locales/en.ts</file></path><path><editType>edit</editType><file>README.md</file></path><path><editType>edit</editType><file>app/locales/de.ts</file></path><path><editType>edit</editType><file>server/api/registration/confirm.post.ts</file></path><path><editType>edit</editType><file>server/utils/i18n.ts</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://jenkins.younex.de/user/info</absoluteUrl><fullName>info</fullName></culprit><inProgress>false</inProgress><previousBuild><number>14</number><url>https://jenkins.younex.de/job/blut24-landing/14/</url></previousBuild></lastSuccessfulBuild><nextBuildNumber>16</nextBuildNumber><property _class='com.coravy.hudson.plugins.github.GithubProjectProperty'></property><property _class='org.jenkinsci.plugins.workflow.job.properties.PipelineTriggersJobProperty'></property><property _class='jenkins.model.BuildDiscarderProperty'></property><concurrentBuild>true</concurrentBuild><inQueue>false</inQueue><resumeBlocked>false</resumeBlocked></workflowJob>