-
Notifications
You must be signed in to change notification settings - Fork 1
fix(auth): no sign-in error toast on storage-blocking browsers; App Store 1.0 metadata & screenshots #163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
fix(auth): no sign-in error toast on storage-blocking browsers; App Store 1.0 metadata & screenshots #163
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
6045c42
fix(frontend): disable Clerk quietly when the browser denies site sto…
WilliamAGH 320823d
chore(git): ignore transient asc run state and screenshot working art…
WilliamAGH 3285a36
chore(asc): add App Store Connect CLI workflow and screenshot config
WilliamAGH 266c606
chore(metadata): add canonical App Store metadata for version 1.0
WilliamAGH c76ba54
chore(screenshots): add validated App Store screenshots and captions
WilliamAGH be4c316
chore(git): ignore stray debug captures at the screenshots root
WilliamAGH a290c4c
docs(frontend): align loadClerkAuthentication @throws with actual beh…
WilliamAGH 25cba93
test(frontend): restore inherited localStorage after storage-denial t…
WilliamAGH File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "version": 1, | ||
| "app": { | ||
| "bundle_id": "ai.javachat", | ||
| "udid": "booted", | ||
| "output_dir": "./screenshots/raw/en-US/iphone" | ||
| }, | ||
| "steps": [ | ||
| { | ||
| "action": "launch" | ||
| }, | ||
| { | ||
| "action": "wait", | ||
| "duration_ms": 8000 | ||
| }, | ||
| { | ||
| "action": "screenshot", | ||
| "name": "01-welcome" | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "version": 1, | ||
| "app": { | ||
| "bundle_id": "ai.javachat", | ||
| "project": "mobile/iosApp/JavaChat.xcodeproj", | ||
| "scheme": "JavaChat", | ||
| "simulator_udid": "booted" | ||
| }, | ||
| "paths": { | ||
| "plan": ".asc/screenshots.json", | ||
| "raw_dir": "./screenshots/raw/en-US/iphone", | ||
| "framed_dir": "./screenshots/final/en-US/iphone" | ||
| }, | ||
| "pipeline": { | ||
| "frame_enabled": true, | ||
| "upload_enabled": false | ||
| }, | ||
| "upload": { | ||
| "version_localization_id": "d4c9161f-0343-47ed-b4f0-73f1cf37a424", | ||
| "device_type": "IPHONE_69", | ||
| "source_dir": "./screenshots/final/en-US/iphone" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| { | ||
| "env": { | ||
| "APP_ID": "6796580187", | ||
| "VERSION": "1.0", | ||
| "METADATA_PATH": "metadata", | ||
| "SCREENSHOT_PATH": "screenshots/final/en-US" | ||
| }, | ||
| "before_all": "asc auth status", | ||
| "workflows": { | ||
| "release-assets": { | ||
| "private": true, | ||
| "description": "Validates canonical metadata and every local screenshot set.", | ||
| "steps": [ | ||
| { | ||
| "name": "validate_metadata", | ||
| "run": "asc metadata validate --dir $METADATA_PATH" | ||
| }, | ||
| { | ||
| "name": "validate_iphone_screenshots", | ||
| "run": "asc screenshots validate --path $SCREENSHOT_PATH/iphone --device-type IPHONE_69" | ||
| }, | ||
| { | ||
| "name": "validate_ipad_screenshots", | ||
| "run": "asc screenshots validate --path $SCREENSHOT_PATH/ipad --device-type IPAD_PRO_3GEN_129" | ||
| }, | ||
| { | ||
| "name": "validate_mac_screenshots", | ||
| "run": "asc screenshots validate --path $SCREENSHOT_PATH/mac --device-type DESKTOP" | ||
| } | ||
| ] | ||
| }, | ||
| "ios-release-preflight": { | ||
| "description": "Validates local App Store assets and performs the read-only iOS release check.", | ||
| "steps": [ | ||
| { | ||
| "workflow": "release-assets" | ||
| }, | ||
| { | ||
| "name": "validate_ios_listing", | ||
| "run": "asc validate --app $APP_ID --version $VERSION --platform IOS" | ||
| } | ||
| ] | ||
| }, | ||
| "mac-release-preflight": { | ||
| "description": "Validates local App Store assets and performs the read-only Mac release check.", | ||
| "steps": [ | ||
| { | ||
| "workflow": "release-assets" | ||
| }, | ||
| { | ||
| "name": "validate_mac_listing_only", | ||
| "run": "asc validate --app $APP_ID --version $VERSION --platform MAC_OS" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
frontend/src/lib/composables/clerkAuthentication.svelte.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| /** | ||
| * Covers the environment gates of {@link loadClerkAuthentication}: browsers | ||
| * that deny site storage (kiosk / hardened-privacy frames make the | ||
| * `window.localStorage` getter throw) and builds without a publishable key | ||
| * must disable auth quietly — no toast, no rejected promise, controls hidden. | ||
| */ | ||
| import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; | ||
| import { get } from "svelte/store"; | ||
|
|
||
| const originalLocalStorageDescriptor = Object.getOwnPropertyDescriptor(window, "localStorage"); | ||
|
|
||
| /** | ||
| * Mirrors Chromium's behavior when site data is blocked: the property getter | ||
| * itself throws a SecurityError before any storage method can be called. | ||
| */ | ||
| function denySiteStorageAccess(): void { | ||
| Object.defineProperty(window, "localStorage", { | ||
| configurable: true, | ||
| get() { | ||
| throw new DOMException( | ||
| "Failed to read the 'localStorage' property from 'Window': Access is denied for this document.", | ||
| "SecurityError", | ||
| ); | ||
| }, | ||
| }); | ||
| } | ||
|
|
||
| function restoreSiteStorageAccess(): void { | ||
| if (originalLocalStorageDescriptor) { | ||
| Object.defineProperty(window, "localStorage", originalLocalStorageDescriptor); | ||
| } else { | ||
| // No own descriptor to restore (storage inherited from the prototype): | ||
| // deleting the override re-exposes the inherited accessor for later tests. | ||
| Reflect.deleteProperty(window, "localStorage"); | ||
| } | ||
| } | ||
|
|
||
| async function importClerkAuthenticationModule() { | ||
| return import("./clerkAuthentication.svelte"); | ||
| } | ||
|
|
||
| async function importToastStoreModule() { | ||
| return import("../stores/toastStore"); | ||
| } | ||
|
|
||
| beforeEach(() => { | ||
| vi.resetModules(); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| restoreSiteStorageAccess(); | ||
| vi.unstubAllEnvs(); | ||
| vi.restoreAllMocks(); | ||
| }); | ||
|
|
||
| describe("loadClerkAuthentication", () => { | ||
| it("disables auth quietly when the browser denies site storage access", async () => { | ||
| vi.stubEnv("VITE_CLERK_PUBLISHABLE_KEY", "pk_test_storage-gate"); | ||
| const consoleInfoSpy = vi.spyOn(console, "info").mockImplementation(() => {}); | ||
| denySiteStorageAccess(); | ||
| const { loadClerkAuthentication, clerkAuthentication } = | ||
| await importClerkAuthenticationModule(); | ||
| const { toasts } = await importToastStoreModule(); | ||
|
|
||
| await expect(loadClerkAuthentication()).resolves.toBeUndefined(); | ||
|
|
||
| expect(clerkAuthentication.isLoaded).toBe(false); | ||
| expect(get(toasts)).toEqual([]); | ||
| expect(consoleInfoSpy).toHaveBeenCalledWith( | ||
| expect.stringContaining("denies site storage access"), | ||
| expect.any(DOMException), | ||
| ); | ||
| }); | ||
|
|
||
| it("disables auth quietly when the build has no publishable key", async () => { | ||
| vi.stubEnv("VITE_CLERK_PUBLISHABLE_KEY", ""); | ||
| const consoleInfoSpy = vi.spyOn(console, "info").mockImplementation(() => {}); | ||
| const { loadClerkAuthentication, clerkAuthentication } = | ||
| await importClerkAuthenticationModule(); | ||
| const { toasts } = await importToastStoreModule(); | ||
|
|
||
| await expect(loadClerkAuthentication()).resolves.toBeUndefined(); | ||
|
|
||
| expect(clerkAuthentication.isLoaded).toBe(false); | ||
| expect(get(toasts)).toEqual([]); | ||
| expect(consoleInfoSpy).toHaveBeenCalledWith( | ||
| expect.stringContaining("no VITE_CLERK_PUBLISHABLE_KEY"), | ||
| ); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # App Store release readiness | ||
|
|
||
| The customer-facing copy, screenshots, processed builds, and privacy declaration are complete for iOS and Mac version 1.0. Both platform versions have been submitted to App Review. | ||
|
|
||
| ## Completed | ||
|
|
||
| - App name: `Java Chat - AI Learning` | ||
| - Subtitle: `Cited answers. Guided lessons.` | ||
| - Description, keywords, promotional text, marketing URL, support URL, and privacy-policy URL | ||
| - Five iPhone screenshots at 1320 × 2868 | ||
| - Five iPad screenshots at 2064 × 2752 | ||
| - Three Mac screenshots at 2880 × 1800 | ||
| - iOS build 2 attached to version 1.0 | ||
| - Mac build 1 attached to version 1.0 | ||
| - Copyright: `2026 William Callahan` | ||
| - Primary category: `Education` | ||
| - Secondary category: `Developer Tools` | ||
| - Price schedule: Free, with the United States as the base territory | ||
| - Age-rating declaration: no objectionable or sensitive content; all questionnaire fields are `NONE` or `false` | ||
| - App Review contact: William Callahan, `william@javachat.ai`, `+1 650-638-8380` | ||
| - App Review notes for both iOS and Mac; no demo account is required | ||
| - Content-rights declaration: uses third-party content, matching the app's cited and linked documentation | ||
| - Availability: 123 non-European storefronts enabled; 52 European, EU, Europe-boundary, and UK-associated storefronts disabled | ||
| - Automatic availability in future storefronts: disabled, so a new European storefront cannot be enabled implicitly | ||
| - App Privacy declaration: published by William Callahan | ||
| - App Privacy data types: Name, Email Address, Customer Support, Other User Content, Search History, User ID, Product Interaction, Other Usage Data, Other Diagnostic Data, and Other Data Types | ||
| - App Privacy use: account and support fields are used for App Functionality; content, identifiers, usage, diagnostics, and other technical data are used for App Functionality and Analytics; all declared data is conservatively linked to the user and none is used for tracking | ||
| - Free Apps Agreement: active for all countries and regions through July 30, 2027 | ||
| - Paid Apps Agreement: unsigned and not required while Java Chat remains free | ||
|
|
||
| The excluded storefront codes are `AIA`, `ALB`, `ARM`, `AUT`, `AZE`, `BEL`, `BGR`, `BIH`, `BLR`, `BMU`, `CHE`, `CYM`, `CYP`, `CZE`, `DEU`, `DNK`, `ESP`, `EST`, `FIN`, `FRA`, `GBR`, `GEO`, `GRC`, `HRV`, `HUN`, `IRL`, `ISL`, `ITA`, `KAZ`, `LTU`, `LUX`, `LVA`, `MDA`, `MKD`, `MLT`, `MNE`, `MSR`, `NLD`, `NOR`, `POL`, `PRT`, `ROU`, `RUS`, `SRB`, `SVK`, `SVN`, `SWE`, `TCA`, `TUR`, `UKR`, `VGB`, and `XKS`. This conservative set includes transcontinental Europe-boundary countries and the six separately listed UK Overseas Territories. | ||
|
|
||
| Apple does not permit a `What’s New` field on a first release. The drafted version 1.0 notes are retained under `metadata/release-notes/1.0/en-US.md` for future reuse. | ||
|
|
||
| ## Validation | ||
|
|
||
| - iOS 1.0: zero validation errors, zero warnings, and one nonblocking public-API advisory whose App Privacy state was confirmed published in the authenticated web interface | ||
| - Mac 1.0: zero validation errors, zero warnings, and one nonblocking public-API advisory whose App Privacy state was confirmed published in the authenticated web interface | ||
| - iOS build 2: attached, `VALID`, unexpired, encryption exempt, with an extracted App Store icon | ||
| - Mac build 1: attached, `VALID`, unexpired, encryption exempt, with an extracted App Store icon | ||
|
|
||
| ## Submission state | ||
|
|
||
| - iOS 1.0: `WAITING_FOR_REVIEW`, submission `b69dada6-a287-41fd-8184-125bad73c73c`, submitted August 2, 2026 at 5:29:57 PM PDT | ||
| - Mac 1.0: `WAITING_FOR_REVIEW`, submission `94e9a04c-af4d-4e9d-b64a-4329ebfe6aa1`, submitted August 2, 2026 at 5:31:07 PM PDT | ||
| - Release type: automatic after App Review approval | ||
|
|
||
| ## Suggested App Review notes | ||
|
|
||
| Java Chat is an internet-connected Java learning app. The core review path can be exercised without signing in: open Chat to ask a Java question and inspect cited sources, or open Learn to browse a guided lesson and its lesson-focused chat. The iPhone, iPad, and Mac apps present the same JavaChat.ai learning experience in their platform WebKit shells. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "name": "Java Chat - AI Learning", | ||
| "subtitle": "Cited answers. Guided lessons.", | ||
| "privacyPolicyUrl": "https://javachat.ai/privacy" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| Welcome to Java Chat on iPhone, iPad, and Mac. | ||
|
|
||
| Version 1.0 includes: | ||
|
|
||
| - Streaming AI-assisted answers to Java and JVM questions | ||
| - Expandable source links on cited responses | ||
| - Guided lessons from Java fundamentals to modern JVM languages and frameworks | ||
| - Lesson-focused follow-up chat | ||
| - Formatted code and quick copy controls | ||
| - System, Light, and Dark appearance options |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "description": "Java Chat is an AI-assisted learning companion for Java and the wider JVM ecosystem. Ask about APIs, language features, patterns, and best practices, then read the answer as it streams and open its cited sources.\n\nBUILD UNDERSTANDING, ONE QUESTION AT A TIME\n\nStart with your own question or tap a suggested topic. Java Chat formats code clearly, keeps the conversation moving, and makes source links easy to explore.\n\nLEARN WITH A STRUCTURED PATH\n\nBrowse guided lessons that start with Java fundamentals—variables, loops, methods, classes, collections, and testing—and continue into records, streams, pattern matching, virtual threads, modules, and memory.\n\nGO BEYOND THE JAVA LANGUAGE\n\nExplore lessons on Kotlin, Scala, Groovy, Clojure, Spring Boot, and Quarkus. Each lesson includes focused content and its own chat, so your follow-up questions stay with the topic.\n\nDESIGNED FOR FOCUSED STUDY\n\n• Streaming answers for Java and JVM questions\n• Expandable source links on cited responses\n• Guided lessons from fundamentals to modern topics\n• Lesson-focused follow-up chat\n• Formatted code with syntax highlighting\n• Quick copy controls for answers\n• System, Light, and Dark appearance options\n\nWhether you are learning the basics or revisiting modern JVM concepts, Java Chat brings questions, explanations, sources, and guided practice together across iPhone, iPad, and Mac.\n\nAn internet connection is required.", | ||
| "keywords": "programming,coding,JDK,JVM,tutor,Spring,Boot,Kotlin,Quarkus,Scala,Groovy,Clojure,records,threads,API", | ||
| "marketingUrl": "https://javachat.ai", | ||
| "promotionalText": "Ask a Java question, follow the answer as it streams, and open cited sources. Or choose a guided lesson, then ask follow-up questions in that lesson’s context.", | ||
| "supportUrl": "https://javachat.ai/contact" | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.