APPS: App Password creation starts from 'what do you want to connect?' in plain words, not protocol presets #412

Open
opened 2026-09-29 08:07:21 +00:00 by kayg · 35 comments
Owner

Request (owner, 2026-09-29)

"we need to make this way more user friendly!" — the App Password "Scope preset" menu lists technical labels ("Calendar apps · CalDAV", "Files / WebDAV", "Photo upload · PhotoSync", "Automation · API", "AI assistant · MCP (read only)", "Custom scopes").

Direction (Claude proposal; owner reviews the screenshots)

  • Start from what the user wants to connect, in plain words, as a short grid of choices with the app's name and icon: "Apple Calendar & Reminders", "Thunderbird / DAVx5 calendar", "Finder, Files app or rclone", "PhotoSync (upload photos)", "An AI assistant (Claude, Codex, other MCP clients)", "A script or automation (API)". Each choice explains in one line what that app can and cannot do ("can read and change your calendar; cannot see your files").
  • After choosing, show only the fields that matter (name prefilled with the app and device, e.g. "PhotoSync on Aayushy's iPhone"; folder picker only for upload/files; expiry under "More options").
  • Protocol and scope words (CalDAV, WebDAV, scopes) appear only under "More options → Custom access" for power users.
  • After creation, the per-app setup steps (QR/profile for Apple, server URL and username for others) as today.
  • Lives in Settings → Apps with App Passwords (#395); shared components only (Select/cards from #402).
    Evidence: screenshots of the chooser and each flow at 390/820/1440, light and dark.
## Request (owner, 2026-09-29) "we need to make this way more user friendly!" — the App Password "Scope preset" menu lists technical labels ("Calendar apps · CalDAV", "Files / WebDAV", "Photo upload · PhotoSync", "Automation · API", "AI assistant · MCP (read only)", "Custom scopes"). ## Direction (Claude proposal; owner reviews the screenshots) - Start from **what the user wants to connect**, in plain words, as a short grid of choices with the app's name and icon: "Apple Calendar & Reminders", "Thunderbird / DAVx5 calendar", "Finder, Files app or rclone", "PhotoSync (upload photos)", "An AI assistant (Claude, Codex, other MCP clients)", "A script or automation (API)". Each choice explains in one line what that app can and cannot do ("can read and change your calendar; cannot see your files"). - After choosing, show only the fields that matter (name prefilled with the app and device, e.g. "PhotoSync on Aayushy's iPhone"; folder picker only for upload/files; expiry under "More options"). - Protocol and scope words (CalDAV, WebDAV, scopes) appear only under "More options → Custom access" for power users. - After creation, the per-app setup steps (QR/profile for Apple, server URL and username for others) as today. - Lives in Settings → Apps with App Passwords (#395); shared components only (Select/cards from #402). Evidence: screenshots of the chooser and each flow at 390/820/1440, light and dark.
Author
Owner

Added (found by the docs-site job, #415): AppPasswordsGroup.svelte:393,426,428 always says the Apple profile is unsigned ("Not Verified", "author is unknown"). On calternal.cloud, profile signing is configured and verified (the admin config reports enabled: true, macOS reports GoodSignature). Drive this copy from the server's profile-signing status (ProfileSigningStatus in the OpenAPI contract): when signed, show the signer name ("Signed by ") and drop the unknown-author steps. Show the unsigned guidance only when signing is not configured. Add an e2e for both states.

Added (found by the docs-site job, #415): `AppPasswordsGroup.svelte:393,426,428` always says the Apple profile is unsigned ("Not Verified", "author is unknown"). On calternal.cloud, profile signing is configured and verified (the admin config reports enabled: true, macOS reports GoodSignature). Drive this copy from the server's profile-signing status (`ProfileSigningStatus` in the OpenAPI contract): when signed, show the signer name ("Signed by <name>") and drop the unknown-author steps. Show the unsigned guidance only when signing is not configured. Add an e2e for both states.
Author
Owner

Starting #412 on job/app-pw-chooser from dfb5964a2f (dev). I’m tracing the existing App Password flows and profile-signing contract before changing the chooser.

Starting #412 on job/app-pw-chooser from dfb5964a2fcf13dc8b9a50a319eee09bc386f322 (dev). I’m tracing the existing App Password flows and profile-signing contract before changing the chooser.
Author
Owner

Finding: carries , but it is an admin-only route. App Passwords are available to non-admin Users too. I’ll return the signing status alongside the one-use profile links, from the same signer operation that creates the profile bytes, so the UI reports the status of the profile it will deliver.

Finding: carries , but it is an admin-only route. App Passwords are available to non-admin Users too. I’ll return the signing status alongside the one-use profile links, from the same signer operation that creates the profile bytes, so the UI reports the status of the profile it will deliver.
Author
Owner

Correction: the status is in GET /api/v1/admin/config as the ProfileSigningStatus field, and that route is admin-only. Since ordinary Users can create App Passwords, I will return the status beside the one-use profile links from the same signer operation that creates the profile bytes.

Correction: the status is in GET /api/v1/admin/config as the ProfileSigningStatus field, and that route is admin-only. Since ordinary Users can create App Passwords, I will return the status beside the one-use profile links from the same signer operation that creates the profile bytes.
Author
Owner

Finding: the first bun run test reported shared-components.guard.test.ts at AppPasswordsGroup.svelte: <Card because the guard treats every Card as a private Settings card. The chooser uses the shared @calternal/ui Card from #402, so I updated the guard to allow that import while keeping SettingsCard for the Settings surface. The same run had 875/877 tests pass; the unrelated ThemePicker test hit its 5-second timeout with jsdom scrollTo() warnings. I left that timeout and its expectations unchanged and will report the final suite result after the merge.

Finding: the first `bun run test` reported `shared-components.guard.test.ts` at `AppPasswordsGroup.svelte: <Card` because the guard treats every Card as a private Settings card. The chooser uses the shared `@calternal/ui` Card from #402, so I updated the guard to allow that import while keeping `SettingsCard` for the Settings surface. The same run had 875/877 tests pass; the unrelated ThemePicker test hit its 5-second timeout with jsdom `scrollTo()` warnings. I left that timeout and its expectations unchanged and will report the final suite result after the merge.
Author
Owner

Finding: the bearer-token reveal showed the token and scope but no server endpoint for API, MCP, or PhotoSync clients. The reveal now shows a copyable /api/v1/ URL for API grants and /mcp for MCP grants. The real-server e2e flow checks the displayed API URL.

Finding: the bearer-token reveal showed the token and scope but no server endpoint for API, MCP, or PhotoSync clients. The reveal now shows a copyable `/api/v1/` URL for API grants and `/mcp` for MCP grants. The real-server e2e flow checks the displayed API URL.
Author
Owner

Finding: the profile-links response did not report whether its one-use profile bytes were signed, and the admin configuration status is not available to regular Users. The response now carries ProfileSigningStatus from the same sign-or-unsigned operation that creates the queued bytes. Evidence: cargo test -p calternal-auth finished with test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 115.14s; clippy passed. Commit: cffbcdcc2.

Finding: the profile-links response did not report whether its one-use profile bytes were signed, and the admin configuration status is not available to regular Users. The response now carries `ProfileSigningStatus` from the same sign-or-unsigned operation that creates the queued bytes. Evidence: `cargo test -p calternal-auth` finished with `test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 115.14s`; clippy passed. Commit: `cffbcdcc2`.
Author
Owner

The chooser UI slice is committed as 0293cd5cf (feat(web): add plain-language app password presets). It adds eight preset choices with scope explanations, real Home folder selection for Files and PhotoSync, one-time secret and endpoint copy, and signer-aware Apple setup copy. The production-server E2E script now checks Notes/Mail plugin isolation, PhotoSync restrictions, and captures chooser, API, and Apple setup states at the requested device widths and themes. bun run check passed with 0 errors and 0 warnings; the focused shared-component guard test passed (2 tests). Server clippy is still running before the final post-merge gates.

The chooser UI slice is committed as 0293cd5cf (`feat(web): add plain-language app password presets`). It adds eight preset choices with scope explanations, real Home folder selection for Files and PhotoSync, one-time secret and endpoint copy, and signer-aware Apple setup copy. The production-server E2E script now checks Notes/Mail plugin isolation, PhotoSync restrictions, and captures chooser, API, and Apple setup states at the requested device widths and themes. `bun run check` passed with 0 errors and 0 warnings; the focused shared-component guard test passed (2 tests). Server clippy is still running before the final post-merge gates.
Author
Owner

Owner decisions (2026-09-30):

  • ONE preset covers everything calternaldav serves (Calendar, Reminders, Contacts, Mail, Notes). There is no separate Mail or Notes App Password in the UI; per-service scopes may stay internal.
  • Preset name: Sync with Your Devices. Subtitle: "Calendar, Reminders, Contacts, Mail & Notes".
  • Instructions layout for this preset (after the one-time password reveal):
Apple Devices                      (expanded)
  Automatic                        (expanded)
    <QR code>  → scanning it on iPhone/iPad opens the profile download
    [Install Profile] button       → downloads the signed .mobileconfig on this device
  Manual                           (collapsed)
    iPhone / iPad                  (step by step: Settings → Apps → Calendar/Contacts/Mail/Notes → Accounts → Add Account → Other …, with server, username and password to copy)
    Mac                            (step by step: System Settings → Internet Accounts → Add Other Account …)
Other Devices                      (collapsed; orchestrator assumption, owner to confirm: Android via DAVx5, Thunderbird, Outlook, with server URLs to copy)
  • Use the shared disclosure/accordion component; every section is deep-linkable (§33); copy buttons use the shared Copy control; the QR code is dark on light in both themes (the #431 lesson). Plain words only, no jargon.
  • If the running app-pw-chooser job finishes before it sees this comment, it is relaunched in the same worktree to apply it before merge.
**Owner decisions (2026-09-30):** - ONE preset covers everything calternaldav serves (Calendar, Reminders, Contacts, Mail, Notes). There is no separate Mail or Notes App Password in the UI; per-service scopes may stay internal. - Preset name: **Sync with Your Devices**. Subtitle: "Calendar, Reminders, Contacts, Mail & Notes". - Instructions layout for this preset (after the one-time password reveal): ``` Apple Devices (expanded) Automatic (expanded) <QR code> → scanning it on iPhone/iPad opens the profile download [Install Profile] button → downloads the signed .mobileconfig on this device Manual (collapsed) iPhone / iPad (step by step: Settings → Apps → Calendar/Contacts/Mail/Notes → Accounts → Add Account → Other …, with server, username and password to copy) Mac (step by step: System Settings → Internet Accounts → Add Other Account …) Other Devices (collapsed; orchestrator assumption, owner to confirm: Android via DAVx5, Thunderbird, Outlook, with server URLs to copy) ``` - Use the shared disclosure/accordion component; every section is deep-linkable (§33); copy buttons use the shared Copy control; the QR code is dark on light in both themes (the #431 lesson). Plain words only, no jargon. - If the running app-pw-chooser job finishes before it sees this comment, it is relaunched in the same worktree to apply it before merge.
Author
Owner

Server verification finding: cargo clippy -p calternal-server --all-targets -- -D warnings passed. cargo test -p calternal-server ran 87 tests: 84 passed, 2 ignored, and the process-isolated live_apps_run_in_separate_processes test failed because its nested full_app_setup_session_config_and_backup test timed out with Elapsed(()) after 40.41s. The test expectation is unchanged. This appeared during heavy shared-host Rust activity. I will preserve it in the final report.

Server verification finding: `cargo clippy -p calternal-server --all-targets -- -D warnings` passed. `cargo test -p calternal-server` ran 87 tests: 84 passed, 2 ignored, and the process-isolated `live_apps_run_in_separate_processes` test failed because its nested `full_app_setup_session_config_and_backup` test timed out with `Elapsed(())` after 40.41s. The test expectation is unchanged. This appeared during heavy shared-host Rust activity. I will preserve it in the final report.
Author
Owner

Post-merge auth gates: clippy passed (Finished dev profile ... in 1m 50s). cargo test -p calternal-auth reported 53 passed and 10 failed. All 10 failures returned Err(Unavailable) from test database setup (oidc.rs:463 or store.rs:2957); the same auth crate passed all 63 tests earlier in this job. No test expectation was changed. This run occurred during heavy shared-host Rust activity.

Post-merge auth gates: clippy passed (`Finished dev profile ... in 1m 50s`). `cargo test -p calternal-auth` reported 53 passed and 10 failed. All 10 failures returned `Err(Unavailable)` from test database setup (`oidc.rs:463` or `store.rs:2957`); the same auth crate passed all 63 tests earlier in this job. No test expectation was changed. This run occurred during heavy shared-host Rust activity.
Author
Owner

Final report for #412. The job passed the four-hour cap, so I stopped with a clean worktree and recorded the remaining gates below. No screenshots were produced.

Built and committed:

  • cffbcdcc2 feat(auth): report profile signer status with setup links
  • 0293cd5cf feat(web): add plain-language app password presets
  • Merged origin/dev once; merge commit 07899dc59.
  • Final head: 07899dc599.

Implemented the chooser presets, scope explanations, real Home folder choices, one-time token and endpoint copy, and signer-aware Apple profile instructions. The E2E script covers Photosync restrictions, Notes/Mail plugin isolation, signed/unsigned profile copy branches, and production screenshots. Those browser probes and captures were not run before the time cap.

Gate output:

  • cargo fmt --check: passed with no output.
  • cargo clippy -p calternal-auth --all-targets -- -D warnings: Finished dev profile [unoptimized + debuginfo] target(s) in 1m 50s (post-merge).
  • cargo test -p calternal-auth: test result: FAILED. 53 passed; 10 failed; 0 ignored; 0 measured; 0 filtered out; finished in 56.57s. Each failure returned Err(Unavailable) while setting up the test database. The same crate passed all 63 tests earlier in this job. Test expectations were not changed.
  • cargo clippy -p calternal-server --all-targets -- -D warnings: Finished dev profile [unoptimized + debuginfo] target(s) in 9m 58s (post-merge).
  • Pre-merge cargo test -p calternal-server: test result: FAILED. 84 passed; 1 failed; 2 ignored; 0 measured; 0 filtered out; finished in 51.79s. The nested live-app setup test timed out with Elapsed(()) after 40.41s. Expectations were not changed.
  • Post-merge server tests were stopped at the time cap (exit 130); no final result.
  • Pre-merge bun run check: svelte-check found 0 errors and 0 warnings. Focused shared-component test passed: Test Files 1 passed (1); Tests 2 passed (2).
  • bun run test had an earlier run with 2 failures among 877 tests (the shared-card guard, since fixed, and an unrelated ThemePicker timeout). It was not rerun after the guard fix or after the merge.
  • Production build, server-backed E2E, final Bun gates, and requested 390/820/1440 light/dark screenshots remain outstanding.

Decisions not specified in DESIGN: Notes and Mail use existing API credentials with a fixed plugin scope, so each token is limited to its named plugin. Files and PhotoSync select real visible Home folders. API, MCP, DAV and Files endpoints are shown with their matching transport URLs. Apple setup copy uses the signing status returned with the profile links so it describes the delivered profile.

Final report for #412. The job passed the four-hour cap, so I stopped with a clean worktree and recorded the remaining gates below. No screenshots were produced. Built and committed: - cffbcdcc2 `feat(auth): report profile signer status with setup links` - 0293cd5cf `feat(web): add plain-language app password presets` - Merged `origin/dev` once; merge commit 07899dc59. - Final head: 07899dc599a5cad7508b2b24fe17377216977d9c. Implemented the chooser presets, scope explanations, real Home folder choices, one-time token and endpoint copy, and signer-aware Apple profile instructions. The E2E script covers Photosync restrictions, Notes/Mail plugin isolation, signed/unsigned profile copy branches, and production screenshots. Those browser probes and captures were not run before the time cap. Gate output: - `cargo fmt --check`: passed with no output. - `cargo clippy -p calternal-auth --all-targets -- -D warnings`: `Finished dev profile [unoptimized + debuginfo] target(s) in 1m 50s` (post-merge). - `cargo test -p calternal-auth`: `test result: FAILED. 53 passed; 10 failed; 0 ignored; 0 measured; 0 filtered out; finished in 56.57s`. Each failure returned `Err(Unavailable)` while setting up the test database. The same crate passed all 63 tests earlier in this job. Test expectations were not changed. - `cargo clippy -p calternal-server --all-targets -- -D warnings`: `Finished dev profile [unoptimized + debuginfo] target(s) in 9m 58s` (post-merge). - Pre-merge `cargo test -p calternal-server`: `test result: FAILED. 84 passed; 1 failed; 2 ignored; 0 measured; 0 filtered out; finished in 51.79s`. The nested live-app setup test timed out with `Elapsed(())` after 40.41s. Expectations were not changed. - Post-merge server tests were stopped at the time cap (exit 130); no final result. - Pre-merge `bun run check`: `svelte-check found 0 errors and 0 warnings`. Focused shared-component test passed: `Test Files 1 passed (1); Tests 2 passed (2)`. - `bun run test` had an earlier run with 2 failures among 877 tests (the shared-card guard, since fixed, and an unrelated ThemePicker timeout). It was not rerun after the guard fix or after the merge. - Production build, server-backed E2E, final Bun gates, and requested 390/820/1440 light/dark screenshots remain outstanding. Decisions not specified in DESIGN: Notes and Mail use existing API credentials with a fixed plugin scope, so each token is limited to its named plugin. Files and PhotoSync select real visible Home folders. API, MCP, DAV and Files endpoints are shown with their matching transport URLs. Apple setup copy uses the signing status returned with the profile links so it describes the delivered profile.
Author
Owner

Resuming #412 in /home/kayg/Developer/calternal-wt/app-pw-chooser at 07899dc599a5cad7508b2b24fe17377216977d9c (job/app-pw-chooser). I have read the current owner decisions from 2026-09-30 and will apply the single “Sync with Your Devices” preset, the Apple/Other Devices disclosure layout, deep links, and QR contrast. First I am updating from origin/dev as requested, then I will rerun the auth tests alone and continue the UI verification.

Resuming #412 in `/home/kayg/Developer/calternal-wt/app-pw-chooser` at `07899dc599a5cad7508b2b24fe17377216977d9c` (job/app-pw-chooser). I have read the current owner decisions from 2026-09-30 and will apply the single “Sync with Your Devices” preset, the Apple/Other Devices disclosure layout, deep links, and QR contrast. First I am updating from `origin/dev` as requested, then I will rerun the auth tests alone and continue the UI verification.
Author
Owner

E2E finding: Chromium timed out at apps/web/e2e/app-passwords.mjs:45 when the helper called radio.check() for PhotoSync. The radio is intentionally clipped to a 1px hit box; Playwright attempted that hidden hit target and reported that .preset-grid intercepted the click. The visible wrapping label remains the intended pointer target. I am updating the E2E helper to exercise the visible label and keyboard selection separately; this is a test interaction mismatch, not evidence of a UI failure.

E2E finding: Chromium timed out at `apps/web/e2e/app-passwords.mjs:45` when the helper called `radio.check()` for PhotoSync. The radio is intentionally clipped to a 1px hit box; Playwright attempted that hidden hit target and reported that `.preset-grid` intercepted the click. The visible wrapping label remains the intended pointer target. I am updating the E2E helper to exercise the visible label and keyboard selection separately; this is a test interaction mismatch, not evidence of a UI failure.
Author
Owner

E2E finding: after fixing pointer selection, the chooser reached PhotoSync and the assertion getByText('Protocol').count() === 0 found the label inside the collapsed Custom access panel. Disclosure.svelte retains its panel in the DOM with hidden/display: none so its aria-controls target remains stable. The visible UI still keeps protocol choices closed. I am narrowing this assertion to the visible custom-access panel so it checks the original user-facing requirement rather than counting hidden DOM text.

E2E finding: after fixing pointer selection, the chooser reached PhotoSync and the assertion `getByText('Protocol').count() === 0` found the label inside the collapsed Custom access panel. `Disclosure.svelte` retains its panel in the DOM with `hidden`/`display: none` so its `aria-controls` target remains stable. The visible UI still keeps protocol choices closed. I am narrowing this assertion to the visible custom-access panel so it checks the original user-facing requirement rather than counting hidden DOM text.
Author
Owner

E2E finding: the first Sync password POST returned HTTP 200. The flow then failed before checking manual instructions because the non-exact getByRole('button', { name: 'Manual' }) matched both the Manual disclosure and its new Copy link to Manual action. I am scoping that locator to the exact accessible name so the test addresses the disclosure while retaining the copy-link check.

E2E finding: the first Sync password POST returned HTTP 200. The flow then failed before checking manual instructions because the non-exact `getByRole('button', { name: 'Manual' })` matched both the Manual disclosure and its new `Copy link to Manual` action. I am scoping that locator to the exact accessible name so the test addresses the disclosure while retaining the copy-link check.
Author
Owner

E2E finding: the Sync flow reached Manual and rendered the expected headings (iPhone / iPad, Mac). The check failed because assert.equal compares allTextContents() arrays by object identity, even when their contents match. The updated App Password and Calendar E2E flows have this assertion pattern; I am using deepEqual while keeping both expected arrays unchanged.

E2E finding: the Sync flow reached Manual and rendered the expected headings (`iPhone / iPad`, `Mac`). The check failed because `assert.equal` compares `allTextContents()` arrays by object identity, even when their contents match. The updated App Password and Calendar E2E flows have this assertion pattern; I am using `deepEqual` while keeping both expected arrays unchanged.
Author
Owner

E2E finding: both Sync creation requests returned HTTP 200. The shared ready-state matcher then timed out because its regex accidentally required the words secret and password together, while the UI has two valid messages: “Copy this password now” for Sync and “Copy the secret now” for other grants. I am correcting the matcher to accept those two exact message forms; the UI text and expectation remain unchanged.

E2E finding: both Sync creation requests returned HTTP 200. The shared ready-state matcher then timed out because its regex accidentally required the words `secret` and `password` together, while the UI has two valid messages: “Copy this password now” for Sync and “Copy the secret now” for other grants. I am correcting the matcher to accept those two exact message forms; the UI text and expectation remain unchanged.
Author
Owner

E2E finding: the Sync Manual panel renders the same server URL for both iPhone/iPad and Mac, as required by the two setup sections. The test used a strict exact-text locator that expected one match and failed with two matches. I am asserting that both manual instructions contain the server URL and waiting on the first rendered value; the UI and expected setup content remain unchanged.

E2E finding: the Sync Manual panel renders the same server URL for both iPhone/iPad and Mac, as required by the two setup sections. The test used a strict exact-text locator that expected one match and failed with two matches. I am asserting that both manual instructions contain the server URL and waiting on the first rendered value; the UI and expected setup content remain unchanged.
Author
Owner

E2E finding: the Sync setup exposes the same one-time password in six locations: the reveal, two Manual instructions, and three Other Devices instructions. A strict single-match locator failed when the test read it. I am reading all rendered secret fields, asserting they carry the same value, and retaining the first value for the existing checks without logging it.

E2E finding: the Sync setup exposes the same one-time password in six locations: the reveal, two Manual instructions, and three Other Devices instructions. A strict single-match locator failed when the test read it. I am reading all rendered secret fields, asserting they carry the same value, and retaining the first value for the existing checks without logging it.
Author
Owner

E2E finding: the second Sync password has the same scope summary as the first, so the list contains two identical scope strings. The strict text locator then failed despite the new credential row being present. I am locating the row by its unique password name and checking the expected scope within that row.

E2E finding: the second Sync password has the same scope summary as the first, so the list contains two identical scope strings. The strict text locator then failed despite the new credential row being present. I am locating the row by its unique password name and checking the expected scope within that row.
Author
Owner

E2E finding: the uniquely named password row was present. SettingsRow combines the scope summary with created, last-used, and expiry text in one metadata span, so an exact-text query for only the scope cannot match. I am retaining the same expected scope and matching it as text within that named row.

E2E finding: the uniquely named password row was present. `SettingsRow` combines the scope summary with created, last-used, and expiry text in one metadata span, so an exact-text query for only the scope cannot match. I am retaining the same expected scope and matching it as text within that named row.
Author
Owner

E2E finding: the full apps/web/e2e/calendar.mjs run stopped at line 579, before its App Passwords section. The existing assertion the send started received null where it expects true. I did not alter that existing expectation because this issue does not change send behavior. The dedicated App Passwords E2E passed and covers the profile setup flow independently.

E2E finding: the full `apps/web/e2e/calendar.mjs` run stopped at line 579, before its App Passwords section. The existing assertion `the send started` received `null` where it expects `true`. I did not alter that existing expectation because this issue does not change send behavior. The dedicated App Passwords E2E passed and covers the profile setup flow independently.
Author
Owner

Benchmark profile finding: the first temporary App Password POST returned HTTP 200, but the seed wait timed out. The ready paragraph also contains the credential name, so an exact text query for only the copy sentence did not match. I am matching the unchanged ready sentence within the paragraph before continuing the 50-row profile.

Benchmark profile finding: the first temporary App Password POST returned HTTP 200, but the seed wait timed out. The ready paragraph also contains the credential name, so an exact text query for only the copy sentence did not match. I am matching the unchanged ready sentence within the paragraph before continuing the 50-row profile.
Author
Owner

Performance probe finding: selecting Photos from /files left the shell at /files with Opening Photos… after 5 seconds, despite HTTP 200 from /api/v1/photos/timeline/buckets; the existing route probe timed out at 30 seconds. I filed this unrelated navigation issue as #528. I am running the #412 profile in isolation so its measurements cover App Passwords only.

Performance probe finding: selecting Photos from `/files` left the shell at `/files` with `Opening Photos…` after 5 seconds, despite HTTP 200 from `/api/v1/photos/timeline/buckets`; the existing route probe timed out at 30 seconds. I filed this unrelated navigation issue as #528. I am running the #412 profile in isolation so its measurements cover App Passwords only.
Author
Owner

Finished report — #412 App Password chooser

Branch: job/app-pw-chooser
Head: 8f774059f5ab2668f742522c10d615ca08c3ffaf

Built the single Sync with Your Devices preset with the approved subtitle, plus Files, PhotoSync, AI assistant and automation choices. Setup now uses shared disclosures and stable section links. Apple setup opens on Apple Devices → Automatic, with a dark-on-light QR code and Install Profile action; Manual and Other Devices start collapsed and show copyable credentials. Mail and Notes are not separate choices. Existing Notes/Mail records remain supported and are summarized as “Synced data.”

Attached 12 production-build screenshots to this issue: chooser and ready states at 390, 820 and 1440 px in light and dark themes. The dedicated App Password production E2E flow passed, including grant checks, one-use profile links, QR contrast, deep links and actual clipboard copies.

Changed files:

  • apps/web/src/routes/settings/account/AppPasswordsGroup.svelte
  • packages/ui/src/components/Disclosure.svelte, CopyControl.svelte, and packages/ui/src/index.ts
  • apps/web/e2e/app-passwords.mjs, calendar.mjs, and route-perf.mjs
  • bench/run.sh, bench/record.py, and bench/test_record.py
  • docs/perf/runs/2026-09-30-issue-412-app-passwords.md and 2026-09-30T1514Z-issue-412-app-passwords.json

Gates

cargo fmt --check: exit 0; no output.

cargo test -p calternal-auth (run alone):

test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 31.14s

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

bun run check:

Text sizes and UI shape values use shared role tokens.
svelte-check found 0 errors and 0 warnings

bun run test:

 Test Files  137 passed (137)
      Tests  892 passed (892)
   Duration  160.39s (transform 53%, environment 18%, import 14%, tests 9%, setup 5%)

The web tests also printed existing jsdom Window's scrollTo() and CSS parse warnings. python3 -m unittest bench.test_record:

Ran 2 tests in 0.190s

OK

cargo clean completed: Removed 8535 files, 5.4GiB total. Web build/ and .svelte-kit/ outputs were removed.

Performance

The #412 profile used 50 real credentials, three runs at 390/1440 px and a 24-client burst. App Password data-ready p50/p95 was 2973/3020 ms at 390 px and 7355/10040 ms at 1440 px. Chooser open p50/p95 was 443/909 ms. The server sample recorded idle RSS 215.7 MiB, idle CPU 0.5%, peak RSS 215.9 MiB, and peak CPU 427.94%.

The 12-second list burst made 17,398 requests: 102 HTTP 200 and 17,296 HTTP 429. Its latency percentiles mostly describe rate-limit responses, not successful list reads. docs/perf/baseline.json has no App Password route. Its nearest Settings route was Appearance; its 24-client storm returned only 200s. The current host load average ranged from 26.29 to 34.80, and the routes and workloads differ, so the report records these numbers as diagnostic rather than a direct regression comparison.

Known gaps and decisions

The broader bun e2e/calendar.mjs run stopped before its App Password section at the existing “the send started” assertion (line 579; actual null, expected true). I kept that expectation unchanged; the dedicated App Password E2E passed. The performance probe also found Photos navigation stuck at “Opening Photos…” while its bucket API returned 200; that separate finding is filed as #528.

Decision not specified in DESIGN: the new Sync choice maps to the existing full CalDAV grant and /dav/ setup path; existing per-service Notes/Mail credentials remain supported but are shown generically. No Rust source crate changed. The auth crate test was rerun alone and passed.

### Finished report — #412 App Password chooser Branch: `job/app-pw-chooser` Head: `8f774059f5ab2668f742522c10d615ca08c3ffaf` Built the single **Sync with Your Devices** preset with the approved subtitle, plus Files, PhotoSync, AI assistant and automation choices. Setup now uses shared disclosures and stable section links. Apple setup opens on Apple Devices → Automatic, with a dark-on-light QR code and Install Profile action; Manual and Other Devices start collapsed and show copyable credentials. Mail and Notes are not separate choices. Existing Notes/Mail records remain supported and are summarized as “Synced data.” Attached 12 production-build screenshots to this issue: chooser and ready states at 390, 820 and 1440 px in light and dark themes. The dedicated App Password production E2E flow passed, including grant checks, one-use profile links, QR contrast, deep links and actual clipboard copies. Changed files: - `apps/web/src/routes/settings/account/AppPasswordsGroup.svelte` - `packages/ui/src/components/Disclosure.svelte`, `CopyControl.svelte`, and `packages/ui/src/index.ts` - `apps/web/e2e/app-passwords.mjs`, `calendar.mjs`, and `route-perf.mjs` - `bench/run.sh`, `bench/record.py`, and `bench/test_record.py` - `docs/perf/runs/2026-09-30-issue-412-app-passwords.md` and `2026-09-30T1514Z-issue-412-app-passwords.json` ### Gates `cargo fmt --check`: exit 0; no output. `cargo test -p calternal-auth` (run alone): ```text test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 31.14s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` `bun run check`: ```text Text sizes and UI shape values use shared role tokens. svelte-check found 0 errors and 0 warnings ``` `bun run test`: ```text Test Files 137 passed (137) Tests 892 passed (892) Duration 160.39s (transform 53%, environment 18%, import 14%, tests 9%, setup 5%) ``` The web tests also printed existing jsdom `Window's scrollTo()` and CSS parse warnings. `python3 -m unittest bench.test_record`: ```text Ran 2 tests in 0.190s OK ``` `cargo clean` completed: `Removed 8535 files, 5.4GiB total`. Web `build/` and `.svelte-kit/` outputs were removed. ### Performance The #412 profile used 50 real credentials, three runs at 390/1440 px and a 24-client burst. App Password data-ready p50/p95 was 2973/3020 ms at 390 px and 7355/10040 ms at 1440 px. Chooser open p50/p95 was 443/909 ms. The server sample recorded idle RSS 215.7 MiB, idle CPU 0.5%, peak RSS 215.9 MiB, and peak CPU 427.94%. The 12-second list burst made 17,398 requests: 102 HTTP 200 and 17,296 HTTP 429. Its latency percentiles mostly describe rate-limit responses, not successful list reads. `docs/perf/baseline.json` has no App Password route. Its nearest Settings route was Appearance; its 24-client storm returned only 200s. The current host load average ranged from 26.29 to 34.80, and the routes and workloads differ, so the report records these numbers as diagnostic rather than a direct regression comparison. ### Known gaps and decisions The broader `bun e2e/calendar.mjs` run stopped before its App Password section at the existing “the send started” assertion (line 579; actual `null`, expected `true`). I kept that expectation unchanged; the dedicated App Password E2E passed. The performance probe also found Photos navigation stuck at “Opening Photos…” while its bucket API returned 200; that separate finding is filed as #528. Decision not specified in DESIGN: the new Sync choice maps to the existing full CalDAV grant and `/dav/` setup path; existing per-service Notes/Mail credentials remain supported but are shown generically. No Rust source crate changed. The auth crate test was rerun alone and passed.
Author
Owner

Owner, 2026-09-30 night: the instruction sections in the App Password setup must be plain headings / sub-sections / sub-cards, with no expand/collapse pills or disclosures. The queued polish round (job/app-pw-chooser) is updated with this rule.

Owner, 2026-09-30 night: the instruction sections in the App Password setup must be plain headings / sub-sections / sub-cards, with no expand/collapse pills or disclosures. The queued polish round (job/app-pw-chooser) is updated with this rule.
Author
Owner

Starting polish round 2 on branch job/app-pw-chooser. Current HEAD: 8f774059f5; branch base (merge-base with origin/dev): ec917c7f19. I’m updating the ready/setup layout, heading Copy link controls, responsive sheet surface, and #412 browser coverage.

Starting polish round 2 on branch job/app-pw-chooser. Current HEAD: 8f774059f5ab2668f742522c10d615ca08c3ffaf; branch base (merge-base with origin/dev): ec917c7f19ed5a53b28dff62b876e2e3a1d6a2a2. I’m updating the ready/setup layout, heading Copy link controls, responsive sheet surface, and #412 browser coverage.
Author
Owner

Finding after the origin/dev merge: stopped in the new motion-token guard at AppPasswordsGroup.svelte:863 because the Copy link animation used a literal 140ms ease. I am switching that transition to the shared token and will rerun the web gates.

Finding after the origin/dev merge: stopped in the new motion-token guard at AppPasswordsGroup.svelte:863 because the Copy link animation used a literal 140ms ease. I am switching that transition to the shared token and will rerun the web gates.
Author
Owner

Finding after origin/dev merge: the new motion-token checker rejected AppPasswordsGroup.svelte's literal 140ms ease transition. I replaced it with --dur-brief and --ease-standard. The rerun completed with: svelte-check found 0 errors and 0 warnings.

Finding after origin/dev merge: the new motion-token checker rejected AppPasswordsGroup.svelte's literal 140ms ease transition. I replaced it with --dur-brief and --ease-standard. The rerun completed with: svelte-check found 0 errors and 0 warnings.
Author
Owner

Finding from the 390 px light capture: the App Passwords SettingsCard painted an inset panel inside the phone's glass sheet. I removed that wrapper surface and padding only on the phone sheet. Its content now uses the sheet's standard 16 px inset, and the three setup sub-cards keep their shared card role. The dedicated E2E asserts this rule and completed the 12 screenshot captures.

Evidence: svelte-check found 0 errors and 0 warnings; app password e2e: one sync choice, Apple profiles, other devices, retained grants, and QR contrast passed.

Finding from the 390 px light capture: the App Passwords SettingsCard painted an inset panel inside the phone's glass sheet. I removed that wrapper surface and padding only on the phone sheet. Its content now uses the sheet's standard 16 px inset, and the three setup sub-cards keep their shared card role. The dedicated E2E asserts this rule and completed the 12 screenshot captures. Evidence: `svelte-check found 0 errors and 0 warnings`; `app password e2e: one sync choice, Apple profiles, other devices, retained grants, and QR contrast passed`.
Author
Owner

The focused live adversarial round for App Password profile issuance and delivery completed with 0 findings. It checked malformed and oversized requests, cross-user and mismatched IDs, signed CMS delivery, expiry, replay, a 20-request one-use race, and a 200-request burst. It reported one SLOW-only result: signing took 1.2 s (HTTP 200) on the shared local host. No 5xx or accepted hostile input was reported.

The focused live adversarial round for App Password profile issuance and delivery completed with 0 findings. It checked malformed and oversized requests, cross-user and mismatched IDs, signed CMS delivery, expiry, replay, a 20-request one-use race, and a 200-request burst. It reported one SLOW-only result: signing took 1.2 s (HTTP 200) on the shared local host. No 5xx or accepted hostile input was reported.
Author
Owner

Finished: App Password chooser polish round 2

Built: static Apple setup headings; Manual and Other Devices sub-cards; in-row Copy link actions with the warm tooltip; centred 200 px QR, caption and content-sized Install Profile action; footnotes after the action; and a trailing Done action. The phone sheet owns the outer surface, and the app-password content uses its 16 px inset. The E2E asserts this and masks both the one-time secret and QR in every ready screenshot.

Files:

  • apps/web/src/routes/settings/account/AppPasswordsGroup.svelte, apps/web/e2e/app-passwords.mjs, apps/web/e2e/calendar.mjs, apps/web/e2e/route-perf.mjs, apps/web/src/routes/settings/shared-components.guard.test.ts
  • packages/ui/src/components/CopyControl.svelte, CopyLink.svelte, Disclosure.svelte, LinkedHeading.svelte, packages/ui/src/index.ts
  • crates/calternal-auth/src/api.rs, profile_signing.rs, contracts/openapi.json, packages/api-client/src/generated.ts
  • bench/record.py, bench/run.sh, bench/test_record.py, and docs/perf/runs/2026-09-30-issue-412-app-passwords.md, 2026-09-30T1514Z-issue-412-app-passwords.json, 2026-10-01-issue-412-polish-round2.md

Screenshots: all 12 sanitized screenshots are attached here.

Width State Light Dark
390 px Chooser Light Dark
390 px Ready Light Dark
820 px Chooser Light Dark
820 px Ready Light Dark
1440 px Chooser Light Dark
1440 px Ready Light Dark

Head SHA: e2cf6ef0700f9bd4cf594f5ce0e4a89f1d27ed6b

Gates (verbatim excerpts)

cargo fmt --check: exit 0; no output.

bun run check:

$ node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/app-pw-chooser/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test:

 Test Files  140 passed (140)
      Tests  914 passed (914)
   Start at  00:08:54
   Duration  128.57s (transform 52%, environment 18%, import 15%, tests 10%, setup 4%)

bun run test:e2e:app-passwords:

app password e2e: one sync choice, Apple profiles, other devices, retained grants, and QR contrast passed

Rust gates:

Finished `dev` profile [unoptimized + debuginfo] target(s) in 9m 05s

test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 37.32s

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Finished `dev` profile [unoptimized + debuginfo] target(s) in 13.60s

test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 44.83s

Production SPA build:

Wrote site to "build"
✔ done

Performance: local calternal-dev, 50 credentials, one route sample per viewport, load average 24.43–26.68. Chooser visible p50/p95 was 197/427 ms; API list read was 8.1/22.9 ms over 50 successful samples. The 24-client, 12 s list burst made 11715 requests: 49 HTTP 200 and 11666 HTTP 429, p50/p95 21.2/49.9 ms; peak RSS 231.3 MiB. docs/perf/baseline.json has no App Password route, so the report records the nearest Appearance values as context only. The local profile is diagnostic under this load.

Adversarial round: 0 findings. One SLOW-only result: profile signing took 1.2 s (HTTP 200) on the shared host. No 5xx or accepted hostile input was reported. Three calternal-server tests remain ignored by their existing process-isolation annotations.

Decisions: for phone sheet presentation only, the SettingsCard wrapper is a transparent, zero-padding layout container so the sheet remains the single outer surface; its three shared instruction sub-cards remain intact. This follows the owner’s 390 px requirement and leaves desktop card styling unchanged.

## Finished: App Password chooser polish round 2 **Built:** static Apple setup headings; Manual and Other Devices sub-cards; in-row Copy link actions with the warm tooltip; centred 200 px QR, caption and content-sized Install Profile action; footnotes after the action; and a trailing Done action. The phone sheet owns the outer surface, and the app-password content uses its 16 px inset. The E2E asserts this and masks both the one-time secret and QR in every ready screenshot. **Files:** - `apps/web/src/routes/settings/account/AppPasswordsGroup.svelte`, `apps/web/e2e/app-passwords.mjs`, `apps/web/e2e/calendar.mjs`, `apps/web/e2e/route-perf.mjs`, `apps/web/src/routes/settings/shared-components.guard.test.ts` - `packages/ui/src/components/CopyControl.svelte`, `CopyLink.svelte`, `Disclosure.svelte`, `LinkedHeading.svelte`, `packages/ui/src/index.ts` - `crates/calternal-auth/src/api.rs`, `profile_signing.rs`, `contracts/openapi.json`, `packages/api-client/src/generated.ts` - `bench/record.py`, `bench/run.sh`, `bench/test_record.py`, and `docs/perf/runs/2026-09-30-issue-412-app-passwords.md`, `2026-09-30T1514Z-issue-412-app-passwords.json`, `2026-10-01-issue-412-polish-round2.md` **Screenshots:** all 12 sanitized screenshots are attached here. | Width | State | Light | Dark | |---|---|---|---| | 390 px | Chooser | [Light](https://git.kayg.org/attachments/6cd63175-d9bf-4ee7-8937-5a8d9f74bcd2) | [Dark](https://git.kayg.org/attachments/f34fdc3a-3de8-447e-ad93-5cb551308b4b) | | 390 px | Ready | [Light](https://git.kayg.org/attachments/2ad563fc-6306-4c4b-bdc9-69e9ee00c22e) | [Dark](https://git.kayg.org/attachments/9dd842a9-18dd-4494-800b-74e219baec6c) | | 820 px | Chooser | [Light](https://git.kayg.org/attachments/841aeed0-e275-469f-80cb-a9970880d26a) | [Dark](https://git.kayg.org/attachments/944cc255-78a1-45d8-a71a-8d2f371b38d1) | | 820 px | Ready | [Light](https://git.kayg.org/attachments/ab15133a-7637-4661-a6fb-8127a2b3e420) | [Dark](https://git.kayg.org/attachments/946075f9-67a2-407d-a600-83ff80706a21) | | 1440 px | Chooser | [Light](https://git.kayg.org/attachments/f432f773-5120-44d7-9af4-db03268856e4) | [Dark](https://git.kayg.org/attachments/dd500c62-a6aa-45b1-bbde-5422d0ae4a86) | | 1440 px | Ready | [Light](https://git.kayg.org/attachments/5ad4cf2c-0f46-46e5-a465-7226b3973615) | [Dark](https://git.kayg.org/attachments/39478b02-e88d-481c-a090-e6fd2ff98960) | **Head SHA:** `e2cf6ef0700f9bd4cf594f5ce0e4a89f1d27ed6b` ## Gates (verbatim excerpts) `cargo fmt --check`: exit 0; no output. `bun run check`: ```text $ node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/app-pw-chooser/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test`: ```text Test Files 140 passed (140) Tests 914 passed (914) Start at 00:08:54 Duration 128.57s (transform 52%, environment 18%, import 15%, tests 10%, setup 4%) ``` `bun run test:e2e:app-passwords`: ```text app password e2e: one sync choice, Apple profiles, other devices, retained grants, and QR contrast passed ``` Rust gates: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 9m 05s test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 37.32s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Finished `dev` profile [unoptimized + debuginfo] target(s) in 13.60s test result: ok. 93 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 44.83s ``` Production SPA build: ```text Wrote site to "build" ✔ done ``` **Performance:** local `calternal-dev`, 50 credentials, one route sample per viewport, load average 24.43–26.68. Chooser visible p50/p95 was 197/427 ms; API list read was 8.1/22.9 ms over 50 successful samples. The 24-client, 12 s list burst made 11715 requests: 49 HTTP 200 and 11666 HTTP 429, p50/p95 21.2/49.9 ms; peak RSS 231.3 MiB. `docs/perf/baseline.json` has no App Password route, so the report records the nearest Appearance values as context only. The local profile is diagnostic under this load. **Adversarial round:** 0 findings. One SLOW-only result: profile signing took 1.2 s (HTTP 200) on the shared host. No 5xx or accepted hostile input was reported. Three `calternal-server` tests remain ignored by their existing process-isolation annotations. **Decisions:** for phone sheet presentation only, the SettingsCard wrapper is a transparent, zero-padding layout container so the sheet remains the single outer surface; its three shared instruction sub-cards remain intact. This follows the owner’s 390 px requirement and leaves desktop card styling unchanged.
Author
Owner

Copy audit evidence for the current Settings → Apps → App Passwords screen

The current screen still exposes the protocol-first labels that this issue aims to remove:

  • apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:45,56-60: CalDAV, Notes · IMAP, WebDAV, API, MCP in protocol names and custom-access choices. Use app tasks such as Calendar, Files, Automation, and AI helper; keep protocol names out of the normal flow.
  • :48-52: Calendar apps · CalDAV, Files / WebDAV, Photo upload · PhotoSync, Automation · API, AI assistant · MCP (read only). Use plain choices that describe the app and what it can do. The 2026-10-02 owner rule also says not to name third-party products in the UI.
  • :335: Give each external app its own password. Choose its protocol and access, set an optional Home folder or expiry, and revoke it without changing other passwords. Replace protocol and access with plain task words.
  • :403, :441-462: setup steps name platform Settings paths, CalDAV, Thunderbird and DAVx⁵. Use plain steps for adding a calendar account and copy-ready fields. Do not name third-party products in the instructions.
  • :495-499: Bearer token, Authorization header, and scope tell people how to send the secret. Use a plain label and one short setup sentence.
  • :509-510: scopeSummary(...) shows protocol, access and resource details in each row. Show what the password can do in plain words.
  • :532-546: Scope preset, protocol, and access labels. Use What do you want to connect?, then show extra technical choices only under a clearly named advanced section.
  • :559-569: Plugin ID, Plugin access, Resource ID and Home folder prefix. Use app name, allowed actions, and folder names.
  • :164,177,198-212: validation errors and last-used summaries can expose API, plugin ID, and protocol names. Keep those messages in plain words too.

Test idea: review the create, setup, detail and revoke flows at phone, tablet and desktop widths. Check visible labels, help text, errors, screen-reader names and saved-row summaries. The normal flow must not show protocol names or third-party product names.

Copy audit evidence for the current Settings → Apps → App Passwords screen The current screen still exposes the protocol-first labels that this issue aims to remove: - `apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:45,56-60`: `CalDAV`, `Notes · IMAP`, `WebDAV`, `API`, `MCP` in protocol names and custom-access choices. Use app tasks such as `Calendar`, `Files`, `Automation`, and `AI helper`; keep protocol names out of the normal flow. - `:48-52`: `Calendar apps · CalDAV`, `Files / WebDAV`, `Photo upload · PhotoSync`, `Automation · API`, `AI assistant · MCP (read only)`. Use plain choices that describe the app and what it can do. The 2026-10-02 owner rule also says not to name third-party products in the UI. - `:335`: `Give each external app its own password. Choose its protocol and access, set an optional Home folder or expiry, and revoke it without changing other passwords.` Replace `protocol` and `access` with plain task words. - `:403`, `:441-462`: setup steps name platform Settings paths, CalDAV, Thunderbird and DAVx⁵. Use plain steps for adding a calendar account and copy-ready fields. Do not name third-party products in the instructions. - `:495-499`: `Bearer token`, `Authorization header`, and `scope` tell people how to send the secret. Use a plain label and one short setup sentence. - `:509-510`: `scopeSummary(...)` shows protocol, access and resource details in each row. Show what the password can do in plain words. - `:532-546`: `Scope preset`, `protocol`, and `access` labels. Use `What do you want to connect?`, then show extra technical choices only under a clearly named advanced section. - `:559-569`: `Plugin ID`, `Plugin access`, `Resource ID` and `Home folder prefix`. Use app name, allowed actions, and folder names. - `:164,177,198-212`: validation errors and last-used summaries can expose `API`, `plugin ID`, and protocol names. Keep those messages in plain words too. Test idea: review the create, setup, detail and revoke flows at phone, tablet and desktop widths. Check visible labels, help text, errors, screen-reader names and saved-row summaries. The normal flow must not show protocol names or third-party product names.
Author
Owner

More App Passwords wording from setup and validation

  • apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:161: Upload-only access needs a Home folder. → Choose a folder for uploads.
  • :177: Use lowercase letters, numbers, hyphens, or underscores for the plugin ID. → Use lowercase letters, numbers, hyphens, or underscores for the feature name.
  • :180: Enter a valid resource ID or leave it empty. → Enter a valid item name or leave it empty.
  • :389: Install within 8 minutes. Apple removes a downloaded profile that is not installed in time. → Install the downloaded profile within 8 minutes. It is removed after that.
  • :393: The profile is unsigned. Apple may show “Not Verified”; HTTPS protects the download. → Your device may show “Not verified” for this profile. The download uses a secure connection.
  • :422: If Safari asks to allow downloads from this site, choose Allow. → If your browser asks to allow downloads from this site, choose Allow.
  • :428: The profile is unsigned. macOS labels it “Not Signed” and warns that the author is unknown. This is expected until profile signing is configured. → Your Mac may say it cannot verify who made this profile. This is expected.
  • :535: The selected protocol and access are enforced for every request. The calendar preset keeps its existing QR and profile setup. → This password keeps the access you chose. The calendar choice also gives setup steps and a QR code.
  • :541: This credential can list names and upload new files in this folder. It cannot download or replace files. → This password can show file names and upload files in this folder. It cannot download or replace files.

Test idea: check each custom-access validation error and both setup paths. Check the copy on a Mac and on other devices. Keep the same secure profile installation steps.

More App Passwords wording from setup and validation - `apps/web/src/routes/settings/account/AppPasswordsGroup.svelte:161`: `Upload-only access needs a Home folder.` → `Choose a folder for uploads.` - `:177`: `Use lowercase letters, numbers, hyphens, or underscores for the plugin ID.` → `Use lowercase letters, numbers, hyphens, or underscores for the feature name.` - `:180`: `Enter a valid resource ID or leave it empty.` → `Enter a valid item name or leave it empty.` - `:389`: `Install within 8 minutes. Apple removes a downloaded profile that is not installed in time.` → `Install the downloaded profile within 8 minutes. It is removed after that.` - `:393`: `The profile is unsigned. Apple may show “Not Verified”; HTTPS protects the download.` → `Your device may show “Not verified” for this profile. The download uses a secure connection.` - `:422`: `If Safari asks to allow downloads from this site, choose Allow.` → `If your browser asks to allow downloads from this site, choose Allow.` - `:428`: `The profile is unsigned. macOS labels it “Not Signed” and warns that the author is unknown. This is expected until profile signing is configured.` → `Your Mac may say it cannot verify who made this profile. This is expected.` - `:535`: `The selected protocol and access are enforced for every request. The calendar preset keeps its existing QR and profile setup.` → `This password keeps the access you chose. The calendar choice also gives setup steps and a QR code.` - `:541`: `This credential can list names and upload new files in this folder. It cannot download or replace files.` → `This password can show file names and upload files in this folder. It cannot download or replace files.` Test idea: check each custom-access validation error and both setup paths. Check the copy on a Mac and on other devices. Keep the same secure profile installation steps.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#412
No description provided.