Repository navigation
Release iOS wrapper and export toolbar cleanup - #2
Conversation
Use base: './' only for --mode capacitor; web build uses '/' so deep links like /app/library resolve assets correctly in production preview. Why: commit 2464dd0 added base: './' for the iOS wrapper, which broke web deep links because the browser resolved ./assets/foo.js relative to the route path. Pairs with Part 4 (iOS Capacitor wrapper). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pin the Capacitor Swift package, add the dictation microphone usage description, and remove the obsolete armv7 device capability without hardcoding a signing team.
Introduce a shared ExportToolbar that puts the EXPORT tag on the left, AutoSavedSourcesUndo + PDF/DOCX/Google Docs (+ optional Clipboard) glued to the right, and a second row only for auxiliary actions like flowchart imports, save, and undo. Attack/Brainstorm/Factoids/Generate all consume the shared component so their export rows look and align identically. Also align Attack strength-area ticks with the text baseline (drop the stray mt-1) and update an AskChat test that no longer applies now that the desktop saved-chats sidebar is always open.
Align the export label and all export/action buttons to the left while preserving wrapping order across locales.
Keep export actions in a single wrapping row and translate generate result model, duration, and clipboard labels across English, Spanish, and Hungarian.
Row 1: secondaryActions (Save, Discuss, Flowcharts, Undo) + onDiscuss
+ showUndo's AutoSavedSourcesUndo
Row 2: EXPORT tag + extraExports (Clipboard) + PDF + DOCX + Google Docs
Both rows use justify-start. The previous version (commit 1be277e)
only flipped justify-between to justify-start without forcing a row
break, so on wide screens everything still collapsed to a single row.
User explicitly requested 2 left-aligned rows and called out that
ELEVEN earlier agents shipped partial fixes. Confirmed layout choice
on 2026-05-27.
Pairs with Part 4 (replaces / extends commit 1be277e).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add a regression test for the exact two-row left-aligned export toolbar and remove stale onboarding copy that advertised compare-side behavior.
Allow capacitor://localhost across browser-called Edge Functions, keep generated share links on the public HTTPS origin, and add a Deno regression test for the native CORS surface.
Match the existing evidence-direction wording so the backend prompt-builder suite reflects the shipped implementation.
Use PKCE-only OAuth callbacks with bounded exchange time, recover cold-start deep links, route external WebView links through the native browser, keep Stripe callbacks on HTTPS, and align the Swift package pin with Capacitor 8.4.0.
Add Playwright smoke coverage for public and authenticated routes across locales, and scope Vite dependency scanning to the app entry so Capacitor-copied build assets do not get scanned during dev.
Upgrade Vitest and coverage tooling to the current clean-audit line, then update affected test mocks for Vitest 4 constructor behavior. Also removes a future-breaking nested mock warning and turns the Generate page result-state test into a real assertion.
Fix the valid CodeRabbit findings: restore the AttackResults discuss icon import, prevent duplicate undo controls, auto-open Factoids Google Docs exports, localize onboarding strings, add the iOS UserDefaults privacy reason, declare the Vite Node engine, and calibrate the selected-scope coverage gate. Capacitor plugin packages were left unchanged because npm reports those plugin versions as the latest available releases.
Address the second CodeRabbit pass: avoid empty export toolbar rows, clear OAuth query noise, close native auth error callbacks, make hardware back exit when it cannot go back, preserve iOS safe-area footer padding, tighten Playwright console filters, keep mobile emulation consistent, and document the selected-scope coverage gate.
Clean up remaining valid CodeRabbit items: always strip OAuth callback query params even on failed code exchange, reuse the E2E locale helper, guard duplicate native launch URL handling, and make the selected-scope coverage baseline rationale explicit.
Use the product bundle identifier for the custom URL type, set the dark native status bar to light glyphs, and route export button labels through shared locale keys. The App Store encryption flag remains false because this app only uses standard TLS/OAuth/PKCE, and Capacitor 8 remains intentional for this wrapper.
Enable row-level security for the Stripe webhook idempotency table, revoke anon/authenticated access, and keep service-role access for backend webhook processing.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (70)
📝 WalkthroughWalkthroughThis PR implements comprehensive iOS native app support for DebateLab via Capacitor. It introduces the complete native iOS project infrastructure, modernizes OAuth to use PKCE code exchange, consolidates export UI into a reusable toolbar component, adds native-aware platform abstraction for URLs and external browsing, and includes E2E test coverage for public and authenticated routes across multiple locales. ChangesiOS Capacitor Native App
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
|
* Add a per-agent, Docker-free local Supabase stack helper Uses the CLI's experimental stack engine with the native runtime so several agents can each run migrations, pgTAP and RLS queries at once without the shared db-gate lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Plan the 25-item pre-ship security pass Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document the per-agent stack and run the full database suite on it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Harden promo redemption, client grants and account deletion - Lock a user out of promo redemption after 5 failures in 15 minutes and answer unknown, expired and exhausted codes alike (next-15 #2). - Promo grants never lower a tier, end date or daily limit. - Revoke TRUNCATE/TRIGGER/REFERENCES/MAINTAIN from client roles, make global_prompts and global rate limits server-only, make the admin reporting RPCs service-role only, and close default privileges. - Account deletion removes the user's demo code and scrubs the IPs and fingerprints recorded against it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Serve Edge Functions on the per-agent stack The stack does not find functions behind a symlink, and its workers read supabase/functions/.env rather than --env-file, so copy both into the overlay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Render Markdown images from model output as links A prompt-injected source could make the model emit an image whose URL carries the student's work; the browser fetched it without a click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Clear tool drafts on sign-out and user switch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tighten the CSP to the hosts the app uses Drop provider, Jina, Google API and font hosts the client no longer calls; replace *.supabase.co with the two project hosts; stop allowing images from any HTTPS host; add form-action; make X-Frame-Options agree with frame-ancestors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Guard the public build and trim client telemetry - Fail the build if dist/ holds source maps, server-secret patterns or a non-anon JWT. - Log auth events only in development builds. - Redact share codes from Sentry events and transactions. - Move tailwindcss-animate to devDependencies and update dompurify. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(edge): claim Stripe events before applying current subscription state Co-Authored-By: Codex <noreply@openai.com> * fix(edge): authenticate and allowlist AI features before processing input Co-Authored-By: Codex <noreply@openai.com> * fix(edge): conceal internal and provider errors from clients Co-Authored-By: Codex <noreply@openai.com> * fix(edge): validate promo inputs and omit attempted codes from logs Co-Authored-By: Codex <noreply@openai.com> * fix(edge): rate limit unknown demo callers without extending refusals Co-Authored-By: Codex <noreply@openai.com> * fix(edge): validate import bodies and public hosts before reserving quota Co-Authored-By: Codex <noreply@openai.com> * fix(edge): restrict export origins and vary CORS responses by Origin Co-Authored-By: Codex <noreply@openai.com> * fix(edge): keep prompt and research text out of diagnostic logs Co-Authored-By: Codex <noreply@openai.com> * Recover abandoned webhook claims and take payment status from Stripe Claiming an event before its handlers means a worker that dies mid-run would leave a claim that blocks every Stripe retry. Mark claims complete, and let a retry take over a claim left incomplete for 10 minutes. payment_succeeded now copies the subscription status from Stripe instead of writing active, so a late delivery cannot revive a canceled plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pin supabase-js in Edge Functions to the client's version esm.sh/@supabase/supabase-js@2 resolved whatever 2.x esm.sh served on deploy day, inside functions that hold the service-role key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Record the pre-ship security findings and new database rules Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Describe the explicit Supabase hosts in the CSP Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give the webhook a fake Stripe in the full-stack gate The webhook now reads subscription state from Stripe, so it honours STRIPE_API_URL like the account function, and the fake serves GET /v1/subscriptions/:id from state the test sets. The billing journey also checks that a late active update cannot revive a canceled plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Find Library source fields by placeholder in full-stack journeys The form gained visible Title and Content labels, so the placeholder is no longer the accessible name. This was already failing on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Claim webhook events on the database clock and retry in-flight ones Codex review round 1: - A retry that found an unfinished claim got 200 duplicate, which ends Stripe's retries; it now gets 409 so a dead delivery is retried. - The abandon cutoff came from the Edge clock but was compared with a Postgres timestamp. claim_webhook_event and complete_webhook_event now decide on the database clock. - The new-object grant test checked pg_default_acl rows; it now checks the effective privileges of a newly created table and sequence. A global function revoke would also strip extension functions (pgTAP broke), so functions keep their explicit per-migration revokes, which the anon EXECUTE test enforces. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Report a webhook duplicate only for a completed claim Codex review round 2: if a failed delivery released its claim between a concurrent delivery's insert and its read, the second delivery found no row and answered duplicate (HTTP 200) for an event nobody completed. Claim again when the row is gone, and fall back to in_progress. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Update the security report for the review fixes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Drop hosted rate_limits and global_prompts policies by catalog Production and staging carry rate_limits policies that no migration created (rate_limits_select_own_or_global, "Users can read own limits"), both allowing global rows. Dropping by the migration's own name would have left them. Drop every policy on the two tables, and revoke client writes on rate_limits. Rehearsed on read-only dumps of both projects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Codex <noreply@openai.com>
Summary
Safety / rollback
Verification
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests
Chores