Conversation
- Added unit tests for the History and Overview components using Vitest and Testing Library, improving test coverage and reliability. - Introduced contract tests to ensure OpenAPI paths align with expected schemas, enhancing API stability. - Implemented visual regression tests with Playwright to capture UI changes and maintain visual consistency. - Updated README and ROADMAP to reflect new testing capabilities and deployment instructions, including a full staging pipeline command. - Upgraded Wrangler to version 4 across the project for improved development experience.
- Updated session list caching to use a 60s TTL in Cloudflare KV with a 15s HTTP max-age for responses, improving cache efficiency. - Introduced a new utility function `isSessionId` for validating session IDs against a UUID format. - Enhanced session retrieval routes to validate session IDs before processing requests, ensuring better error handling. - Refactored cache-related functions to handle errors gracefully, maintaining API reliability. - Updated documentation to reflect changes in caching strategy and session ID validation.
- Integrated PWA capabilities using vite-plugin-pwa, enabling offline access and caching for session data. - Added i18n support with react-i18next, providing English translations for navigation and session details. - Implemented a scorecard export feature, allowing users to generate print-ready scorecards for sessions. - Introduced an OfflineBanner component to notify users when offline, enhancing user experience. - Updated package dependencies to include necessary libraries for analytics and query persistence. - Enhanced documentation to reflect new features and usage instructions.
… updates - Updated the `FileField` component to include a visible button for file selection, improving user experience. - Implemented state management to display the selected file name, enhancing feedback for users. - Modified tooltip descriptions in the documentation to clarify the new file input pattern and usage guidelines. - Ensured accessibility by maintaining proper aria attributes and labels for the file input.
There was a problem hiding this comment.
3 issues found across 53 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/web/vite.config.ts">
<violation number="1" location="apps/web/vite.config.ts:60">
P1: API read caching can fail at runtime because this matcher closes over `apiOrigin`, but generateSW serializes matcher functions into the service worker without outer-scope variables. Using a self-contained RegExp/string matcher here keeps route matching valid in the generated sw.js.</violation>
</file>
<file name="apps/web/src/main.tsx">
<violation number="1" location="apps/web/src/main.tsx:19">
P1: Session/history cache can leak across venue/account switches because persisted React Query data is stored under one global localStorage key while query keys are not owner-scoped. Scoping the persistence key by current owner/api key (or clearing persisted cache on venue switch) would prevent cross-owner stale data from being restored.</violation>
</file>
<file name="apps/web/vite.config.js">
<violation number="1" location="apps/web/vite.config.js:59">
P1: Session list/detail responses can leak between venues on a shared browser because the new service-worker cache stores authenticated `/sessions*` responses by URL. This route is called with per-owner auth headers, so excluding authenticated requests from runtimeCaching (or keying cache by auth identity) would avoid cross-owner stale/private data reuse.</violation>
</file>
You're on the cubic free plan with 17 free PR reviews remaining this month. Upgrade for unlimited reviews.
Re-trigger cubic
| navigateFallbackDenylist: [/^\/docs\//], | ||
| runtimeCaching: [ | ||
| { | ||
| urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname), |
There was a problem hiding this comment.
P1: API read caching can fail at runtime because this matcher closes over apiOrigin, but generateSW serializes matcher functions into the service worker without outer-scope variables. Using a self-contained RegExp/string matcher here keeps route matching valid in the generated sw.js.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/vite.config.ts, line 60:
<comment>API read caching can fail at runtime because this matcher closes over `apiOrigin`, but generateSW serializes matcher functions into the service worker without outer-scope variables. Using a self-contained RegExp/string matcher here keeps route matching valid in the generated sw.js.</comment>
<file context>
@@ -21,7 +31,45 @@ function injectPreconnect(): PluginOption {
+ navigateFallbackDenylist: [/^\/docs\//],
+ runtimeCaching: [
+ {
+ urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname),
+ handler: 'NetworkFirst',
+ options: {
</file context>
| urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname), | |
| urlPattern: new RegExp(`^${apiOrigin().replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/sessions(?:/|$|\\?)`), |
|
|
||
| const persister = createSyncStoragePersister({ | ||
| storage: window.localStorage, | ||
| key: 'oche-query-cache', |
There was a problem hiding this comment.
P1: Session/history cache can leak across venue/account switches because persisted React Query data is stored under one global localStorage key while query keys are not owner-scoped. Scoping the persistence key by current owner/api key (or clearing persisted cache on venue switch) would prevent cross-owner stale data from being restored.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/src/main.tsx, line 19:
<comment>Session/history cache can leak across venue/account switches because persisted React Query data is stored under one global localStorage key while query keys are not owner-scoped. Scoping the persistence key by current owner/api key (or clearing persisted cache on venue switch) would prevent cross-owner stale data from being restored.</comment>
<file context>
@@ -1,14 +1,24 @@
+
+const persister = createSyncStoragePersister({
+ storage: window.localStorage,
+ key: 'oche-query-cache',
+});
+
</file context>
| navigateFallbackDenylist: [/^\/docs\//], | ||
| runtimeCaching: [ | ||
| { | ||
| urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname), |
There was a problem hiding this comment.
P1: Session list/detail responses can leak between venues on a shared browser because the new service-worker cache stores authenticated /sessions* responses by URL. This route is called with per-owner auth headers, so excluding authenticated requests from runtimeCaching (or keying cache by auth identity) would avoid cross-owner stale/private data reuse.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/vite.config.js, line 59:
<comment>Session list/detail responses can leak between venues on a shared browser because the new service-worker cache stores authenticated `/sessions*` responses by URL. This route is called with per-owner auth headers, so excluding authenticated requests from runtimeCaching (or keying cache by auth identity) would avoid cross-owner stale/private data reuse.</comment>
<file context>
@@ -20,7 +30,45 @@ function injectPreconnect() {
+ navigateFallbackDenylist: [/^\/docs\//],
+ runtimeCaching: [
+ {
+ urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname),
+ handler: 'NetworkFirst',
+ options: {
</file context>
| urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname), | |
| urlPattern: ({ url, request }) => | |
| url.origin === apiOrigin() && | |
| /^\/sessions(\/|$|\?)/.test(url.pathname) && | |
| !request.headers.has('authorization') && | |
| !request.headers.has('x-oche-owner'), |
Summary by cubic
Raises quality and DX with unit, contract, and visual tests plus a one-command staging deploy. Also ships an offline-ready PWA, i18n, scorecard export, and static OpenAPI docs.
New Features
vite-plugin-pwawith WorkboxNetworkFirstforGET /sessions*, React Query persistence, and anOfflineBannerthat hides mutations when offline.exportSessionScorecard()and a header button on Session Detail.react-i18nextwith anenlocale for nav and session detail; scorecard labels localized.scripts/export-openapi.mjscreatesapps/web/public/openapi.json; Redoc served at/docs/.FileFielduses a hidden input + visible button and shows the selected filename.Refactors
vitest+@testing-library/react), OpenAPI contract tests, and Playwright visual snapshots.max-age=15; best‑effort KV writes;X-Cacheretained.isSessionIdUUID check added to session routes for cleaner 404s.npm run deploy:staging:full(migrate → force-rls → rls check → seed → deploy); README quick start updated.^4; addedvite-plugin-pwa,react-i18next,@tanstack/react-query-persist-client, and optional analytics (VITE_PLAUSIBLE_DOMAINorVITE_CF_WEB_ANALYTICS_TOKEN).Written for commit 796efd1. Summary will update on new commits.