Files
pleno-vue/package.json
T
Jeppe B 88eda43560 Automate signed iOS App Store releases (#192)
## What changed

- adds production iOS identity, localized storefront metadata, native
privacy declarations, App Store-safe artwork, and account-deletion UX
- mirrors the live Danish Google Play title, short description, and long
description in the App Store metadata source
- generates Android launcher/store icons from the opaque iOS marketing
master so both platforms use the same white background
- adds guarded GitHub Actions workflows for storefront readiness,
credential health, signed TestFlight uploads, and App Store candidate
preparation
- adds pinned Fastlane configuration with a committed dependency lock,
release manifest tooling, and an operational App Store runbook
- preserves the upstream iOS safe-area implementation while retaining
opaque App Store icon assets

## Why

The repository previously supported development-signed device bundles
but had no production App Store identity, reproducible storefront source
of truth, or protected signed-release pipeline. Apple also requires
in-app account deletion for apps that support account creation. The
Android icon master was transparent, which rendered as black on dark
store/device surfaces.

## Impact

Automation remains fail-closed behind
`APP_STORE_AUTOMATION_ENABLED=false`. No build can upload to TestFlight
or change App Store metadata until the switch is deliberately enabled
after merge and the remaining release gates are satisfied.

## Validation

- focused App Store, iOS icon, and cross-platform icon-background tests
pass
- every generated Android store/launcher icon is opaque with pure-white
corners; iOS marketing artwork is checked the same way
- Android icon drift check passes for all 19 generated files
- production Vite build and the broader focused release checks completed
successfully
- storefront metadata is valid; only the two expected screenshot-set
warnings remain
- App Store Readiness is green at head `4445fecc`
- Apple Distribution certificate and App Store profile were
independently verified for `HP3FJ4GVL7.io.truckwash.app`
- live App Store Connect API authentication succeeded for app
`6792777794`
- App Store record, free Denmark-only availability, and automatic
`Internal QA` TestFlight group are configured
- EU trader status, Content Rights, 4+ age rating, and the published App
Privacy label are completed in App Store Connect
- iPhone and iPad accessibility declarations are configured honestly as
pre-release drafts

## Remaining external gates

- reviewed iPhone and iPad screenshot sets are still required
- an App Review login must be supplied without creating or exposing
customer credentials
- the first signed TestFlight candidate must run after merge and
deliberate automation enablement
2026-07-20 17:59:43 +02:00

171 lines
8.6 KiB
JSON

{
"name": "truckwashdashboardsfrontend",
"version": "0.0.0",
"web-types": "./web-types.json",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"build:dev": "vite build --mode development",
"lint": "eslint eslint.config.js src tests scripts vite.config.js vitest.config.js playwright*.ts --quiet",
"lint:strict": "npm run lint:report -- --max-warnings=0",
"lint:report": "eslint eslint.config.js src tests scripts vite.config.js vitest.config.js playwright*.ts",
"format:tests": "prettier --write \"tests/**/*.{js,ts}\"",
"format:tests:commit": "node scripts/pre-commit-format-tests.mjs",
"format:tests:check": "prettier --check \"tests/**/*.{js,ts}\"",
"prepare": "node scripts/prepare-husky.mjs",
"preview": "vite preview",
"preview:prod": "npm run build && npm run preview -- --host 127.0.0.1 --port 4173",
"text:fix-encoding": "node scripts/text-encoding.mjs fix",
"text:check-encoding": "node scripts/text-encoding.mjs check",
"i18n:v2:compile": "node scripts/i18n-v2-compile-source.mjs",
"i18n:v2:source-check": "node scripts/i18n-v2-compile-source.mjs --check",
"i18n:v2:check": "npm run i18n:v2:source-check && npm run i18n:v2:global-template-audit && npm run i18n:v2:template-dedupe-audit && npm run i18n:v2:word-audit",
"i18n:v2:word-audit": "node scripts/i18n-v2-word-dedupe.mjs",
"i18n:v2:word-dedupe": "node scripts/i18n-v2-word-dedupe.mjs --apply",
"i18n:v2:global-template-audit": "node scripts/i18n-v2-globalize-templates.mjs",
"i18n:v2:globalize-templates": "node scripts/i18n-v2-globalize-templates.mjs --apply",
"i18n:v2:template-dedupe-audit": "node scripts/i18n-v2-template-dedupe.mjs",
"i18n:v2:template-dedupe": "node scripts/i18n-v2-template-dedupe.mjs --apply",
"test:unit": "npm run text:check-encoding && npm run test:unit:fast && npm run test:unit:serial",
"test:unit:fast": "node scripts/run-vitest-unit-fast.mjs",
"test:unit:serial": "node scripts/run-vitest-unit-batches.mjs --from-list tests/unit/serial-tests.txt",
"test:unit:single": "vitest run",
"test:e2e": "npm run test:e2e:matrix --",
"test:e2e:matrix": "playwright test",
"test:e2e:pr": "node scripts/run-playwright-pr.mjs",
"test:e2e:changed": "node scripts/run-playwright-pr.mjs --changed-only",
"test:e2e:i18n:views": "playwright test tests/e2e/i18n.views.spec.ts --project=chromium-desktop",
"test:e2e:ci": "node scripts/run-playwright-ci-parallel.mjs",
"test:e2e:full:slice": "node scripts/run-playwright-full-slice.mjs",
"test:e2e:ci:serial": "playwright test --reporter=line,html",
"test:e2e:batched:chromium": "node scripts/run-playwright-batched-chromium.mjs",
"test:e2e:batched:chromium:rerun-failed": "node scripts/run-playwright-batched-chromium.mjs --rerun-failed",
"test:e2e:smoke": "playwright test --grep @smoke --project=chromium-desktop --project=chromium-mobile",
"test:e2e:prod": "playwright test --config=playwright.prod.config.ts",
"test:e2e:live": "playwright test --config=playwright.live.config.ts",
"test:e2e:live:public": "playwright test --config=playwright.live.config.ts --grep @public-live",
"test:e2e:live:roles": "playwright test --config=playwright.live.config.ts --grep @role-live",
"test:e2e:release": "npm run test:e2e:prod && npm run test:e2e:live",
"test:ct": "playwright test --config=playwright.ct.config.ts",
"test:ct:pr": "playwright test --config=playwright.ct.config.ts --project=chromium-desktop",
"release:package": "node scripts/release/package-dist.mjs",
"release:deploy:cpanel": "node scripts/release/deploy-cpanel.mjs",
"release:deploy:cpanel:rollback": "node scripts/release/deploy-cpanel.mjs --rollback",
"release:cpanel-root:audit": "node scripts/release/cpanel-root.mjs audit",
"release:cpanel-root:restore": "node scripts/release/cpanel-root.mjs restore",
"release:verify-upload": "node scripts/release/verify-upload.mjs",
"release:update-server-version": "node scripts/release/update-server-version.mjs",
"release:upload:lftp": "bash scripts/release/upload-dist-lftp.sh",
"test:e2e:pos-mobile-live": "node -e \"const { spawnSync } = require('child_process'); const result = spawnSync('npx', ['playwright', 'test', 'tests/e2e/adminModulePosMobileOrderFlow.spec.ts', '--project=chromium-mobile'], { stdio: 'inherit', shell: true, env: { ...process.env, PLAYWRIGHT_LIVE: '1' } }); process.exit(result.status ?? 1);\"",
"test:all": "npm run test:unit && npm run test:ct:pr && npm run test:e2e:pr",
"twa:build": "bubblewrap build",
"twa:update": "bubblewrap update",
"mobile:sync": "npm run build && npx cap sync",
"mobile:android:icons": "node scripts/mobile/generate-android-icons.mjs",
"mobile:android:icons:check": "node scripts/mobile/generate-android-icons.mjs --check",
"mobile:android:sync": "npm run mobile:android:icons && npm run build && npx cap sync android",
"mobile:permissions:check": "node scripts/mobile/check-permissions.mjs",
"mobile:store:env-check": "node scripts/mobile/check-store-upload-env.mjs",
"mobile:android:signing:check": "node scripts/mobile/check-android-signing-env.mjs",
"mobile:android:bundle": "npm run mobile:android:signing:check && npm run mobile:android:sync && npm run mobile:permissions:check && cd android && ./gradlew bundleRelease",
"mobile:android:bundle:unsigned": "npm run mobile:android:sync && npm run mobile:permissions:check && cd android && ./gradlew bundleRelease",
"mobile:android:play-upload": "node scripts/mobile/upload-google-play.mjs",
"mobile:ios:sync": "npm run mobile:sync && npm run mobile:permissions:check",
"mobile:ios:device": "node scripts/mobile/ios-device.mjs",
"mobile:ios:storefront:check": "node scripts/mobile/validate-app-store.mjs",
"mobile:ios:storefront:check-strict": "node scripts/mobile/validate-app-store.mjs --strict",
"playstore:graphics": "node scripts/playstore/generate-graphics.mjs"
},
"dependencies": {
"@azure/msal-browser": "^4.12.0",
"@bubblewrap/cli": "^1.24.1",
"@capacitor/core": "^8.4.1",
"@capacitor/geolocation": "^8.2.0",
"@creativebulma/bulma-badge": "^1.0.1",
"@fullcalendar/core": "^6.1.17",
"@fullcalendar/daygrid": "^6.1.17",
"@fullcalendar/interaction": "^6.1.17",
"@fullcalendar/list": "^6.1.17",
"@fullcalendar/timegrid": "^6.1.17",
"@fullcalendar/vue3": "^6.1.17",
"@popperjs/core": "^2.11.8",
"@sweetalert2/theme-bulma": "^5.0.18",
"@sweetalert2/theme-dark": "^5.0.18",
"@vue-flow/core": "^1.43.1",
"@vueuse/core": "^12.7.0",
"@vueuse/head": "^2.0.0",
"@vueuse/integrations": "^13.7.0",
"@xterm/addon-fit": "^0.11.0",
"animate.css": "^4.1.1",
"apexcharts": "^5.10.4",
"axios": "1.18.1",
"buefy": "^3.0.3",
"bulma": "^1.0.2",
"bulma-block-list": "^1.1.0",
"bulma-calendar": "^7.1.1",
"bulma-list": "^3.0.0",
"bulma-o-steps": "^1.1.0",
"bulma-pageloader": "^0.3.0",
"bulma-quickview": "^2.0.0",
"bulma-switch": "^2.0.4",
"chart.js": "^4.4.7",
"dayspan-vuetify": "^0.4.0",
"flow": "^0.2.3",
"html2canvas": "^1.4.1",
"qrcode": "^1.5.4",
"sass": "^1.81.1",
"sweetalert2": "11.22.4",
"tesseract.js": "^6.0.1",
"toastify-js": "^1.12.0",
"vite-plugin-singlefile": "^2.1.0",
"vue": "^3.5.12",
"vue-cal": "^5.0.1-rc.20",
"vue-chartjs": "^5.3.2",
"vue-i18n": "^9.14.5",
"vue-popperjs": "^2.3.0",
"vue-qrcode-reader": "^5.7.3",
"vue-router": "^4.5.0",
"vue-toast-notification": "^3.1.3",
"vue3-apexcharts": "^1.11.1",
"vue3-cookies": "^1.0.6",
"vuex": "^4.1.0",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
"xterm": "^5.3.0"
},
"devDependencies": {
"@capacitor/android": "^8.4.1",
"@capacitor/cli": "^8.4.1",
"@capacitor/ios": "^8.4.1",
"@creativebulma/bulma-divider": "^1.1.0",
"@eslint/js": "^10.0.1",
"@event-calendar/core": "^4.1.0",
"@playwright/experimental-ct-vue": "^1.58.2",
"@playwright/test": "^1.58.2",
"@types/event-calendar__core": "^3.7.0",
"@vitejs/plugin-vue": "^6.0.5",
"@vitejs/plugin-vue-jsx": "^5.1.5",
"@vue/test-utils": "^2.4.6",
"eslint": "^10.4.1",
"eslint-plugin-vue": "^10.9.2",
"globals": "^17.6.0",
"husky": "^9.1.7",
"jimp": "0.22.12",
"jsdom": "^29.0.0",
"otpauth": "^9.5.0",
"prettier": "2.8.8",
"sass-embedded": "^1.81.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.60.1",
"vite": "8.1.5",
"vite-plugin-pwa": "^1.3.0",
"vite-plugin-vue-devtools": "^7.5.4",
"vitest": "^4.1.10",
"vue-eslint-parser": "^10.3.0"
},
"overrides": {
"tar": "7.5.19"
}
}