Commit Graph
2069 Commits
Author SHA1 Message Date
Jeppe BandTruck Wash Agent 82c95d32c0 Mock /ping in driverAuth e2e so the ConnectivityIssue overlay does not hide the driver entry point (#266)
🤖 Generated with [OpenClaw](https://openclaw.ai)

## Why

`tests/e2e/driverAuth.spec.ts` (added in #265) failed across 4 full-E2E
matrix jobs on master:

- `E2E-full-Chromium-mobile-subuser-shard-1-of-1` (job 93176119977)
- `E2E-full-Chromium-desktop-subuser-shard-1-of-1` (job 93176119967)
- `E2E-full-Firefox-mobile-subuser-shard-1-of-1` (job 93176119955)
- `E2E-full-WebKit-mobile-subuser-shard-1-of-1` (job 93176119945)

Root cause: `/login` wraps the LoginForm in ConnectivityIssue, which
renders an overlay when GET /ping does not return ok. In the full
subuser E2E matrix driverAuth.spec.ts runs first; the api backend may
not yet have answered /ping by then, so the overlay covered the page and
`driver-login-link` was not visible. Targeted E2E (driverAuth only)
passed because the api was warm by then.

## Fix

Add a `test.beforeEach` that mocks `/ping` to return `{ data: { ok: true
} }`, mirroring the pattern already used in
`superuser-department-lanes.spec.ts`. With /ping short-circuited,
ConnectivityIssue renders the LoginForm slot and `driver-login-link` is
reachable.

## Risk

Low. The mock only affects this spec; other suites and the live api are
untouched. driverAuth previously passed under targeted E2E, so the page
logic itself is fine — this just removes a race against the api health
check at the top of the subuser test list.

---------

Co-authored-by: Truck Wash Agent <agent@copenhagentruckwash.local>
2026-08-09 15:37:13 +02:00
Jeppe BandTruck Wash Agent d4f92cd259 Surface driver login on /login and /; make SubuserLogin responsive (#265)
## Why

Drivers (sub-users) could only reach `/login/driver` via the direct URL
— there was no UI affordance anywhere else. They had to know the URL or
be sent a link by their admin. Mobile / tablet users had no obvious path
to the driver login either.

## What changed

- `src/components/forms/auth/LoginForm.vue` — Add a clearly-clickable
**Driver login** button below the existing "Login with QR code" link.
Distinct color (`#1584BC`) and a truck icon separate it from the primary
customer login. Test ID `driver-login-link`, ID `driver-login-button`.
The button is reachable on every viewport (44px+ touch target, no
horizontal scroll on mobile).
- `src/views/pages/LandingPage.vue` — Add a secondary **driver entry**
block below the customer login form, in a tinted container (`#F2F8FC`
with `#BFE0EF` border) with the intro "Are you a driver? Log in here to
register a wash." Test ID `landing-driver-entry` /
`landing-driver-login-link`.
- `src/views/auth/SubuserLogin.vue` — Make the page responsive:
  - **Desktop (>1024px):** 33%/67% sidebar + main (unchanged).
  - **Tablet (≤1024px):** 25%/75% tighter split, smaller sidebar title.
- **Mobile (≤768px):** Stack the sidebar above main (full-width 140px
header band) so it never forces a horizontal scroll.
- `src/i18n/source/{global/shared,da,en,de,no,sv}/.../auth/index.json` —
Add `auth.driver_login_button` and `auth.driver_entry_intro` in 5
locales. Run `npm run i18n:v2:compile` to regenerate the v2 bundle.
- `tests/e2e/driverAuth.spec.ts` — New E2E suite covering:
  - `/login` shows the driver login button on desktop and mobile.
  - `/` shows the driver entry block.
- Clicking either entry navigates to `/login/driver` and the form is
usable (inputs reachable, submit button visible) on mobile.

## Verification

- `npx eslint` — clean for changed files.
- `npm run i18n:v2:check` — green after `i18n:v2:compile`.

## Caveats

- New `.driver-entry` and `.driver-login-link` styles are scoped to the
components; if a global theme override is required, lift to a shared
SCSS partial in a follow-up.
- The driver login button is placed below the customer login in the
form. On very tall mobile viewports it may sit below the fold; in
practice the form fits in the first scroll, but worth watching in
production analytics.

🤖 Generated with [OpenClaw](https://openclaw.ai)

---------

Co-authored-by: Truck Wash Agent <agent@copenhagentruckwash.local>
2026-08-09 01:58:54 +02:00
6b44835347 Surface XL vask accept/compare/link/deny actions and i18n labels (#263)
## Why

In the superuser fakturaer-periode selvvask view, XL vask rows were
missing usable controls. Accept/Deny existed but **Compare** and
**Link** did not, so reviewers had no way to compare candidate orders or
attach by ID without dropping to raw API calls. Additionally, several
status labels in `getAutomationLabel` were hardcoded Danish strings —
they did not respect i18n or the da/en/de/no/sv locale files.

A legacy stub in `XLVaskUsageLog.vue` (`<template v-if="usage.WashItems
&& 1 === 2">`) permanently disabled the per-row wash items display.

## What changed


`src/components/displays/department/pos/sync/xlvaskUsageOrdersTable.vue`:
- New **Compare** button — `<b-modal>` side-by-side price view using
existing `duplicates` + `doesObjectHaveExactMatch`. Disabled when no
duplicates. Test IDs `xlvask-compare-{id}` and `xlvask-compare-modal`.
- New **Link** button — Swal numeric prompt with regex validator →
reuses `runReviewDecision(object, "attach_order", { orderId })`. Test ID
`xlvask-automation-link-{id}`.
- All four actions (Accept / Compare / Link / Deny / Ignore) sit in a
single horizontal flex-wrap button group inside the existing
`hasAutomationState` card, gated on `allowReviewActions &&
isAutomationActionable(object)`.
- Replaced 6 hardcoded Danish strings in `getAutomationLabel` with i18n
calls: `states.suggested_*`, `states.auto_accepted_*`,
`states.accepted_*`.

`src/i18n/source/global/shared/invoicing_period/xlvask_autopilot.json`
(and the 5 locale overrides) — added:
- `actions.compare`, `actions.link`
- `actions.compare_modal_title`, `actions.compare_modal_close`
- `actions.link_prompt_title`, `actions.link_prompt_label`,
`actions.link_prompt_invalid`
- `states.suggested_create_order`, `states.suggested_attach_order`,
`states.auto_accepted_create`, `states.auto_accepted_attach`,
`states.accepted_create`, `states.accepted_attach`

Regenerated the i18n bundle (`src/i18n/generated/*-v2.json`).


`src/views/dashboards/superUserDashboard/vehicle/displays/XLVaskUsageLog.vue`:
- Restored wash-items display behind `<details>/<summary>` collapsible
(was stubbed with `1 === 2`).

## Verification

- `npx eslint` — clean.
- `npm run i18n:v2:check` — all 4 sub-checks green.

Pre-existing vitest failures in `xlvask-usage-amount-cache`
(localStorage undefined in jsdom) are unrelated to these changes and
exist on master.

## Risk

- Surface-only changes inside existing automation card; no new
endpoints, no new permissions, no data shape changes. Backwards
compatible.

🤖 Generated with [OpenClaw](https://openclaw.ai)

---------

Co-authored-by: XL Vask Subagent <agent@truckwash.dk>
Co-authored-by: Truck Wash Agent <agent@copenhagentruckwash.local>
2026-08-09 01:14:26 +02:00
Jeppe B 683196ddf5 Gate Fakturer nu on red flag count; expand customer card layout (#264)
## Why

1. The **Fakturer nu** button on the customer card in the superuser faktura-periode "Alle" view was firing even when the customer had multiple red flags — a footgun for superusers (the button shouldn't be one click away from a flagged customer).
2. Each customer card had a fixed `min-height: 68px` on its row and `overflow: hidden` on the identity block, so longer customer names were ellipsised and attribute chips were clipped. The user asked for taller cards with no internal scroll.

## What changed

### Original commit (`da35baa8`)

`src/views/dashboards/superUserDashboard/InvoicingBillingPeriod/views/InvoicingBillingPeriodViewAll.vue`:

- New helper `hasMultipleRedFlags(customer)` — true when `getCustomerActiveFlagCounts(customer).manual >= 2`.
- Button `v-if` now requires `!hasMultipleRedFlags(customer)`.
- When gated, an `is-danger is-light` "Gennemgå flag" tag replaces it so superusers see why.

### Follow-up commit (`8370ba81`) — card layout + chip discoverability

- `.period-customer-card` — `min-height: 9rem`.
- `.period-customer-card__row` — dropped fixed `min-height: 68px`; added explicit `grid-template-rows: auto auto auto auto` + `row-gap: 0.35rem` so the grid stretches naturally.
- `.period-customer-card__identity` — `overflow: hidden → visible`.
- Customer name — added `overflow-wrap: anywhere` so long names wrap instead of clipping.
- Removed internal scroll; the outer list scroll still works.
- Sort billing-type chips deterministically (billing first, operational, review) so chip order is stable regardless of API response shape.
- Add view_friendly_name i18n key for `invoice_per_order`.
- Widen `invoicing-period.smoke.spec.js` mobile card-height tolerance from 3px → 32px (with explanatory comment) for the taller-cards-no-internal-scroll design.

### Follow-up commit (`4f5363fa`) — Playwright strict-mode collision

The chip-mirroring change in the review-detail header shared the same data-testid pattern (`invoicing-period-customer-attributes-{n}`) as the queue card, so the Playwright test failed with `strict mode violation: ... resolved to 2 elements` whenever a flagged customer was selected.

- Added a `scope` prop to `InvoicingBillingPeriodCustomerAttributes` (default `'queue'`, accepts `'review-detail'`). When scope is review-detail, the wrapper and per-chip test-ids are namespaced, so both instances coexist.

## Verification

- `npx eslint` — clean.
- `npm run i18n:v2:check` — pass.
- `vite build` — pass.

## Caveats / follow-ups (out of scope, not blocking)

- `invoicing_period.xlvask_autopilot` — fallback Danish strings ("Gennemgå flag") aren't yet in `invoicingPeriodTranslation.js`.
- Red-flag threshold `>= 2` is hard-coded; promote to a config ref if you want it tunable.
- `InvoicingBillingPeriodCustomerAttributes` still has internal `height: 2.45rem; overflow: hidden` on attribute chips — separate cleanup.

## Risk

- Surface-only CSS + 1 v-if guard; no data shape changes, no API changes, no permission changes. Behaviour change is strictly "Fakturer nu is hidden on multi-flag customers with an explanatory tag in its place".

🤖 Generated with [OpenClaw](https://openclaw.ai)
2026-08-09 00:43:30 +02:00
Jeppe BandJeppe Bundgaard 1548ae8cd5 Add multiple select customer product price recalculation (#261)
Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-08-04 16:13:23 +00:00
Jeppe B fd8b896c56 Add Superuser XL Vask AI automation controls (#260) 2026-08-04 11:46:20 +02:00
Jeppe B 2e95608b05 Enable one-time release recovery fast path (#259)
## Scope

Temporarily skips the multi-hour full cross-browser matrix for exactly
one protected-master push: the immediate child of
`d393c8c17508c46c61e97bd834a2e407367c69eb`.

All quality, build, unit, PR E2E, Required CI, release build, live
gates, exact-SHA updater recording, and readback checks remain
mandatory. The exception expires automatically because every later push
has a different `github.event.before`.

## Verification

- `git diff --check`
- Prettier check for `.github/workflows/tests.yml`
- Exact diff against current `origin/master`
2026-08-03 15:03:10 +00:00
Jeppe B d393c8c175 Fix release version credential fallback (#258)
## Summary
- fall back to the existing scoped `RELEASE_MANAGER_GATE_TOKEN` when
`SERVER_UPDATE_TOKEN` is absent
- record the exact frontend SHA through the release-gate endpoint, then
independently read it back
- preserve the legacy dedicated-token path when it is configured
- carry the scoped credential and exact run-attempt build ID through
normal releases, rollback recovery, and restore-on-failure

## Dependency
Depends on backend PR copenhagentruckwash/api#342 being merged and
deployed before this PR is merged.

## Verification
- focused release-gate updater test: 1 passed
- direct exact-SHA update/readback execution passed
- ESLint passed for changed JavaScript/tests
- Prettier passed for both workflows and changed JavaScript/tests
- Node syntax and `git diff --check` passed

The existing broader cPanel release test is also updated; the local
cached dependency set cannot collect that file because `jszip` is
absent, so protected CI remains the full-suite authority.
2026-08-03 14:27:43 +00:00
Jeppe B 668e240e12 Surface XL-Vask autopilot in invoice period (#257)
Publish the revision-aware XL-Vask import status, certainty evidence, bounded run controls, and preview/apply workflow. Automatic production actions remain fail-closed behind backend readiness gates.
2026-08-03 15:46:03 +02:00
Jeppe B 0831d37d3c Stabilize self-serve loading skeleton release gate (#256)
Keep the mocked post-toggle image response pending long enough for every browser shard to observe the loading skeleton deterministically.
2026-08-03 14:31:57 +02:00
Jeppe B 60dff74507 Fix invoice preview i18n release gate (#255)
Use a statically discoverable invoice-preview translation key while preserving the off-period fallback.
2026-08-03 14:12:12 +02:00
Jeppe B f995440098 Align invoicing period review workspace (#251)
Keep review navigation, customer cards, metadata, date labels, and direct order-item tables aligned across desktop and responsive layouts.
2026-08-03 13:45:11 +02:00
Jeppe B 7a5ee1aa5b Fix invoice period tree review findings (#253)
## Summary
- preserve complete snapshot item payloads during inline edits and
reject partial text-field payloads
- force snapshot refreshes after parent/mutation changes with one
bounded recovery retry
- make legacy tree-action fallback create, confirm, and apply a fresh
compatible preview
- keep collection labeling localized and report the correct changed
count

## Verification
- focused object-tree and snapshot suites: 30 tests passed
- focused ESLint and `git diff --check` clean
- production build and selected-customer mocked Playwright flow passed
before final review fixes
- App Store Readiness and Qodana green on exact head; Automated Tests in
progress
- independent QA and reviewer gates: GO

Resolves all inline review threads on the current head.
2026-08-03 13:04:19 +02:00
Jeppe B 3639527b0e Stabilize invoice-period responsive layout assertion (#254)
Wait for WebKit to settle responsive layout boxes before asserting tablet and mobile positioning.
2026-08-03 12:54:45 +02:00
Jeppe B f4816124c2 Complete selected-customer invoice period tree (#252)
Add the complete selected-customer invoice collection tree, revision-bound actions, fallback handling, and focused frontend coverage.
2026-08-03 12:15:55 +02:00
Jeppe B 664b50d4ef Clarify customer login and invoice emails (#250)
Separate Pleno login email from e-conomic invoice email, make the login-email update flow authoritative and cache-safe, clear stale economic profile state, and add focused frontend coverage.
2026-08-03 10:43:53 +02:00
Jeppe B 1768f5a38e Restore invoicing period right rail layout (#249)
## What changed

- restore the desktop invoicing-period category groups as a vertical
right-hand rail
- use a 3:1 content-to-navigation split at desktop widths with
responsive stacking below 1024px
- size the inline month selector to the available content width with a
readable 32rem cap
- adapt the invoice review workspace to the narrower content region
- add unit contracts and browser geometry coverage for desktop, tablet,
and mobile

## Why

The grouped period categories had moved into a wide horizontal row,
leaving unused space on the right and constraining the period content.
The inline month picker was also too small to read comfortably.

## User impact

Superusers again see period categories in the right rail on desktop.
Compact layouts retain responsive navigation, and the review/object-tree
content avoids field wrapping when the main region becomes narrow.

## Validation

- 60/60 focused unit tests
- 30/30 full Chromium desktop invoicing-period browser tests
- 9/9 priority browser tests across Chromium desktop, tablet, and mobile
- ESLint
- production Vite build
- focused Prettier checks
- git diff check
2026-08-03 07:54:53 +00:00
Jeppe B f2453ba0a3 Restore expand-all control in invoice period object tree (#248)
Add a persistent recursive expand/collapse control above collected invoices and keep order-item quantity and price in the canonical editable field layout.
2026-08-03 09:03:57 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 7b769eeb24 Bump JetBrains/qodana-action from 2026.1.3 to 2026.2.0 (#246)
Bumps
[JetBrains/qodana-action](https://github.com/jetbrains/qodana-action)
from 2026.1.3 to 2026.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jetbrains/qodana-action/releases">JetBrains/qodana-action's
releases</a>.</em></p>
<blockquote>
<h2>v2026.2.0</h2>
<h2>Changelog</h2>
<ul>
<li>69c00ce 🐛 Fix azure release workflow husky error (<a
href="https://redirect.github.com/jetbrains/qodana-action/issues/604">#604</a>)</li>
<li>f4341f6 QD-14362 bump color able axios version to 1.15.2</li>
<li>97d17d6 QD-13746 pass Qodana exit code in action</li>
<li>cf5541e QD-12982 skip pull in action if arg is specified</li>
<li>f28920a :docs: Update qodana-maven-plugin version to 2026.1.3</li>
<li>1f6f293 QD-15472 bump tar dependency</li>
<li>e11337f QD-15410 check that in case of pr-mode: true the repository
checked out to source branch</li>
<li>8069c0f QD-15420 Warn about sanity problems in the summary posted in
the pull request comments</li>
<li>d37471b 🐛 QD-14507 Add title parameter to gh release create
command (<a
href="https://redirect.github.com/jetbrains/qodana-action/issues/593">#593</a>)</li>
<li>b588768 QD-15622 ⬆️ Update <code>qodana</code> to
<code>v2026.2.0</code> (<a
href="https://redirect.github.com/jetbrains/qodana-action/issues/611">#611</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/b588768b6e7e6da579e518bc584f79de0d243692"><code>b588768</code></a>
QD-15622 ⬆️ Update <code>qodana</code> to <code>v2026.2.0</code>
(<a
href="https://redirect.github.com/jetbrains/qodana-action/issues/611">#611</a>)</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/d37471b9ddca0747e9bfe9a631f3aa0635db24fa"><code>d37471b</code></a>
🐛 QD-14507 Add title parameter to gh release create command (<a
href="https://redirect.github.com/jetbrains/qodana-action/issues/593">#593</a>)</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/8069c0fbcfdcab755d68a4531756b461ceb0b2df"><code>8069c0f</code></a>
QD-15420 Warn about sanity problems in the summary posted in the pull
request...</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/e11337f2e389833df2bdbf47c8e82488384fb8c2"><code>e11337f</code></a>
QD-15410 check that in case of pr-mode: true the repository checked out
to so...</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/1f6f2932c4700773782c5632110dd112c2e1ba67"><code>1f6f293</code></a>
QD-15472 bump tar dependency</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/f28920a0646f05ed428ae22ce6e6e2a003ecade3"><code>f28920a</code></a>
:docs: Update qodana-maven-plugin version to 2026.1.3</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/cf5541e814e0b76d8700480aa04942d9c149c502"><code>cf5541e</code></a>
QD-12982 skip pull in action if arg is specified</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/97d17d64bd474d256c395f2e96bedde675e977d3"><code>97d17d6</code></a>
QD-13746 pass Qodana exit code in action</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/f4341f6ba3067fafa7cd79ce6f7a458db22ee0cf"><code>f4341f6</code></a>
QD-14362 bump color able axios version to 1.15.2</li>
<li><a
href="https://github.com/JetBrains/qodana-action/commit/69c00ce51f0310b330090dfc033ebdb51c1ba15b"><code>69c00ce</code></a>
🐛 Fix azure release workflow husky error (<a
href="https://redirect.github.com/jetbrains/qodana-action/issues/604">#604</a>)</li>
<li>See full diff in <a
href="https://github.com/jetbrains/qodana-action/compare/4861e015da555e86a72b862892aba6c2b93e6891...b588768b6e7e6da579e518bc584f79de0d243692">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=JetBrains/qodana-action&package-manager=github_actions&previous-version=2026.1.3&new-version=2026.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 06:24:39 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 391e0c8a6f Bump actions/setup-java from 5.6.0 to 5.7.0 (#247)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from
5.6.0 to 5.7.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-java/releases">actions/setup-java's
releases</a>.</em></p>
<blockquote>
<h2>v5.7.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix npm audit failures on releases/v5 by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1154">actions/setup-java#1154</a></li>
<li>Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1151">#1151</a>:
Fix missing wrapper cache distributions by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1153">actions/setup-java#1153</a></li>
<li>Deprecate legacy Adopt distributions in v5 by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1186">actions/setup-java#1186</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-java/compare/v5.6.0...v5.7.0">https://github.com/actions/setup-java/compare/v5.6.0...v5.7.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/setup-java/commit/b6effb05e454b25005698d916606bdc6ffcbf961"><code>b6effb0</code></a>
Deprecate legacy Adopt distributions in v5 (<a
href="https://redirect.github.com/actions/setup-java/issues/1186">#1186</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/e498d2a66a953492f322542257b22125c989b422"><code>e498d2a</code></a>
Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1151">#1151</a>:
Fix missing wrapper cache distributions (<a
href="https://redirect.github.com/actions/setup-java/issues/1153">#1153</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/6a3384db745932178632d0e22b2bd28cad1678e6"><code>6a3384d</code></a>
Fix npm audit failures on releases/v5 (<a
href="https://redirect.github.com/actions/setup-java/issues/1154">#1154</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/setup-java/compare/03ad4de0992f5dab5e18fcb136590ce7c4a0ac95...b6effb05e454b25005698d916606bdc6ffcbf961">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-java&package-manager=github_actions&previous-version=5.6.0&new-version=5.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 08:03:50 +02:00
Jeppe B 0149e06c42 Fix invoice period i18n release gate (#245)
Replace unreviewed dynamic invoice-period translation calls with a bounded literal-key contract and focused fallback coverage.
2026-08-03 07:04:48 +02:00
Jeppe B 832b362254 Redesign invoice period review workspace (#244)
Create an exception-first superuser invoice-period review workspace with responsive navigation, complete review states, and regression coverage.
2026-08-02 19:34:31 +02:00
Jeppe B eee9ba1c13 Fix localized forbidden assertions in full E2E (#243)
Use the stable localized forbidden-page contract in customer, subuser, and superuser denial tests while retaining the protected-action and zero-request assertions.
2026-08-02 12:24:36 +02:00
Jeppe B aaecffbdfa Finish Sæby demo registration and limited backoffice (#242)
Unify truckwash.dk Kundeoprettelse and QR traffic on the shared customer page, add protected registration UX, and complete the limited-backoffice demo flow.
2026-08-02 11:50:58 +02:00
Jeppe B 917c10c1d3 Fix mobile Stripe reader recovery action (#241)
## Summary
- keep the mobile Stripe terminal menu in normal document flow so it
cannot cover the reader recovery action
- preserve the existing desktop dropdown overlay behavior
- replace pre-existing dynamic subuser-access translations with direct
literal calls
- explicitly review Bird's bounded health-state translation signatures
in the full view-i18n gate

## Root causes
Exact master CI run `30484128661` exposed two deterministic failures:

1. All three attempts of `reader unavailable state is recoverable and
non-fatal` timed out because the open terminal dropdown intercepted
pointer events on `pos-stripe-no-readers`.
2. The full Chromium desktop/customer view-i18n gate rejected two
bounded Bird health-state signatures plus three pre-existing dynamic
subuser-access calls. The PR matrix did not run this full scanner.

## Verification
- exact Chromium mobile failing scenario: 1/1 passed
- Chromium mobile repeat stress: 5/5 passed
- exact full view-i18n scanner: 1/1 passed
- Bird configuration units: 5/5 passed
- Firefox mobile scenario: skipped by the existing project/browser gate
- ESLint: passed
- test Prettier check: passed
- `git diff --check`: passed
- Vite production build: passed
2026-08-02 09:42:47 +02:00
Jeppe B 14a0d65a01 fix(ci): unblock Bird frontend release (#239)
Link Bird status translations to existing aliases and modernize the POS automatic-capture visual contract with deterministic one-time completion assertions.
2026-07-29 21:22:34 +02:00
Jeppe B 468d436d3e Harden atomic cPanel release recovery (#238)
Adds exact-SHA cPanel release proof v2, atomic rollback restoration, and protected recovery gating.
2026-07-29 20:30:34 +02:00
Jeppe B c85a82b9ac feat(bird): add Control Plane configuration (#237)
Adds a safe Bird Control Plane configuration surface with read-only health, credential redaction, protected capability switches, canonical workspace support, and focused frontend coverage.

Required CI passed on head cc04117d6b against master 3de5215b5e.
2026-07-29 19:19:17 +02:00
Jeppe BandJeppe Bundgaard 3de5215b5e Fix Superuser invoicing registration field layout (#236)
## Summary
- Fixes Superuser invoicing period object-tree registration rows so
`reg_1`, `reg_2`, and `reg_3` labels/values no longer overlap in compact
rows.
- Lets composite registration fields auto-size, wraps long plate values
safely, and spans the full compact grid width on small containers.
- Adds a focused source-level regression contract and committed visual
before/after previews.

## Tests
- `npm run test:unit:single --
tests/unit/superuser-invoices-view.spec.js`
- `npm run build`

## Visual change previews

### View: Superuser invoicing period registration field
**Description:** Registration rows in the invoice-period object tree now
keep each registration label and value on distinct readable rows,
including compact mobile layout.

#### Mobile (390x844)
**Before:**
![Before mobile registration
overlap](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6a733a0023430929a3c130191c8015694f951a86/visual-previews/workboard-4505b9ab-registration-overlap/mobile-before.png)

**After:**
![After mobile registration
layout](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6a733a0023430929a3c130191c8015694f951a86/visual-previews/workboard-4505b9ab-registration-overlap/mobile-after.png)

#### Tablet (768x1024)
**Before:**
![Before tablet registration
overlap](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6a733a0023430929a3c130191c8015694f951a86/visual-previews/workboard-4505b9ab-registration-overlap/tablet-before.png)

**After:**
![After tablet registration
layout](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6a733a0023430929a3c130191c8015694f951a86/visual-previews/workboard-4505b9ab-registration-overlap/tablet-after.png)

#### Desktop (1440x900)
**Before:**
![Before desktop registration
overlap](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6a733a0023430929a3c130191c8015694f951a86/visual-previews/workboard-4505b9ab-registration-overlap/desktop-before.png)

**After:**
![After desktop registration
layout](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6a733a0023430929a3c130191c8015694f951a86/visual-previews/workboard-4505b9ab-registration-overlap/desktop-after.png)

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-29 14:26:04 +02:00
Jeppe B 5ffd471a45 Exchange one-time login grants in QR flow (#235)
## Summary

Updates the QR login view to consume the short-lived, one-time employee
login grants created by approved Pleno Control Plane
Conversations/Suggestions actions.

- reads generated grants from the URL fragment
- scrubs the bearer from the address bar before exchange
- exchanges the grant for a normal session token, then uses the existing
secure session-storage path
- preserves legacy token QR links
- validates exact URL origin and removes raw credential/QR logging
- prevents repeated scanner exchange attempts while one is in progress

## Visual change previews

No layout or styling changes. The visible flow changes only after
opening or scanning a grant:

- Before: one-time grant links were rejected as unknown QR content.
- After: the existing loader appears during exchange; invalid/expired
grants use the existing localized error dialog; successful grants
redirect through the existing login path.

## Verification

- focused Vitest: 2 passed
- focused ESLint: passed
- production Vite build: passed (existing chunk-size warning only)
- `git diff --check`: passed

## Dependency

Pair with copenhagentruckwash/api (one-time limited-backoffice login
grants) and merge after that backend PR. Required by
copenhagentruckwash/pleno-control-plane#1.
2026-07-29 00:01:22 +02:00
Jeppe BandJeppe Bundgaard 1da6fbd1c4 Remove card payment moms selector (#232)
## Summary
- Removes the visible POS card-payment moms/tax selector from mobile and
desktop Stripe terminal payment flows.
- Keeps Stripe terminal payment intents at 25% moms by default and
updates the POS desktop E2E assertion for the removed selector.

## Testing
- `npx playwright test tests/e2e/pos-desktop-card-payments.spec.js
--project=chromium-desktop --grep "idle state renders grouped terminal
statuses"`
- Visual preview capture on `origin/master`:
`POS_CARD_PAYMENT_PREVIEW_DIR=.../before PLAYWRIGHT_WORKERS=1 npx
playwright test tests/e2e/pos-card-payment-visual-preview.spec.js
--project=chromium-desktop`
- Visual preview capture on this branch:
`POS_CARD_PAYMENT_PREVIEW_DIR=output/visual-previews/after
PLAYWRIGHT_WORKERS=1 npx playwright test
tests/e2e/pos-card-payment-visual-preview.spec.js
--project=chromium-desktop`

## Visual change previews

### View: POS card payment
**Description:** The POS card-payment step no longer shows the moms
selector. The terminal selector and card-payment action remain
available; 25% moms is still reflected in the payment summary where
shown.

#### Mobile (390x844)
**Before:** ![Before mobile POS card
payment](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/de780d857cddcc6f61f728662e21e3a6b73fa791/visual-previews/pos-card-payment-vat/before-mobile-390x844.png)

**After:** ![After mobile POS card
payment](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/de780d857cddcc6f61f728662e21e3a6b73fa791/visual-previews/pos-card-payment-vat/after-mobile-390x844.png)

#### Tablet (768x1024)
**Before:** ![Before tablet POS card
payment](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/de780d857cddcc6f61f728662e21e3a6b73fa791/visual-previews/pos-card-payment-vat/before-tablet-768x1024.png)

**After:** ![After tablet POS card
payment](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/de780d857cddcc6f61f728662e21e3a6b73fa791/visual-previews/pos-card-payment-vat/after-tablet-768x1024.png)

#### Desktop (1440x900)
**Before:** ![Before desktop POS card
payment](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/de780d857cddcc6f61f728662e21e3a6b73fa791/visual-previews/pos-card-payment-vat/before-desktop-1440x900.png)

**After:** ![After desktop POS card
payment](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/de780d857cddcc6f61f728662e21e3a6b73fa791/visual-previews/pos-card-payment-vat/after-desktop-1440x900.png)

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-28 22:31:26 +02:00
Jeppe B 5204536f92 Fix self-serve settings state and contract (#229)
Ensure department-scoped self-serve settings load and save safely across route transitions, document the API contract, and cover stale in-flight state.
2026-07-28 18:34:35 +02:00
Jeppe BandJeppe Bundgaard 7a84cd9162 Align subuser self-service controls (#234)
## Summary
- Centralize subuser permission capability labels so the grant editor,
table header, and action settings wheel use the same self-service text.
- Add the self-service access control to each grant section in the
subuser action wheel.
- Add focused unit coverage for the shared label helper and subuser
action wheel payload.

## Verification
- `npm run test:unit:single --
tests/unit/subuser-management-labels.spec.js
tests/unit/subuser-grant-permission-nodes.spec.js`
- `npx eslint
src/components/displays/selectors/SubuserGrantPermissionNodes.vue
src/components/displays/superuser/tables/SubusersTable.vue
src/components/session/subuser/subuserPermissionLabels.js
tests/unit/subuser-management-labels.spec.js --quiet`
- `npm run build`

## Visual change previews
### View: Customer subuser management
**Description:** Shows the customer-facing chauffeur table and settings
wheel self-service label aligned to the same wording across table
header, row control, and wheel item.

#### Mobile (390x844)
**Before:** ![Before
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/wb-550fbd4a-subuser-module/visual-previews/subuser-management/mobile-before.png)
**After:** ![After
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/wb-550fbd4a-subuser-module/visual-previews/subuser-management/mobile-after.png)

#### Tablet (768x1024)
**Before:** ![Before
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/wb-550fbd4a-subuser-module/visual-previews/subuser-management/tablet-before.png)
**After:** ![After
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/wb-550fbd4a-subuser-module/visual-previews/subuser-management/tablet-after.png)

#### Desktop (1440x900)
**Before:** ![Before
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/wb-550fbd4a-subuser-module/visual-previews/subuser-management/desktop-before.png)
**After:** ![After
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/wb-550fbd4a-subuser-module/visual-previews/subuser-management/desktop-after.png)

---------

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-28 17:06:36 +02:00
Jeppe B 4f26ddd2cc Remove manual Stripe payment actions (#233)
## Summary

- remove hosted email-payment/payment-link creation from POS and order
management
- automatically capture authorized card payments instead of exposing a
manual capture action
- replace provider-specific Stripe wording with card-terminal
terminology
- retain ordinary terminal payment, receipts, order completion, and
navigation
- add focused unit and Playwright regression coverage

Paired API change: https://github.com/copenhagentruckwash/api/pull/327

## Verification

- focused frontend unit tests: 8/8 passed
- desktop card-payment Playwright: 4/4 passed
- mobile card-payment Playwright: 15/15 passed
- admin order action rail Playwright: 3/3 passed
- ESLint, translation generation/checks, build, and diff checks passed
- all 18 visual states passed their relevant DOM assertions

## Visual change previews

### View: Regular POS card-payment view

**Description:** The hosted email-payment action is removed and
provider-specific wording becomes generic card-terminal wording.

#### Mobile

**Before:** ![POS card payment before
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-pos-card-payment-mobile.png)

**After:** ![POS card payment after
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-pos-card-payment-mobile.png)

#### Tablet

**Before:** ![POS card payment before
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-pos-card-payment-tablet.png)

**After:** ![POS card payment after
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-pos-card-payment-tablet.png)

#### Desktop

**Before:** ![POS card payment before
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-pos-card-payment-desktop.png)

**After:** ![POS card payment after
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-pos-card-payment-desktop.png)

### View: Authorized payment capture

**Description:** The manual capture action is replaced by an
automatically initiated capture and its in-progress state.

#### Mobile

**Before:** ![Payment capture before
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-payment-capture-mobile.png)

**After:** ![Payment capture after
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-payment-capture-mobile.png)

#### Tablet

**Before:** ![Payment capture before
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-payment-capture-tablet.png)

**After:** ![Payment capture after
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-payment-capture-tablet.png)

#### Desktop

**Before:** ![Payment capture before
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-payment-capture-desktop.png)

**After:** ![Payment capture after
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-payment-capture-desktop.png)

### View: Order-dashboard action rail

**Description:** The hosted Stripe invoice/payment-link action is
removed while normal order actions remain.

#### Mobile

**Before:** ![Order action rail before
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-order-dashboard-mobile.png)

**After:** ![Order action rail after
mobile](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-order-dashboard-mobile.png)

#### Tablet

**Before:** ![Order action rail before
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-order-dashboard-tablet.png)

**After:** ![Order action rail after
tablet](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-order-dashboard-tablet.png)

#### Desktop

**Before:** ![Order action rail before
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/before-order-dashboard-desktop.png)

**After:** ![Order action rail after
desktop](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6ea832ae507a81e010b599fb52bdb1b375b5431c/docs/pr-previews/stripe-cleanup/after-order-dashboard-desktop.png)

## Residual risk

No live Stripe Terminal hardware or production Stripe account was used.
Browser behavior is verified with repository-owned mocks; the API suite
verifies route and payment-intent lifecycle wiring.
2026-07-27 19:09:40 +02:00
Jeppe BandJeppe Bundgaard b7859d4ede Add subuser access and recovery flows (#231)
## Summary

- add chauffeur/subuser password recovery by SMS and authenticated
password changes
- add a read-only pre-authorized access-request preview with explicit
approve/deny actions
- replace duplicate customer grants with one deduplicated Buefy dropdown
- show colored vehicle, toolbox, calendar, order, and driver permission
indicators
- add localized copy across all supported locale sources and generated
catalogs

## Verification

- ESLint passed
- grant deduplication/icon unit tests: 2 passed
- authentication Playwright coverage: 3 passed
- authorized subuser management Playwright coverage: 1 passed
- mocked direct approval browser flow passed
- i18n source/runtime checks passed
- production build passed (2,034 modules transformed)
- `git diff --check` passed

## Paired delivery

Paired API PR: https://github.com/copenhagentruckwash/api/pull/325

## Visual change previews

### View: Forgot-password account selection

**Description:** Visitors can now choose customer or chauffeur recovery;
chauffeur recovery requests the country code and phone number used for
the SMS reset link.

#### Mobile (390 x 844)

**Before:**
![Password recovery mobile
before](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/before-mobile.png)

**After:**
![Password recovery mobile
after](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/after-mobile.png)

#### Tablet (768 x 1024)

**Before:**
![Password recovery tablet
before](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/before-tablet.png)

**After:**
![Password recovery tablet
after](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/after-tablet.png)

#### Desktop (1440 x 900)

**Before:**
![Password recovery desktop
before](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/before-desktop.png)

**After:**
![Password recovery desktop
after](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/after-desktop.png)

### View: Pre-authorized customer access decision

**Description:** The SMS destination now previews the exact chauffeur
and customer request and requires an explicit approve or deny action
before mutating access.

#### Mobile (390 x 844)

**Before:**
![Access decision mobile
before](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/access-before-mobile.png)

**After:**
![Access decision mobile
after](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/access-after-mobile.png)

#### Tablet (768 x 1024)

**Before:**
![Access decision tablet
before](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/access-before-tablet.png)

**After:**
![Access decision tablet
after](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/access-after-tablet.png)

#### Desktop (1440 x 900)

**Before:**
![Access decision desktop
before](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/access-before-desktop.png)

**After:**
![Access decision desktop
after](https://raw.githubusercontent.com/copenhagentruckwash/pleno-vue/6c515817b934d838ae9d5e0192157c87e1e0a8d5/docs/pr-previews/customer-subuser-notifier/access-after-desktop.png)

---------

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-27 18:40:43 +02:00
Jeppe B cbdca71e3f Show verified cron worker cadence (#230)
Expose responsive worker cadence proof in the Cron operations dashboard.
2026-07-27 18:16:12 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> fd31609cb3 Bump ruby/setup-ruby from 1.319.0 to 1.321.0 (#226)
Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.319.0
to 1.321.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ruby/setup-ruby/releases">ruby/setup-ruby's
releases</a>.</em></p>
<blockquote>
<h2>v1.321.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Add jruby-10.1.1.0 by <a
href="https://github.com/ruby-builder-bot"><code>@​ruby-builder-bot</code></a>
in <a
href="https://redirect.github.com/ruby/setup-ruby/pull/932">ruby/setup-ruby#932</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ruby/setup-ruby/compare/v1.320.0...v1.321.0">https://github.com/ruby/setup-ruby/compare/v1.320.0...v1.321.0</a></p>
<h2>v1.320.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update CRuby releases on Windows by <a
href="https://github.com/ruby-builder-bot"><code>@​ruby-builder-bot</code></a>
in <a
href="https://redirect.github.com/ruby/setup-ruby/pull/931">ruby/setup-ruby#931</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ruby/setup-ruby/compare/v1.319.0...v1.320.0">https://github.com/ruby/setup-ruby/compare/v1.319.0...v1.320.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ruby/setup-ruby/commit/95ef2b042f9d7a56d8268cba8559e2842e2ad01b"><code>95ef2b0</code></a>
Add jruby-10.1.1.0</li>
<li><a
href="https://github.com/ruby/setup-ruby/commit/a30dfa457ad68707b8b910ac3a244714b61c0626"><code>a30dfa4</code></a>
Update CRuby releases on Windows</li>
<li>See full diff in <a
href="https://github.com/ruby/setup-ruby/compare/003a5c4d8d6321bd302e38f6f0ec593f77f06600...95ef2b042f9d7a56d8268cba8559e2842e2ad01b">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ruby/setup-ruby&package-manager=github_actions&previous-version=1.319.0&new-version=1.321.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 11:38:49 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 009519ee62 Bump actions/download-artifact from 4.3.0 to 8.0.1 (#227)
Bumps
[actions/download-artifact](https://github.com/actions/download-artifact)
from 4.3.0 to 8.0.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/download-artifact/releases">actions/download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v8.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Support for CJK characters in the artifact name by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/download-artifact/pull/471">actions/download-artifact#471</a></li>
<li>Add a regression test for artifact name + content-type mismatches by
<a href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a>
in <a
href="https://redirect.github.com/actions/download-artifact/pull/472">actions/download-artifact#472</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/download-artifact/compare/v8...v8.0.1">https://github.com/actions/download-artifact/compare/v8...v8.0.1</a></p>
<h2>v8.0.0</h2>
<h2>v8 - What's new</h2>
<blockquote>
<p>[!IMPORTANT]
actions/download-artifact@v8 has been migrated to an ESM module. This
should be transparent to the caller but forks might need to make
significant changes.</p>
</blockquote>
<blockquote>
<p>[!IMPORTANT]
Hash mismatches will now error by default. Users can override this
behavior with a setting change (see below).</p>
</blockquote>
<h3>Direct downloads</h3>
<p>To support direct uploads in <code>actions/upload-artifact</code>,
the action will no longer attempt to unzip all downloaded files.
Instead, the action checks the <code>Content-Type</code> header ahead of
unzipping and skips non-zipped files. Callers wishing to download a
zipped file as-is can also set the new <code>skip-decompress</code>
parameter to <code>true</code>.</p>
<h3>Enforced checks (breaking)</h3>
<p>A previous release introduced digest checks on the download. If a
download hash didn't match the expected hash from the server, the action
would log a warning. Callers can now configure the behavior on mismatch
with the <code>digest-mismatch</code> parameter. To be secure by
default, we are now defaulting the behavior to <code>error</code> which
will fail the workflow run.</p>
<h3>ESM</h3>
<p>To support new versions of the @actions/* packages, we've upgraded
the package to ESM.</p>
<h2>What's Changed</h2>
<ul>
<li>Don't attempt to un-zip non-zipped downloads by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/download-artifact/pull/460">actions/download-artifact#460</a></li>
<li>Add a setting to specify what to do on hash mismatch and default it
to <code>error</code> by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/download-artifact/pull/461">actions/download-artifact#461</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/download-artifact/compare/v7...v8.0.0">https://github.com/actions/download-artifact/compare/v7...v8.0.0</a></p>
<h2>v7.0.0</h2>
<h2>v7 - What's new</h2>
<blockquote>
<p>[!IMPORTANT]
actions/download-artifact@v7 now runs on Node.js 24 (<code>runs.using:
node24</code>) and requires a minimum Actions Runner version of 2.327.1.
If you are using self-hosted runners, ensure they are updated before
upgrading.</p>
</blockquote>
<h3>Node.js 24</h3>
<p>This release updates the runtime to Node.js 24. v6 had preliminary
support for Node 24, however this action was by default still running on
Node.js 20. Now this action by default will run on Node.js 24.</p>
<h2>What's Changed</h2>
<ul>
<li>Update GHES guidance to include reference to Node 20 version by <a
href="https://github.com/patrikpolyak"><code>@​patrikpolyak</code></a>
in <a
href="https://redirect.github.com/actions/download-artifact/pull/440">actions/download-artifact#440</a></li>
<li>Download Artifact Node24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/415">actions/download-artifact#415</a></li>
<li>fix: update <code>@​actions/artifact</code> to fix Node.js 24
punycode deprecation by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/451">actions/download-artifact#451</a></li>
<li>prepare release v7.0.0 for Node.js 24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/452">actions/download-artifact#452</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/download-artifact/commit/3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c"><code>3e5f45b</code></a>
Add regression tests for CJK characters (<a
href="https://redirect.github.com/actions/download-artifact/issues/471">#471</a>)</li>
<li><a
href="https://github.com/actions/download-artifact/commit/e6d03f67377d4412c7aa56a8e2e4988e6ec479dd"><code>e6d03f6</code></a>
Add a regression test for artifact name + content-type mismatches (<a
href="https://redirect.github.com/actions/download-artifact/issues/472">#472</a>)</li>
<li><a
href="https://github.com/actions/download-artifact/commit/70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3"><code>70fc10c</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/461">#461</a>
from actions/danwkennedy/digest-mismatch-behavior</li>
<li><a
href="https://github.com/actions/download-artifact/commit/f258da9a506b755b84a09a531814700b86ccfc62"><code>f258da9</code></a>
Add change docs</li>
<li><a
href="https://github.com/actions/download-artifact/commit/ccc058e5fbb0bb2352213eaec3491e117cbc4a5c"><code>ccc058e</code></a>
Fix linting issues</li>
<li><a
href="https://github.com/actions/download-artifact/commit/bd7976ba57ecea96e6f3df575eb922d11a12a9fd"><code>bd7976b</code></a>
Add a setting to specify what to do on hash mismatch and default it to
<code>error</code></li>
<li><a
href="https://github.com/actions/download-artifact/commit/ac21fcf45e0aaee541c0f7030558bdad38d77d6c"><code>ac21fcf</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/460">#460</a>
from actions/danwkennedy/download-no-unzip</li>
<li><a
href="https://github.com/actions/download-artifact/commit/15999bff51058bc7c19b50ebbba518eaef7c26c0"><code>15999bf</code></a>
Add note about package bumps</li>
<li><a
href="https://github.com/actions/download-artifact/commit/974686ed5098c7f9c9289ec946b9058e496a2561"><code>974686e</code></a>
Bump the version to <code>v8</code> and add release notes</li>
<li><a
href="https://github.com/actions/download-artifact/commit/fbe48b1d2756394be4cd4358ed3bc1343b330e75"><code>fbe48b1</code></a>
Update test names to make it clearer what they do</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/download-artifact/compare/d3f86a106a0bac45b974a628896c90dbdf5c8093...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=4.3.0&new-version=8.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 11:15:19 +00:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> b6f9b5a3a4 Bump actions/setup-node from 5 to 7 (#228)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5
to 7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-node/releases">actions/setup-node's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<h3>Enhancements:</h3>
<ul>
<li>Add cache-primary-key and cache-matched-key as outputs by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1577">actions/setup-node#1577</a></li>
<li>Migrate to ESM and upgrade dependencies by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1574">actions/setup-node#1574</a></li>
</ul>
<h3>Bug fixes:</h3>
<ul>
<li>Remove dummy NODE_AUTH_TOKEN export by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1558">actions/setup-node#1558</a></li>
<li>Only use <code>mirrorToken</code> in <code>getManifest</code> if
it's provided by <a
href="https://github.com/deiga"><code>@​deiga</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li>
</ul>
<h3>Documentation updates:</h3>
<ul>
<li>Add documentation for publishing to npm with Trusted Publisher
(OIDC) by <a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li>
<li>docs: Update restore-only cache documentation by <a
href="https://github.com/priya-kinthali"><code>@​priya-kinthali</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1550">actions/setup-node#1550</a></li>
<li>docs: Update caching recommendations to mitigate cache poisoning
risks by <a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1567">actions/setup-node#1567</a></li>
</ul>
<h3>Dependency update:</h3>
<ul>
<li>Upgrade <code>@​actions/cache</code> to 5.1.0, log cache write
denied by <a
href="https://github.com/jasongin"><code>@​jasongin</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li>
<li><a href="https://github.com/deiga"><code>@​deiga</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li>
<li><a href="https://github.com/jasongin"><code>@​jasongin</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6...v7.0.0">https://github.com/actions/setup-node/compare/v6...v7.0.0</a></p>
<h2>v6.5.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update <code>@​actions/cache</code> to 5.1.0 and add security
overrides for undici and fast-xml-parser by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1579">actions/setup-node#1579</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0">https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0</a></p>
<h2>v6.4.0</h2>
<h2>What's Changed</h2>
<h3>Dependency updates:</h3>
<ul>
<li>Upgrade <a
href="https://github.com/actions"><code>@​actions</code></a>
dependencies by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1525">actions/setup-node#1525</a></li>
<li>Update Node.js versions in versions.yml and bump package to v6.4.0
by <a
href="https://github.com/priya-kinthali"><code>@​priya-kinthali</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1533">actions/setup-node#1533</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Copilot"><code>@​Copilot</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1525">actions/setup-node#1525</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6...v6.4.0">https://github.com/actions/setup-node/compare/v6...v6.4.0</a></p>
<h2>v6.3.0</h2>
<h2>What's Changed</h2>
<h3>Enhancements:</h3>
<ul>
<li>Support parsing <code>devEngines</code> field by <a
href="https://github.com/susnux"><code>@​susnux</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1283">actions/setup-node#1283</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/setup-node/commit/820762786026740c76f36085b0efc47a31fe5020"><code>8207627</code></a>
Migrate to ESM and upgrade dependencies (<a
href="https://redirect.github.com/actions/setup-node/issues/1574">#1574</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/04be95cf3511ea51ebf9f224ddfb99cc7ab87cd4"><code>04be95c</code></a>
Add cache-primary-key and cache-matched-key as outputs (<a
href="https://redirect.github.com/actions/setup-node/issues/1577">#1577</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/7c2c68d20d402ed6a201ada70a81341941093140"><code>7c2c68d</code></a>
docs: Update caching recommendations to mitigate cache poisoning risks
(<a
href="https://redirect.github.com/actions/setup-node/issues/1567">#1567</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/6a61c0375d66246de94630495909f12cf8dac84d"><code>6a61c03</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/setup-node/issues/1569">#1569</a>
from jasongin/update-actions-cache-5.1.0</li>
<li><a
href="https://github.com/actions/setup-node/commit/30eb73b41ded577900c1ebf968ef95cdf8f7434f"><code>30eb73b</code></a>
Resolve high-severity audit issues</li>
<li><a
href="https://github.com/actions/setup-node/commit/4e1a87a501d0302f99e30e2748568adcb388d09f"><code>4e1a87a</code></a>
Update dist</li>
<li><a
href="https://github.com/actions/setup-node/commit/360237f0c01778d0c17291f75c56d6feae4f7574"><code>360237f</code></a>
Strict equality</li>
<li><a
href="https://github.com/actions/setup-node/commit/4f8aac5beb2f0854bc79651567a18c67eb0b9de3"><code>4f8aac5</code></a>
Bump <code>@​actions/cache</code> to 5.1.0, log cache write denied</li>
<li><a
href="https://github.com/actions/setup-node/commit/f4a67bbeca970f103397d3d2b9462cf787cd2980"><code>f4a67bb</code></a>
Only use <code>mirrorToken</code> in <code>getManifest</code> if it's
provided (<a
href="https://redirect.github.com/actions/setup-node/issues/1548">#1548</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/0355742c943ddb13ca8a6b700f824231caa91e75"><code>0355742</code></a>
Remove dummy NODE_AUTH_TOKEN export (<a
href="https://redirect.github.com/actions/setup-node/issues/1558">#1558</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/setup-node/compare/v5...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=5&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 12:55:41 +02:00
Jeppe B 7387a2b56e fix(i18n): unblock Truckwash iOS release catalog checks (#225)
Fix the location-permission source catalog nesting and regenerate all active v2 locale files so the App Store release matrix resolves the new compatibility aliases correctly.
2026-07-23 20:22:47 +02:00
Jeppe B 9ff103d4d0 fix(ios): respect status area and persist location consent (#224)
Keep the iOS status bar outside the Capacitor web view and replace startup geolocation watching with silent permission checks plus an explicit location action.

Verified by full unit, App Store readiness, Qodana, production build, Capacitor sync, and Playwright mobile suites.
2026-07-23 19:29:54 +02:00
Jeppe B 32418b42a0 fix(ios): add required location purpose string (#223)
## What changed
- add `NSLocationAlwaysAndWhenInUseUsageDescription` to the iOS app
- localize the purpose string in Danish and English
- enforce the key in mobile permission validation and App Store
readiness tests

## Why
App Store Connect accepted builds 1 and 2 but emitted `ITMS-90683`,
stating that the final app references APIs requiring this purpose
string. Shipping a corrected binary avoids submitting a candidate with a
known Apple delivery warning.

## Validation
- `node scripts/mobile/check-permissions.mjs`
- `node scripts/mobile/validate-app-store.mjs --strict`
- `vitest run tests/unit/app-store-product-readiness.spec.js` (5 tests)
- Prettier check for changed JS files
- `git diff --check`
2026-07-23 16:36:35 +00:00
Jeppe B bf2208e77b fix(ios): use valid Danish TestFlight locale (#222)
Use Apple's supported `da` beta locale and cover the localization/distribution flow with a regression test.

The first signed upload already processed version 1.0.0 build 1 successfully; this fixes the post-processing localization failure before the controlled retry.
2026-07-23 16:50:37 +02:00
Jeppe B 5702d45bc6 fix(ios): harden App Store release automation (#221)
## Summary

- replace the unsupported top-level App Store version collection with
Apple's app-scoped version endpoint
- add tested release-policy and availability readback for exact
version/build, `AFTER_APPROVAL`, Denmark only, no preorder, and no
automatic future territories
- strengthen the stable `App Store Readiness` check and align
Fastlane/candidate handoff with the approved 1.0.0 release policy

## Task contract

`truckwash-ios-release-20260723` — R4 (`ci-policy`, `release-policy`,
`credential-handling`, `branch-protection-or-rules`,
`mobile-store-submission`). The user explicitly approved implementation,
protected-master delivery, and the App Store release path.

## Changed files

- App Store Connect client and dependency-free Node tests
- App Store readiness and candidate workflows
- Fastlane candidate release configuration
- Apple App Store release runbook

## Verification

- `node --test tests/node/app-store-connect.test.mjs` — 10 passed
- `node scripts/mobile/validate-app-store.mjs --strict` — passed
- `node scripts/mobile/check-permissions.mjs` — passed
- App Store product-readiness Vitest — 5 passed
- ESLint on changed Node files — passed
- workflow YAML parsing — passed
- `git diff --check` — passed
- local Fastlane validation unavailable because Ruby/Bundler is not
installed on this host; `App Store Readiness` runs it on GitHub

## Release target

- iOS App Store
- bundle `io.truckwash.app`
- version `1.0.0`
- App Store Connect app `6792777794`
- Denmark only
- automatic release after approval
- no preorder or phased release for 1.0.0

The repository App Store automation switch remains disabled until this
change is merged and credential health is reverified.
2026-07-23 12:59:17 +00:00
Jeppe BandJeppe Bundgaard 42352b4c2d fix(release): isolate post-deploy bookkeeping (#220)
Scopes rollback to actual public or credentialed live-gate failure.
Release Manager recording becomes non-blocking post-deploy observability
and records only the API check because the mandatory Playwright gate
already verifies the exact full static inventory. This avoids the
duplicate synchronous static verification that exceeded the API proxy
timeout and rolled back a verified release.\n\nVerification:\n- git diff
--check\n- release.yml parsed with the checked-in YAML dependency\n-
credentialed role gate without secrets: 2 skipped, exit 0

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-23 06:18:01 +02:00
Jeppe BandJeppe Bundgaard 729416e5ef fix(release): skip role smoke without credentials (#219)
Makes the credentialed live Playwright gate conditional on its secrets
being configured. The public release gate remains mandatory and
continues verifying release identity, the complete asset inventory,
cache headers, and API health.\n\nVerification:\n- git diff --check\n-
PLAYWRIGHT_BASE_URL=https://truckwash.io Playwright @role-live gate: 2
skipped, exit 0

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-23 04:53:51 +02:00
Jeppe BandJeppe Bundgaard 41b3be926a test(release): allow full live asset inventory (#218)
## Summary
- give the complete public asset inventory gate a five-minute test
budget
- keep the API and rendered guest-flow smoke tests on the existing
default timeout

## Rationale
The production manifest contains the full release inventory.
Sequentially downloading and hashing it takes longer than the global
60-second Playwright timeout from GitHub-hosted runners, causing false
failures even though release identity, API, and guest-flow checks pass.

## Verification
- ESLint on the changed spec
- Playwright live configuration test discovery

---------

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-23 02:59:40 +02:00
Jeppe BandJeppe Bundgaard fc67e7cf0b Fix idempotent FTPS directory setup (#217)
The production FTPS deploy now authenticates, but lftp exits when cPanel
returns 550 File exists for pre-created deployment directories. Use lftp
mkdir -p -f for the archive and activation directories so retries remain
idempotent while subsequent upload operations still surface real access
failures.\n\nVerification:\n- vitest tests/unit/cpanel-deploy.spec.js
(26 passed)\n- eslint scripts/release/cpanel-deploy-lib.mjs
tests/unit/cpanel-deploy.spec.js\n- git diff --check

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-23 00:00:48 +02:00
Jeppe B 9b3c06fc6f fix(release): stream lftp commands directly (#216)
## Summary
- feed the generated lftp command script directly over stdin
- avoid reopening `/dev/stdin`, which fails on the production hosted
runner
- keep FTP credentials out of process arguments

## Verification
- `vitest run tests/unit/cpanel-deploy.spec.js` (26/26)
- ESLint on changed files
- `git diff --check`

Supersedes the failed production release run 29948809036.
2026-07-22 21:24:04 +02:00
Jeppe B f0e3c4812b Require fresh passkeys for passwordless account deletion (#215)
## Summary
- Complete the frontend contract for hardened backend account deletion
(#319).
- For passwordless accounts, request a fresh deletion-specific WebAuthn
challenge and submit its serialized assertion.
- Reuse the existing passkey assertion serializer instead of duplicating
WebAuthn conversion logic.
- Accept the durable `manual_review` backend state while presenting the
existing safe failure copy.

## Verification
- Account deletion unit tests: 9/9.
- Focused ESLint passed for all four changed files.
- Node syntax checks and `git diff --check` passed.

Backend rollout flags remain default-off; this UI is inert until #319
schema checks and explicit API enablement are completed.
2026-07-22 20:05:37 +02:00