Skip to content

Tier-6 - #3

Merged
Hum2a merged 5 commits into
tier-5from
tier-6
Jul 3, 2026
Merged

Tier-6#3
Hum2a merged 5 commits into
tier-5from
tier-6

Conversation

@Hum2a

@Hum2a Hum2a commented Jul 3, 2026

Copy link
Copy Markdown
Owner
  • 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.

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

    • Offline read-only PWA: vite-plugin-pwa with Workbox NetworkFirst for GET /sessions*, React Query persistence, and an OfflineBanner that hides mutations when offline.
    • Scorecard export: print-ready HTML via exportSessionScorecard() and a header button on Session Detail.
    • i18n: react-i18next with an en locale for nav and session detail; scorecard labels localized.
    • API docs: scripts/export-openapi.mjs creates apps/web/public/openapi.json; Redoc served at /docs/.
    • File input UX: FileField uses a hidden input + visible button and shows the selected filename.
  • Refactors

    • Testing: component tests for History and Overview (vitest + @testing-library/react), OpenAPI contract tests, and Playwright visual snapshots.
    • Caching: KV TTL set to 60s (Cloudflare minimum) with HTTP max-age=15; best‑effort KV writes; X-Cache retained.
    • Validation: isSessionId UUID check added to session routes for cleaner 404s.
    • Deploy DX: npm run deploy:staging:full (migrate → force-rls → rls check → seed → deploy); README quick start updated.
    • Dependencies: Wrangler upgraded to ^4; added vite-plugin-pwa, react-i18next, @tanstack/react-query-persist-client, and optional analytics (VITE_PLAUSIBLE_DOMAIN or VITE_CF_WEB_ANALYTICS_TOKEN).

Written for commit 796efd1. Summary will update on new commits.

Review in cubic

Hum2a and others added 5 commits July 3, 2026 13:41
- 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.
@Hum2a
Hum2a merged commit 3a9f531 into tier-5 Jul 3, 2026
1 check failed

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread apps/web/vite.config.ts
navigateFallbackDenylist: [/^\/docs\//],
runtimeCaching: [
{
urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Suggested change
urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname),
urlPattern: new RegExp(`^${apiOrigin().replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/sessions(?:/|$|\\?)`),

Comment thread apps/web/src/main.tsx

const persister = createSyncStoragePersister({
storage: window.localStorage,
key: 'oche-query-cache',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>

Comment thread apps/web/vite.config.js
navigateFallbackDenylist: [/^\/docs\//],
runtimeCaching: [
{
urlPattern: ({ url }) => url.origin === apiOrigin() && /^\/sessions(\/|$|\?)/.test(url.pathname),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Suggested change
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'),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant