feat(waiter): native app runs each venue's own UI bundle (self-hosted updater)
@capgo/capacitor-updater (MPL-2.0) in manual mode: autoUpdate off, stats/update/channel URLs empty (nothing contacts Capgo), appReadyTimeout 15s (auto rollback), resetWhenUpdate (APK update → built-in bundle, venue bundle re-fetched), autoDeletePrevious off (we keep one per venue). src/native/bundles.js syncVenueBundle(): - manifest fetched over the pinned TLS link; zip downloaded natively over the LAN HTTP port with the MANDATORY sha256 check - a tampered zip never runs - applied at once only when nobody is mid-service (after pairing / venue switch, or no one logged in); otherwise staged with next() → applied at the next background/restart; never a mid-service reload - APK too old for the bundle (min_shell_build) → skipped + update banner linking to the venue's /downloads/xenia-waiter.apk - a rolled-back version is blocklisted (attempt tracking + grace window) - without it the app re-applied the still-advertised broken bundle in a loop - server without bundles (404) → built-in UI; bundles no venue needs deleted BundleSync: notifyAppReady on start; sync at start, on resume, every 30 min. saveVenue merges fields (bundleVersion); switchVenue flags immediate apply. E2E (emulator vs two isolated venue stacks): fresh pairing applies the venue bundle and it stays healthy; logged-in update staged, applied after background, session kept; tampered zip refused; shell-too-old banner; broken bundle rolled back automatically and not retried (80s + resume); two venues each run their own bundle, round trips served from cache with 0 downloads, stale bundles cleaned; no *.capgo.app traffic. Step 5/7-era rediscovery + cold-start suites and web modes still pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Generated
+18
@@ -11,6 +11,7 @@
|
||||
"@capacitor/android": "^8.5.2",
|
||||
"@capacitor/app": "^8.1.1",
|
||||
"@capacitor/core": "^8.5.2",
|
||||
"@capgo/capacitor-updater": "^8.51.25",
|
||||
"@tanstack/react-query": "^5.100.11",
|
||||
"axios": "^1.15.1",
|
||||
"dexie": "^4.4.2",
|
||||
@@ -31,6 +32,7 @@
|
||||
"eslint": "^9.39.4",
|
||||
"eslint-plugin-react-hooks": "^7.1.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
"fflate": "^0.8.3",
|
||||
"globals": "^17.5.0",
|
||||
"vite": "^8.0.9"
|
||||
}
|
||||
@@ -1584,6 +1586,15 @@
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capgo/capacitor-updater": {
|
||||
"version": "8.51.25",
|
||||
"resolved": "https://registry.npmjs.org/@capgo/capacitor-updater/-/capacitor-updater-8.51.25.tgz",
|
||||
"integrity": "sha512-lznyAv9Ktl1CD6/OKZY+lQZl9ke+dbadLEB2XQKP7VbQO8/5D8yOHS+pysQgVnNkiZYEC3v1AxgY4a5Z+DnxXw==",
|
||||
"license": "MPL-2.0",
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz",
|
||||
@@ -3852,6 +3863,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fflate": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
|
||||
"integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||
|
||||
Reference in New Issue
Block a user