Commit Graph
100 Commits
Author SHA1 Message Date
Jeppe BandJeppe Bundgaard db9f589bf7 Resolve issue causing crash when plate_scanners.deleted_at was missing. (#346)
Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-08-04 16:43:46 +02:00
Jeppe B ab6c3ba5b6 Fix route permission instance calls (#344)
## Root cause

`route_t::hasPermission()` and `requirePermission()` are instance
methods. Route code was invoking them with `self::`; the new XL Vask
hall-scope helper made that call from a genuinely static context,
causing PHP to throw:

`Non-static method routes\\xlvaskUsageLogsRoute::hasPermission() cannot
be called statically`

## Changes

- Invoke route permission methods through `$this` across all 273
executable legacy calls in 45 route classes.
- Make `xlvaskUsageLogsRoute::allowedHallIdsForUser()` an instance
helper and update all 13 callers.
- Preserve the existing all-scope and own-scope hall selection rules.
- Add a token-aware regression test that rejects executable
`self::hasPermission()` and `self::requirePermission()` calls, while
ignoring comments.
- Add focused XL Vask tests for global scanner hall scope and
group-limited own scope.
- Update affected route contract assertions to the instance-call form.

## Verification

- PHP lint: all 53 changed PHP files
- Focused PHPStan: changed XL Vask route and both new regression tests —
clean
- Focused regression slice: 58 passed, 748 assertions
- Full local unit suite: 1,300 passed, 9,442 assertions (1 unrelated
existing warning, 1 environment skip)
- Full local API suite: 285 passed, 11,704 assertions
- Exact-SHA GitHub Tests workflow: all 7 jobs passed (unit, API,
integration, legacy, edge gateway, and supporting checks)
- Independent exact-SHA QA gate: PASS, no findings
- Independent exact-SHA security gate: PASS, no findings
- Independent exact-SHA reviewer gate: PASS, no findings
- Remote comparison: exactly one commit ahead of
`40b104abed7723a7d1b7028190ecda0e7aeef829`; all 53 remote blob hashes
matched the reviewed worktree

## Delivery state

Draft only for human review. No merge or deployment is included. Qodana
is skipped while the PR remains draft and is therefore not represented
as a passed gate.
2026-08-04 16:04:41 +02:00
Jeppe B 40b104abed Add governed XL Vask AI invoice automation (#343) 2026-08-04 11:32:49 +02:00
Jeppe B 842b06c93f Fix frontend release version recording (#342)
Add a scoped release-gate endpoint for exact frontend SHA recording and independent readback.
2026-08-03 16:11:09 +02:00
Jeppe B 1f03b46564 Fix XL-Vask usage metadata hydration (#341)
Keep automation metadata out of the strict legacy XL-Vask helper payload while returning it separately. This restores the invoice-period XL-Vask orders GET after the guarded autopilot deployment.
2026-08-03 16:00:52 +02:00
Jeppe B 6d888a455d Automate XL-Vask invoice-period resolution (#340)
Deploy the revision-aware XL-Vask import and guarded autopilot infrastructure. Automatic actions remain fail-closed pending production readiness, calibration, dry-run, and canary gates.
2026-08-03 15:33:55 +02:00
Jeppe B 0b304a2203 Gate invoice tree activation on audit schema (#339)
## Summary
- gate object-tree v2 on exact, schema-backed supersession audit columns
- serialize checked additive DDL and fail closed without disrupting
legacy invoicing
- preserve pre-schema supersession markers when structured columns are
still null
- add a superuser-only, self-scoped canary endpoint with locked
legacy-to-canonical allowlist migration
- verify effective activation, roll back failed readiness, and audit
enable/disable/failure

## Verification
- focused invoicing safety: 16 tests passed (99 assertions)
- full unit suite: 1,237 passed (9,003 assertions), 2 skipped, existing
warnings only
- PHP syntax and `git diff --check` clean
- independent architecture, security, and reviewer gates: GO

## Activation
Deploy with global database/environment enablement off. POST the
self-canary endpoint for one authenticated superuser, require
`configured_enabled=true` and `effective_enabled=true`, then verify the
exact period and tree GET routes. Roll back with the same endpoint using
`enabled=false`.
2026-08-03 13:03:55 +02:00
Jeppe B 068f9e254f Complete selected-customer invoice period tree (#338)
Add the authoritative revision-bound invoice collection tree and guarded cleanup, merge, price-reset, and transfer operations.
2026-08-03 12:02:34 +02:00
Jeppe B f37feef1e6 Fix customer login email session refresh (#337)
Invalidate cached auth sessions for every active customer token and return the persisted canonical login email.
2026-08-03 09:40:00 +02:00
Jeppe B c795df4aad Add invoice period review workflow (#336)
Improve the superuser invoice-period review API, stale-preview protection, queue visibility, review blockers, and e-conomic eligibility.
2026-08-02 19:20:50 +02:00
Jeppe B 1e0e051775 Harden Sæby demo registration and department scope (#335)
Complete and secure public customer/driver registration, authoritative limited-backoffice department scope, one-time employee QR login, and pricing concurrency for the Sæby demo.
2026-08-02 11:50:56 +02:00
Jeppe B 4587bdfb06 Restore API startup by isolating Bird activation (#334)
Keep Bird activation outside the PHP-FPM/nginx startup path so Bird configuration failures cannot make the core API unavailable. Retain guarded explicit activation and regression coverage.
2026-07-29 22:41:19 +02:00
Jeppe B a442e70744 Add secure Bird gateway for Pleno Control Plane (#332)
Add the Bird Control Plane gateway, signed webhook ingestion, policy-gated writes, fail-closed production auto-activation, and RSA-OAEP bootstrap credential flow.
2026-07-29 19:59:20 +02:00
Jeppe BandJeppe Bundgaard 1b161f1b96 Guard Superuser invoicing registration search fields (#331)
## Summary
- Adds a backend contract guard that Superuser invoicing period search
continues to include all separate registration columns: `reg_1`,
`reg_2`, and `reg_3`.
- This preserves the API/search behavior that the frontend object-tree
registration layout relies on.

## Tests
- `vendor/bin/pest
tests/Unit/Invoicing/InvoicingPeriodRouteGuardsTest.php --colors=always`

Note: local Composer install was run with
`--ignore-platform-req=ext-mysqli --ignore-platform-req=ext-gd` because
those PHP extensions are not enabled in this worker image; the executed
guard test does not use them.

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-29 13:54:58 +02:00
Jeppe B 448e0e50c2 Fix api-v2 CORS at the edge without changing rollout flows (#330)
Add API-only Traefik CORS middleware labels while preserving configured origins and the existing rollout/load-balancer behavior.
2026-07-29 09:01:08 +02:00
Jeppe B 710baad28e Add one-time limited backoffice login grants (#329)
## Summary

Adds the missing backend contract used by Pleno Control Plane
Conversations/Suggestions to create an employee login action safely.

- issues 60–900 second one-time limited-backoffice login grants
- persists only SHA-256 bearer digests; bearer recovery is deterministic
under the server encryption key for identical idempotent retries
- enforces manager permissions, department scope, active
managed-employee constraints, one-time atomic exchange, revocation,
expiry, and account-deletion cleanup
- adds employee-create idempotency so an approved automation retry
cannot duplicate an employee
- documents the create, revoke, and unauthenticated exchange endpoints
in OpenAPI

## Security and concurrency

- bearer values are returned only in a URL fragment and are never
written to logs or database plaintext
- employee and grant rows use a consistent employee-then-grant lock
order
- deactivation revokes outstanding grants and existing sessions in the
same transaction
- consumed, revoked, expired, or payload-mismatched idempotent replays
fail closed

## Verification

- `scripts/php-ci-test.sh api`: 273 passed, 11,086 assertions (one
inherited warning)
- focused security contract: 1 passed, 21 assertions
- PHP syntax checks passed for the service and routes
- `git diff --check` passed

## Dependency

Required by copenhagentruckwash/pleno-control-plane#1. Merge before the
matching frontend and Control Plane PRs.
2026-07-29 00:01:13 +02:00
Jeppe BandJeppe Bundgaard 42ddce84bc Serialize VAT collection mutations with payment operations (#326)
## Summary

- Makes Stripe Terminal card payment intents always use 25% moms in the
API, independent of any client-supplied `tax_percentage`.
- Updates amount calculation, metadata persistence, stored-intent reuse
matching, the authoritative OpenAPI contracts, and operation-specific
Writerside outputs.
- Prevents double charging and false order closure across stale,
concurrently succeeded, partially recorded, or mismatched intents.
- Serializes payment create/capture/closure with order-item changes and
every order-to-invoice-collection reassignment through shared database
locks.
- Converts expected lock contention and reconciliation cases into
deliberate 409 responses.

## Exact-head evidence

Current head: `3a0f70d315a94d2efe586a2188d2c54f8ff11cd4`

- PHP syntax passed for all changed runtime files.
- Focused Orders suite: **42 tests / 293 assertions passed**.
- `git diff --check` passed.
- Fresh exact-head Tests and Qodana are running.
- Every Codex finding has a concrete reply; a fresh exact-head review is
requested below.

## Safety behavior

- Caller-controlled VAT is absent from request contracts; fixed 25% moms
is server-owned.
- A succeeded payment is preserved, requires the full expected
`amount_received`, and cannot close a changed/mismatched or
already-claimed collection.
- A compatible partially recorded Stripe closure is completed
idempotently; conflicting partial state fails closed for manual
reconciliation.
- Every cancellation/delete caller honors a concurrent-success result
and never falsely reports a completed payment as cleared.
- Price changes and invoice-collection reassignment share the payment
lock through validation, capture, post-capture reload, and closure.
- Reader changes are persisted only for reusable matching intents, so
stale intent cancellation targets the original terminal.
- Accepted legacy succeeded intents normalize stored tax to 25% before
response construction.

---------

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-28 22:00:59 +02:00
Jeppe B da0113e3ed Auto-disable department self-serve at opening (#323)
Auto-disable department self-serve at opening
2026-07-28 18:03:05 +02:00
Jeppe BandJeppe Bundgaard 3c13892366 Harden subuser permission payloads (#328)
## Summary
- Normalize subuser grant permission payload keys before enum validation
so mixed-case customer-facing writes are accepted and deduped
consistently.
- Add a focused subuser route static check for permission payload
normalization.

## Verification
- `php
services/nginx/app/tests/subusers/SubusersRoutePermissionLinkTest.php &&
php
services/nginx/app/tests/subusers/SubusersRoutePermissionsPayloadTest.php`
- `php -l services/nginx/app/routes/subusersRoute.php && php -l
services/nginx/app/tests/subusers/SubusersRoutePermissionsPayloadTest.php`

---------

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-28 17:06:29 +02:00
Jeppe B 30d860fdef Retire payment links and capture card payments (#327)
## Summary

- retire Stripe hosted payment-link creation routes used by POS and
order management
- automatically capture authorized payment intents rather than requiring
a separate manual capture action
- preserve ordinary terminal payment and payment-intent lifecycle
behavior
- add API and wiring regressions for payment-link retirement and
automatic capture

Paired frontend change:
https://github.com/copenhagentruckwash/pleno-vue/pull/233

## Verification

- focused backend unit suite: 2 tests, 36 assertions passed
- PHP syntax checks passed
- paired frontend unit and Playwright suites passed locally
- full required GitHub runner suites are required before this task may
enter Review or merge

## Security and operational notes

- no credentials, terminal secrets, or payment data are added
- no live Stripe account or physical terminal was exercised locally
- automatic merge remains gated on both paired PRs having passing
required checks and current branches
2026-07-27 19:09:37 +02:00
Jeppe BandJeppe Bundgaard d3e4798b11 Complete subuser notification and recovery lifecycle (#325)
## Summary

- notify customers by SMS with approve/deny links when a subuser
requests access
- notify subusers by SMS after approval or denial, including manual
grant changes
- support subuser password reset and authenticated password changes
- add read-only token previews followed by explicit POST confirmation
- store short-lived one-time purpose-bound action tokens only as SHA-256
digests
- serialize grant decisions transactionally to prevent conflicting
concurrent actions
- document the API contract in OpenAPI

## Security

- generic reset responses reduce account enumeration
- URL tokens are removed from browser history after frontend bootstrap
- approval previews never mutate state
- concurrent decisions lock the exact grant row
- SMS failures remain non-fatal and are returned as delivery status

Residual risk: existing subuser sessions cannot all be centrally
invalidated after password reset because there is no per-subuser session
index; they expire normally within the existing session lifetime.

## Verification

- backend Pest: 14 tests, 91 assertions
- PHP syntax checks passed
- focused PHPStan passed
- OpenAPI YAML parsed successfully
- `git diff --check` passed

Database-backed API integration tests were unavailable because the local
environment lacks the required database configuration.

## Paired delivery

Paired Frontend PR:
https://github.com/copenhagentruckwash/pleno-vue/pull/231

Both PRs are required before completion. The frontend PR contains the
responsive visual comparisons.

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-27 18:40:40 +02:00
Jeppe B 8d8f0eccce Fix cron worker minute cadence (#324)
Replace drifting cron loops with persistent cadence-tracked workers and CI-verifiable Compose wiring.
2026-07-27 18:16:09 +02:00
Jeppe B 6e24718c1f Isolate backend Docker jobs on ephemeral runners (#322)
## Summary
- Run Docker-producing PHP, Edge Broker, and Edge Gateway jobs on
ephemeral Ubuntu workspaces for both PR and push events.
- Keep the non-Docker Edge Agent and Release Manager gate on the trusted
backend pool.
- Preserve the explicit system-socket selection and fail-closed Docker
access check.

## Root cause
Exact-master run 29942825210 got past Docker access, then later jobs
failed during checkout because an earlier container left
`services/php/logs/error.log` root-owned in the reused self-hosted
workspace. This is workspace contamination, not a product-test failure.
The shallow frontend repair pattern would miss the depth-4 file and
would accumulate undeletable trash directories.

## Verification
- Workflow YAML parse passed.
- `git diff --check` passed.
- PR CI must be green; after merge, exact-master Required CI and the
non-skipped Release Manager gate are mandatory.
2026-07-22 19:47:31 +02:00
Jeppe B 9b481e0957 Use the system Docker socket in backend CI (#321)
## Summary
- Keep untrusted PRs on ephemeral Ubuntu runners and trusted pushes on
the local backend pool.
- Force Docker-dependent jobs to the working system socket instead of
the unavailable default rootless context.
- Preserve the fail-closed Docker access check and never chmod the
socket.

## Evidence
- Exact master run 29942048689 failed before tests because plain Docker
commands resolved to `/run/user/1000/docker.sock`.
- Backend listener processes already have docker-group membership;
`/var/run/docker.sock` is root:docker 0660.
- `DOCKER_HOST=unix:///var/run/docker.sock docker version` succeeds
locally with server 29.3.1.
- Workflow YAML parse and `git diff --check` pass.

Exact-master Required CI and Release Manager gate success remain
mandatory after merge.
2026-07-22 19:33:13 +02:00
Jeppe B 0060fb45ca Add in-app account deletion (#319)
## Summary
- Add self-service deletion for the authenticated customer or subuser
identity only.
- Preserve shared customer grants, reset keys, bookings, order bookings,
vehicles, invoices, and legally required history.
- Require password/TOTP or a fresh deletion-specific, five-minute,
single-use WebAuthn assertion.
- Reject support impersonation and expired legacy plain-session tokens.
- Use durable database throttling, transactional request processing, a
durable outbox, and terminal `manual_review` state.
- Keep API and worker default-off behind separate
`account_deletion.api_enabled` and `account_deletion.worker_enabled`
module-config flags.

## Safe rollout
1. Keep both flags disabled.
2. Run `php scripts/account-deletion-schema.php check`.
3. If needed, run `php scripts/account-deletion-schema.php apply --yes`,
then rerun `check` until `ready:true`.
4. Deploy the frontend companion PR while the API remains disabled.
5. Enable `api_enabled` for a controlled canary; verify password and
passwordless request flows plus immediate authentication revocation.
6. Inspect queued request/outbox state, then enable `worker_enabled`.
7. Verify anonymization, preserved tenant/history data, outbox delivery,
retries, and manual-review behavior before broad rollout.

## Verification
- Account deletion unit tests: 2 passed, 43 assertions.
- PHP lint, both OpenAPI YAML parses, runtime-DDL scan,
destructive-scope scan, and `git diff --check` passed.
- Full API/unit/integration evidence is required from exact-head CI;
local Docker is unavailable and shared-vendor tests were explicitly
discarded.

## Security notes
- Schema mutation is CLI-only; web and cron paths perform read-only
readiness checks.
- Runtime behavior fails closed when schema/config/throttle/delivery
prerequisites are unavailable.
2026-07-22 19:22:17 +02:00
Jeppe B 34cf804d75 Harden CI runner and release gate security (#320)
## Summary

- run untrusted pull-request jobs on ephemeral `ubuntu-24.04` runners
- reserve the local backend runner pool for trusted branch pushes
- remove world-writable Docker-socket fallbacks
- pin core GitHub Actions and disable checkout credential persistence
- remove the release-manager PHP parse-error fail-open path

## Why

Pull-request code previously ran on persistent self-hosted runners with
Docker access, and CI contained permission weakening and a release-gate
break-glass success path. Those behaviors were unsafe for autonomous
intake.

## Validation

- workflow YAML parsed
- backend AI workflow outputs are in sync
- pinned action SHAs match the current v4 tags
- `git diff --check`

## Risk and activation

This is an R4 CI/release-policy change. Keep the PR draft for human
review and let required CI prove the hosted-runner path before merge.
2026-07-22 19:05:55 +02:00
Jeppe B 677d4700b0 Enforce customer product restrictions for order bookings (#318)
## What changed

- validate every normalized order-booking item against active customer
product rules before reservation and persistence
- return a structured HTTP 400 response containing the rejected product
and matching rule metadata
- document the rejection response in both OpenAPI specifications
- add API coverage for restricted base products, restricted add-ons, and
allowed neighboring products

## Why

Frontend rule guidance alone cannot prevent stale or crafted requests
from persisting restricted booking products. The booking write boundary
must enforce the same customer rules.

## Validation

- full backend API suite
- focused order-booking API coverage
- PHP syntax checks
- OpenAPI and diff checks

## Related frontend PR

The coordinated frontend PR provides fail-closed selection, recovery,
and responsive booking-page behavior.
2026-07-20 14:09:20 +02:00
Jeppe B abde54c898 Allow Capacitor iOS API origin (#317)
Allow the exact Capacitor iOS WebView origin through credentialed CORS while strictly validating request-origin syntax.
2026-07-20 13:53:55 +02:00
Jeppe B b177347bf5 Ignore PHPUnit result cache (#316)
Ignore the generated PHPUnit cache directory and remove its volatile test-results file from Git tracking so test runs no longer dirty protected branch checkouts.
2026-07-20 08:49:27 +02:00
Jeppe B 32a5b99204 Resolve remaining backend full-scan Qodana findings (#315)
Fix the two High findings exposed by the first full master Qodana scan after the broader remediation.
2026-07-17 06:24:47 +02:00
Jeppe B 2a6a86c9c3 Resolve backend Qodana critical and high findings (#314)
Resolve recommended-profile Critical and High findings, retain narrow analyzer exceptions, and update the edge-broker WebSocket dependency to a non-vulnerable release.
2026-07-17 05:44:16 +02:00
Jeppe B 6566027746 Configure advisory Qodana analysis (#313)
## Summary

- configure advisory Qodana PHP 2026.1 analysis for trusted pull
requests and master, beta, canary, and internal branch scans
- install both Composer projects and the edge-agent/edge-broker Node
dependencies before analysis
- exclude generated, vendor, build, cache, legacy-test, and local-agent
trees
- keep Quick Fixes, SARIF artifacts, baselines, thresholds, and
required-check enforcement disabled during calibration

## Safety

- fails closed when QODANA_TOKEN is absent
- skips draft, fork, and Dependabot pull requests
- uses least-privilege GitHub permissions and immutable action SHAs
- uploads findings to the dedicated api Qodana Cloud project

## Validation

- actionlint 1.7.12
- SchemaStore qodana-1.0 validation
- bootstrap shell syntax and lockfile structure checks
- immutable action tag verification
- git diff --check
- independent review completed with no findings

## Live verification

- [PR-mode
scan](https://github.com/copenhagentruckwash/api/actions/runs/29494056175)
completed successfully with 0 changed-file problems, 439 inspections,
and a passed license audit ([Qodana
report](https://qodana.cloud/projects/P2nXd/reports/LJv98e))
- [full branch
scan](https://github.com/copenhagentruckwash/api/actions/runs/29495399119)
completed successfully and uploaded 8,248 current findings across 725
files, 439 inspections, and a passed license audit to the dedicated api
project ([Qodana
report](https://qodana.cloud/projects/P2nXd/reports/qJMOxX))
- the initial debt remains advisory; baseline and required-check
enforcement are intentionally deferred until findings are triaged
2026-07-16 14:35:59 +02:00
Jeppe B 511605b619 Verify API master branch protection (#312)
Record the live ruleset and complete the protected-path canary.
2026-07-16 12:55:18 +02:00
Jeppe B c2abf17cd7 Prepare API default branch protection (#311)
Add a stable Required CI gate, branch-protection desired state, and publishing runbook.
2026-07-16 12:38:01 +02:00
Jeppe B fefe18a719 Fix legacy customer attribute session query 2026-07-16 12:20:20 +02:00
Jeppe B 9b2d5d5291 Fix customer restriction CI regressions 2026-07-16 12:06:42 +02:00
Jeppe B e1fb79d9b6 Add customer rule product restrictions 2026-07-16 11:50:52 +02:00
Jeppe B 879dfcf79a Improve invoice period data and POS add-on validation 2026-07-15 17:04:52 +02:00
Jeppe B 0feb705059 Support collected invoice economic PDF downloads 2026-07-14 15:39:39 +02:00
Jeppe B fa1ade555f Fix self-serve cron registry test
Fix self-serve cron registry test
2026-07-09 11:36:11 +02:00
Jeppe B 7a1c444df0 Activate self-serve opening relays
Activate self-serve opening relays
2026-07-09 11:27:32 +02:00
Jeppe B 8aefbd8fb3 Guard wash subscription distribution SQL
Guard the wash subscription distribution query after invoice-inclusion filtering removes all candidate orders, preventing an empty IN () clause on the invoicing distribution endpoint.

Verified with focused syntax, Pest, PHPStan, and invoicing unit-suite checks.
2026-07-09 10:24:02 +02:00
Jeppe B a7181a4ab2 Fix edge gateway relay binding reactivation
Reactivate existing relay binding rows when a gateway/relay pair is re-added after soft deletion, avoiding duplicate uniq_edge_gateway_binding inserts. Add regression coverage for the reactivation path.
2026-07-08 18:46:33 +02:00
Jeppe B e14cddc1fb Fix API suite regressions 2026-07-08 12:54:26 +02:00
Jeppe B 31887fa8c9 Cover API CI skip prevention wiring 2026-07-08 12:32:27 +02:00
Jeppe B eac83b18a0 Preflight required extensions for API CI 2026-07-08 12:32:19 +02:00
Jeppe B 3817a37021 Make API CI fail on skipped bootstrap 2026-07-08 12:31:40 +02:00
Jeppe B b77efc538a Fix backend test gates and department product access 2026-07-07 22:16:37 +02:00
Jeppe B 579ddcf510 Merge pull request #307 from copenhagentruckwash/copilot/update-limited-backoffice-roles
Fix limited-backoffice role permissions and enforce department access on order mutations
2026-07-07 02:53:06 +02:00
Jeppe B 04bb26f1b0 Merge pull request #306 from copenhagentruckwash/copilot/fix-php-api-job-failure
Fix two failing LimitedBackofficeApiTest assertions
2026-07-07 00:44:53 +02:00
Jeppe B e208b1b2a4 Merge pull request #305 from copenhagentruckwash/codex/limited-backoffice-employee-migration
Add limited backoffice employee migration
2026-07-07 00:14:25 +02:00
Jeppe B 709c6acbba Fix product null department permissions
Treats null-like optional product query params as omitted and avoids department_access_0 permission checks.
2026-07-06 20:14:45 +02:00
Jeppe B c7f5c73a9e Merge pull request #303 from copenhagentruckwash/codex/daily-report-product-targets-api
[codex] Add daily report product target API
2026-07-06 19:35:37 +02:00
Jeppe B 8544ce0a18 Merge pull request #297 from copenhagentruckwash/codex/customer-product-fixed-price-overrides
Add customer product fixed price overrides
2026-07-06 17:23:06 +02:00
Jeppe B 742b15116d Merge pull request #295 from copenhagentruckwash/fix/economic-ean-transfer
Fix e-conomic EAN customer transfer
2026-07-06 17:00:57 +02:00
Jeppe B c089186046 Merge pull request #302 from copenhagentruckwash/codex/customer-orderbooking-create-without-permission
Allow customer order booking creation without booking permission
2026-07-06 16:39:17 +02:00
Jeppe B f262047476 Merge pull request #300 from copenhagentruckwash/codex/scoped-monthly-split-api
Scope monthly invoice split API
2026-07-06 16:01:54 +02:00
Jeppe B b8390ac0d3 Merge pull request #298 from copenhagentruckwash/codex/only-tankcleaning-order-enforcement
Enforce only tankcleaning order products
2026-07-06 16:01:40 +02:00
Jeppe B 0d4a5470e5 Add superuser department overview API (#301)
Merge backend API for the superuser department overview.
2026-07-06 16:01:04 +02:00
Jeppe B 845ca6e48e Merge pull request #290 from copenhagentruckwash/codex/custom-pricing-only-departments
Add custom-only department pricing enforcement
2026-07-06 15:31:27 +02:00
Jeppe BandJeppe Bundgaard 8e46ce1b04 [codex] Allow error reports without screenshots (#299)
* Allow error reports without screenshots

* Stabilize edge gateway shell transcript smoke

---------

Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-06 14:27:47 +02:00
Jeppe BandJeppe Bundgaard 11c2a1b72e Block restricted customer order items (#296)
Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-06 14:06:29 +02:00
Jeppe BandJeppe Bundgaard 6f3d7e0f7d Add limited backoffice employee contact fields (#294)
Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-06 13:14:06 +02:00
Jeppe B a8fba73d99 Add limited backoffice role permission details (#291)
Adds grouped safe permission metadata for limited backoffice role presets.
2026-07-06 12:24:54 +02:00
Jeppe B 669759461d Merge pull request #293 from copenhagentruckwash/codex/economic-collected-invoice-transfer-speed
Optimize collected e-conomic invoice transfers
2026-07-06 11:49:47 +02:00
Jeppe B 94c3654240 Merge pull request #292 from copenhagentruckwash/fix/limited-backoffice-price-save
[codex] Fix limited backoffice price saves on legacy schema
2026-07-06 11:03:44 +02:00
Jeppe BandJeppe Bundgaard 3f41eebdf6 Default vehicle subscriptions to false (#288)
Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
2026-07-06 09:21:31 +02:00
Jeppe B 64e0b2444b Merge pull request #289 from copenhagentruckwash/fix/limited-backoffice-api-compat
[codex] Fix limited backoffice schema compatibility
2026-07-06 09:20:56 +02:00
Jeppe B f0a8299133 Merge pull request #287 from copenhagentruckwash/fix/api-ci-limited-backoffice
Fix API CI failures
2026-07-02 11:03:12 +02:00
Jeppe B 605efacece Merge pull request #284 from copenhagentruckwash/codex/optimize-scanner-lpr-backend
[codex] optimize scanner LPR backend
2026-06-12 22:08:35 +02:00
Jeppe B b3ba3c8de5 Merge pull request #283 from copenhagentruckwash/fix/pwa-selfserve-stop-latency
[codex] Reduce self-serve latency and add PHP-FPM workers
2026-06-12 13:15:28 +02:00
Jeppe B 5027d0c919 Merge pull request #282 from copenhagentruckwash/codex/register-cvr-welcome-email-fix
[codex] Fix register CVR welcome email rendering
2026-06-11 21:22:28 +02:00
Jeppe B af8968a87e Merge pull request #281 from copenhagentruckwash/codex/customer-registration-notifications
Add Slack customer registration webhook test endpoint
2026-06-11 15:18:07 +02:00
Jeppe B b5c24ef80a Merge pull request #280 from copenhagentruckwash/fix/self-serve-path-outcome-case-limit
Fix self-serve path outcome case limit
2026-06-11 14:57:16 +02:00
Jeppe B bdb1a0074b Merge pull request #279 from copenhagentruckwash/fix/self-serve-customer-property-gates
Allow customers to open property gates for active washes
2026-06-10 22:00:06 +02:00
Jeppe B 574b263a54 Merge pull request #278 from copenhagentruckwash/fix/self-serve-start-wash-type
Honor wash type in self-serve lane start
2026-06-10 20:07:46 +02:00
Jeppe B 36ff5bb438 Merge pull request #277 from copenhagentruckwash/fix-completion-confirmation-route
Add order booking completion confirmation resend route
2026-06-10 20:07:30 +02:00
Jeppe B d605eca574 Fallback composer installs to source in CI 2026-06-10 19:22:52 +02:00
Jeppe B 7e85c74e60 Retry composer installs in CI 2026-06-10 19:12:12 +02:00
Jeppe B 67d62eff70 Sync fake email deliveries across API tests 2026-06-10 18:53:13 +02:00
Jeppe B 8ebbd52a99 Normalize attachment object type lookups 2026-06-10 18:40:34 +02:00
Jeppe B 6d6cc501db Force completion confirmation resend email 2026-06-10 18:33:53 +02:00
Jeppe B ce999afbb3 Fix MinIO local test storage fallback 2026-06-10 18:22:53 +02:00
Jeppe B cb34b030c8 Add order booking completion confirmation resend route 2026-06-10 17:55:57 +02:00
Jeppe B 6f1c160fbb Sync generated Copilot workflow 2026-06-03 20:57:06 +02:00
Jeppe B bcbc2481c3 Source self-serve lane products from published config 2026-06-02 19:05:06 +02:00
Jeppe B 8288a1069c Merge pull request #276
coolify-github-runner-management
2026-06-02 17:27:42 +02:00
Jeppe B f7485f0767 Merge pull request #273 from copenhagentruckwash/update-self-serve-lane-command-access-logic
Allow customer self-serve lane commands
2026-06-02 10:22:21 +02:00
Jeppe B 1468e43ce2 Merge pull request #272 from copenhagentruckwash/add-endpoint-to-resend-booking-confirmations
Add booking confirmation resend endpoint
2026-06-02 10:12:29 +02:00
Jeppe B ee2af5091c Retry CI docker compose startup 2026-06-02 10:08:01 +02:00
Jeppe B 0672a68e8b Merge pull request #274 from copenhagentruckwash/update-self-serve-lane-command-access-logic-bft43z
Support customer self-serve lane commands with operational/department checks and tests
2026-06-02 10:07:27 +02:00
Jeppe B b92d1f0bdf Fix self-serve lane command API tests 2026-06-02 09:52:44 +02:00
Jeppe B ac60596218 Fix booking confirmation resend test fixture 2026-06-02 09:36:36 +02:00
Jeppe B f4b9d71d40 Merge pull request #270 from copenhagentruckwash/add-customer-self-serve-module-authorization-checks
Guard customer self-serve command fallback behind global module flag
2026-06-02 09:25:00 +02:00
Jeppe B 77b1c8ec78 Merge pull request #271 from copenhagentruckwash/inspect-command-authorization-for-self-serve-route
Authorize self-serve lane commands by customer scope and operator permission
2026-06-02 09:24:38 +02:00
Jeppe B 01221d8282 Allow customer self-serve lane commands 2026-06-02 09:24:33 +02:00
Jeppe B 47068e6d7e Add booking confirmation resend endpoint 2026-06-02 09:15:34 +02:00
Jeppe B 46bdeded78 Fix self-serve lane command customer authorization 2026-06-02 09:15:24 +02:00
Jeppe B eefa521fc5 Guard customer self-serve commands behind module flag 2026-06-02 09:14:57 +02:00
Jeppe B ec1988715d Merge pull request #269 from copenhagentruckwash/fix-parse-error-in-index.php
Handle Release Manager gate parse-error deadlock
2026-06-02 02:53:54 +02:00