Commit graph

376 commits

Author SHA1 Message Date
Johannes Millan
213d0ec010 chore(plugins): remove debug logging from procrastination-buster i18n 2026-01-16 22:34:50 +01:00
Johannes Millan
9be6bf7c27 fix(plugins): initialize current language on plugin mount
Fixed i18n to fetch and use the current language when the plugin
initializes, instead of always defaulting to English. Now the plugin
will show the correct language immediately on first load, and also
update reactively when the language changes.

Changes:
- Added getCurrentLanguage() call in useTranslate initialization
- Changed onMount to createEffect for reactive language loading
- Updated both App.tsx and ProcrastinationInfo.tsx to use createEffect
- Applied fixes to both procrastination-buster and boilerplate
- Added debug logging to troubleshoot language change events

This fixes the issue where plugins always started in English regardless
of the user's selected language.
2026-01-16 22:34:50 +01:00
Johannes Millan
fb05e7be3e chore(plugins): remove debug logging from procrastination-buster 2026-01-16 22:34:50 +01:00
Johannes Millan
de264aff48 fix(plugins): fix i18n message protocol for iframe communication
Fixed the message passing between plugin iframes and plugin.ts to use
the proper PLUGIN_MESSAGE/PLUGIN_MESSAGE_RESPONSE protocol instead of
custom messages. This ensures translations and other messages are
correctly routed through the plugin bridge.

Changes:
- Updated useTranslate to use PLUGIN_MESSAGE type
- Listen for PLUGIN_MESSAGE_RESPONSE instead of custom response
- Wrap message in { type, payload } structure
- Updated plugin.ts to read from message.payload
- Added debug logging for troubleshooting
- Applied fixes to both procrastination-buster and boilerplate
2026-01-16 22:34:50 +01:00
Johannes Millan
1df40ab02d fix(plugins): fix translation loading in procrastination-buster
Changed message.data to message.payload in the onMessage handler
to match the structure sent by useTranslate hook. This fixes the
issue where translations were not loading in the UI.
2026-01-16 22:34:50 +01:00
Johannes Millan
92fd9301fe fix(plugins): remove duplicate side panel registration in procrastination-buster
Remove manual registerSidePanelButton() call since the side panel button
is already automatically registered via manifest.json with 'sidePanel: true'.

This fixes:
- Duplicate side panel button warning
- Plugin loading in both side panel and main view simultaneously

The manifest-based registration is sufficient and avoids duplication.
2026-01-16 22:34:50 +01:00
Johannes Millan
91fe3652dc fix(plugins): copy directories recursively in build script
Add copyRecursive() helper function to handle both files and directories
when copying plugin builds to bundled-plugins. This ensures i18n folders
and other directories are properly copied.

Previously, only files were copied (checking isFile()), which caused i18n
folders to be skipped. Now all three plugin build commands (procrastination-
buster, sync-md, ai-productivity-prompts) properly copy directory trees.

Fixes: 404 errors for i18n/de.json and other directory contents
2026-01-16 22:34:50 +01:00
Johannes Millan
ba0e9ce002 fix(plugins): resolve PluginHooks runtime error in procrastination-buster
Replace PluginHooks.LANGUAGE_CHANGE enum reference with string literal
'languageChange' to fix runtime error. The type-only import of PluginHooks
was not available at runtime, causing "PluginHooks is not defined" error
when installing the plugin.

The hook registration now uses the string value directly:
- Before: plugin.registerHook(PluginHooks.LANGUAGE_CHANGE, ...)
- After: plugin.registerHook('languageChange', ...)
2026-01-16 22:34:50 +01:00
Johannes Millan
ce17c00690 feat(plugins): add German translations to procrastination-buster
- Add comprehensive de.json with 80 German translation keys
- Update manifest.json to include German language support
- Translate all UI strings: home, navigation, strategies, info
- Translate all 8 procrastination types with emotions and strategies
- Translate educational content for understanding procrastination

All translation keys match between en.json and de.json for consistency.
2026-01-16 22:34:50 +01:00
Johannes Millan
2550f91cb7 feat(plugins): add i18n support to procrastination-buster plugin
- Add comprehensive English translations (en.json) for all UI strings
- Add useTranslate() hook for reactive translations
- Update manifest.json with i18n configuration
- Add i18n message handlers to plugin.ts
- Create getProcrastinationTypes() for dynamic translation loading
- Update App.tsx to use translations throughout
- Update ProcrastinationInfo.tsx with full translation support
- All 8 procrastination types, strategies, and info content now translatable

The plugin now supports internationalization with complete English translations
and can easily be extended to support additional languages.
2026-01-16 22:34:50 +01:00
Johannes Millan
eb120baf1b feat(plugins): add i18n support to boilerplate-solid-js
- Add useTranslate() hook for reactive translations in SolidJS
- Include example translation files (en.json, de.json)
- Update Vite plugin to copy i18n folder during build
- Add i18n message handlers to plugin.ts
- Demonstrate i18n usage in App.tsx with ~10 translation keys
- Update documentation with comprehensive i18n guide
- Add i18n to features list in main plugin-dev README

The boilerplate now provides a complete working example of multi-language
plugin support, making it easy for developers to create internationalized
plugins.
2026-01-16 22:34:50 +01:00
Johannes Millan
5bb8b24c82 docs(plugins): add comprehensive i18n documentation
Phase 7: Create documentation

- Create PLUGIN_I18N.md with complete i18n guide
  - Quick start guide with file structure
  - Manifest configuration details
  - Translation file format and best practices
  - Complete API documentation (translate, formatDate, getCurrentLanguage)
  - Language change hook documentation
  - Full list of supported languages (24 languages)
  - Complete working example with multi-language support
  - Best practices and troubleshooting sections
  - Migration guide from hard-coded strings
  - Testing and performance considerations

- Update README.md with i18n section
  - Add i18n API methods to Plugin API section
  - Add languageChange hook to hooks list
  - Add i18n example to usage section
  - Add i18n files to optional files list
  - Add i18n best practice
  - Link to comprehensive PLUGIN_I18N.md guide

Documentation provides complete guide for plugin developers to add
multi-language support to their plugins with working examples.
2026-01-16 17:55:34 +01:00
Johannes Millan
95578ef77b feat(plugins): add plugin i18n foundation (Phase 0-1)
- Add i18n field to PluginManifest type in plugin-api package
- Create PluginI18nService for translation management
  - Load translations from file paths or cached content
  - Nested key lookup with dot notation (e.g., BUTTONS.SAVE)
  - Smart fallback: current language → English → key
  - Parameter interpolation with {{param}} syntax
  - Language switching via signals
  - Memory cleanup for unloaded plugins
- Add type validation for cached translation content
- Document language sync integration points

Part of plugin internationalization system implementation.
Tests will be added in Phase 8.
2026-01-16 17:52:13 +01:00
Johannes Millan
59292abacb refactor(date): use getDbDateStr() utility for consistent date formatting
Replace inline `.toISOString().split('T')[0]` pattern with getDbDateStr()
utility across production code, tests, and plugin examples.

Changes:
- Production: 6 files (plugin-bridge, metrics, counters, task-repeat-cfg)
- Tests: 4 spec files (helper functions and direct uses)
- Plugin example: Added formatDateStr() helper matching main app pattern

This ensures consistent local timezone handling for all user-facing date
operations and provides a single source of truth for date string formatting.
2026-01-16 13:28:05 +01:00
Johannes Millan
f9fd8454cc fix(sync-md): prevent crash when adding subtasks to markdown file directly
Fixes #6021

When users manually added subtasks to markdown files that referenced
non-existent parent tasks, the plugin would crash due to unsafe null
assertions and missing validation. This made the plugin permanently
disabled and required creating a new markdown file to recover.

Changes:
- Added parent ID validation before creating operations
- Orphaned subtasks are now converted to root tasks with warnings
- Added comprehensive error handling with user notifications
- Plugin stays enabled even after sync errors
- Added 15 new tests (689 lines) for orphaned subtask scenarios
- Fixed all existing tests to support new error notifications

The fix implements defense-in-depth:
1. Validation layer: Check parent IDs exist before operations
2. Error handling: Catch and report errors without crashing
3. User feedback: Clear notifications about issues
4. Data preservation: No data loss, orphans become root tasks
2026-01-16 13:28:05 +01:00
Johannes Millan
2f7a00371a fix(supersync): improve GDPR compliance in legal documents
- Remove placeholder address text from privacy policies (DE/EN)
- Expand HTML privacy policy with full GDPR disclosures:
  - Legal bases (Art. 6), data subject rights (Art. 15-22)
  - Supervisory authority, retention periods, DPA info
  - Cookies/tracking and automated decision-making sections
- Align HTML terms with German ToS:
  - Add proper termination notice periods (2 weeks/good cause)
  - Add 6-week notice for ToS amendments
  - Add consumer withdrawal rights (14 days)
  - Add ODR platform link and jurisdiction info
2026-01-15 12:48:18 +01:00
Johannes Millan
a1d736010c fix(plugins): fix empty side panel for AI Productivity Prompts plugin
The plugin was using a custom vite.config.ts that generated separate
JS/CSS files with broken relative paths. When loaded in a blob URL
iframe, these paths couldn't resolve.

- Switch to @super-productivity/vite-plugin which inlines assets
- Fix title from "Procrastination Buster" to "AI Productivity Prompts"
2026-01-15 11:04:12 +01:00
Johannes Millan
cee12a444a fix(sync): pass op.id to uploadSnapshot to prevent ID mismatch
When uploading BACKUP_IMPORT via uploadSnapshot(), the client's op.id
was not sent to the server. The server would generate its own ID,
causing the client to not recognize the operation when downloaded later.
This led to data loss as the old backup state would be re-applied.

Changes:
- Add opId parameter to uploadSnapshot() interface
- Pass op.id from operation-log-upload.service.ts
- Send opId in SuperSync API request payload
- Server uses client's opId instead of generating new one
- Add E2E test to verify ID matching

The fix is backwards compatible - legacy clients without opId still work
as the server falls back to uuidv7() when opId is not provided.
2026-01-14 21:57:08 +01:00
Johannes Millan
e7e693e78f fix(sync-server): add rate limiting to page endpoints
Add explicit per-route rate limits to /verify-email and /magic-login
endpoints to address CodeQL security alerts. These endpoints previously
relied only on global rate limiting.
2026-01-13 18:26:45 +01:00
Johannes Millan
9d77aa2d3f fix(build): add shared-schema to prepare script for CI builds
The shared-schema package was not being built before lint and test
steps in CI, causing "Cannot find module '@sp/shared-schema'" errors.

Changes:
- Add shared-schema:build script to package.json
- Update prepare script to build shared-schema first
- Add shared-schema to build-packages.js for completeness
2026-01-11 16:11:36 +01:00
Johannes Millan
23579a448a fix(shared-schema): use tsup for dual ESM/CJS build
The previous commit changed module resolution to bundler mode which
fixed Angular tests but broke Node.js ESM imports in super-sync-server.

Switch to tsup bundler that outputs both ESM (.mjs) and CJS (.js) formats,
with proper exports field to support both environments:
- CJS for super-sync-server (Node.js commonjs)
- ESM for Angular/webpack bundler imports
2026-01-11 14:05:23 +01:00
Johannes Millan
bc869d359f fix(shared-schema): fix module resolution for bundler compatibility
- Change shared-schema tsconfig to use bundler moduleResolution
- Remove .js extensions from imports (incompatible with bundler mode)
- Fix tsconfig.spec.json to include both package path mappings

The shared-schema package was using NodeNext module resolution which
requires .js extensions in imports. Since the main Angular project
uses bundler resolution and imports directly from source files,
this caused webpack to fail finding the modules during tests.
2026-01-11 13:20:16 +01:00
Johannes Millan
187bfaf24c fix(docker): upgrade npm to v11 to match lockfile version
npm 10.9.4 bundled with node:22-alpine handles optional peer
dependencies differently than npm 11, causing build failures
when resolving vitest peer dep from @angular-devkit/build-angular.
2026-01-10 19:08:38 +01:00
Johannes Millan
6501950760 fix: resolve build issues and update E2E tests for sync import conflict
- Fix TypeScript error in passkey.ts (Buffer to Uint8Array conversion)
- Update Dockerfile.test to use npm install instead of npm ci for workspace sync
- Update E2E test to not setup sync before import
- Add additional unit tests for sync-wrapper.service

Note: E2E tests for sync import conflict dialog need further work due to
automatic upload of SYNC_IMPORT when sync is enabled. The core dialog
functionality is implemented and unit tested.
2026-01-10 18:48:47 +01:00
Johannes Millan
f9620d4f37 feat(sync): add sync import conflict resolution dialog
When all remote operations are filtered due to a local SYNC_IMPORT
(e.g., user changed sync account), show a dialog offering three options:
- Use My Data: Push local state to server (forceUploadLocalState)
- Use Server Data: Accept server state (forceDownloadRemoteState)
- Cancel: Abort sync for now

Changes:
- Extend SyncImportFilterService to return filteringImport operation
- Extend RemoteOpsProcessingService to return filter metadata
- Create DialogSyncImportConflictComponent with Material Dialog
- Create SyncImportConflictDialogService to open the dialog
- Integrate dialog trigger into OperationLogSyncService
- Add translation keys to en.json
- Add comprehensive unit tests (86 tests passing)
- Add E2E test for dialog flow

Also increases maxKeys threshold in super-sync-server validation
to 500K to handle archives with 300K+ keys.
2026-01-10 18:31:37 +01:00
Johannes Millan
63d11b3ac8 fix(build): add missing vite-plugin-solid dep and fix Uint8Array body type
- Add vite-plugin-solid to procrastination-buster plugin dependencies
- Wrap Uint8Array in Blob for fetch body to fix TypeScript error with newer @types/node
2026-01-10 17:17:57 +01:00
Johannes Millan
038a722ed8 style: apply prettier formatting 2026-01-10 17:09:14 +01:00
Johannes Millan
ce91c8b1dc Merge branch 'master' into feat/operation-logs
Resolve merge conflicts:
- package.json: use @types/node@^22.19.5
- sync-form.const.ts: keep eslint-disable for naming convention
- global-config.effects.ts: remove extra blank line
- unlink-all-tasks-on-provider-deletion.effects.ts: keep deprecation notice
- auto-fix-typia-errors.ts: keep better-typed getValueByPath
- undo-task-delete.meta-reducer.spec.ts: keep getLastDeletePayload import
- Accept deletions for files refactored into operation-logs architecture
2026-01-10 17:08:09 +01:00
Johannes Millan
e6da7ced37 chore(deps): upgrade ESLint to v9 with flat config
- Upgrade eslint from v8 to v9.39.2
- Upgrade typescript-eslint to v8.52.0 (unified package)
- Add angular-eslint package for flat config support
- Migrate from .eslintrc.json to eslint.config.js (flat config)
- Update package configs for sync-md, automations, boilerplate-solid-js
- Remove unused eslint-disable directives
- Fix lint errors (empty interface, template eqeqeq)

BREAKING: Requires Node.js 18.18+ (ESLint 9 requirement)
2026-01-10 16:08:11 +01:00
Johannes Millan
db41055feb feat(supersync): add dark mode with WCAG AA compliant colors
Add automatic dark mode support using prefers-color-scheme media query:

- Dark backgrounds: #1a1a1a (page), #2d2d2d (cards)
- Light text: #e5e5e5 (primary), #a3a3a3 (secondary)
- Adjusted primary color for dark: #4db8e8 (7.74:1 contrast)
- Dark variants for warning/success/error message boxes
- Button backgrounds kept darker for white text contrast

Also add consistent link styling for Terms/Privacy links:
- Normal, visited, and hover states use primary color
- Works in both light and dark modes

All colors verified to meet WCAG AA 4.5:1 minimum contrast.
2026-01-06 13:49:50 +01:00
Johannes Millan
e80850fb1e fix(supersync): improve color contrast for WCAG 2.2 compliance #5903
Update CSS color variables to meet WCAG AA 4.5:1 contrast ratio:

- --primary: #0c96e2 → #0077b6 (4.87:1 on white)
- --text-light: #666666#595959 (7.00:1 on white)
- --success: #4caf50 → #2e7d32 (5.13:1 white on bg)
- --error: #f44336 → #c62828 (5.62:1 white on bg)
- .warning-box: #856404 → #6d5200 (6.63:1 on #fff3cd)

All text elements now meet WCAG AA accessibility requirements.
2026-01-06 13:08:46 +01:00
Johannes Millan
b01afbfcd1 fix(sync): address code review findings for operation-logs
Security:
- Add rate limiting (10 req/5min) to GET /snapshot endpoint
- Prevents DoS via CPU-intensive snapshot generation

Consistency:
- Add 30s timeout to download transaction (matches other sync transactions)

Test robustness:
- Fix weak encryption test - always assert error on wrong password
- Update lww-update.meta-reducer tests to use OpLog instead of console

Defensive coding:
- Add entity-not-found warnings in LWW meta-reducer for sync race conditions
- Log when project/tag/parent task deleted before LWW update arrives

Code quality:
- Standardize logging to OpLog in lww-update.meta-reducer
- Document LWW action types as intentionally not in ActionType enum
- Create e2e-constants.ts for centralized E2E test timeouts/delays
- Extract createProjectReliably helper to supersync-helpers.ts (DRY)
2026-01-06 11:42:47 +01:00
Johannes Millan
a42c8a4cee Merge branch 'master' into feat/operation-logs
* master:
  refactor(dialog): remove unused OnDestroy implementation from DialogAddNoteComponent
  fix(calendar): poll all calendar tasks and prevent auto-move of existing tasks
  docs: add info about how to translate stuff #5893
  refactor(calendar): replace deprecated toPromise with firstValueFrom
  build: update links to match our new organization
  add QuestArc to community plugins list
  feat(calendar): implement polling for calendar task updates and enhance data retrieval logic
  fix(heatmap): use app theme class instead of prefers-color-scheme
  fix(focus-mode): start break from banner when manual break start enabled
  feat(i18n): connect Finnish and Swedish translation files
  refactor(focus-mode): split sessionComplete$ and breakComplete$ into single-responsibility effects
  Fixing Plugin API doc on persistence

# Conflicts:
#	src/app/features/issue/store/poll-issue-updates.effects.ts
#	src/app/t.const.ts
2026-01-05 19:12:46 +01:00
Johannes Millan
f0f536671b test(server): fix testing gaps and failing tests
1. Add DELETE /api/sync/data route tests to sync.routes.spec.ts:
   - Test successful deletion returns { success: true }
   - Test 401 without authorization
   - Test uploading new data works after reset

2. Fix passkey.spec.ts failures (4 tests):
   - Add missing passkey.findUnique mock for credential lookup
   - Update test expectations for discoverable credentials
     (no allowCredentials - implementation changed)

3. Fix password-reset-api.spec.ts failures (12 tests):
   - Exclude from vitest - tests routes that don't exist
   - Server uses passkey/magic link auth, not password auth

All 412 tests now pass.
2026-01-05 17:39:17 +01:00
Johannes Millan
e641b89187 test(server): add unit tests for deleteAllUserData (Reset Account)
Add comprehensive unit tests for the reset account functionality:

- Test that deleteAllUserData removes all operations for a user
- Test that new operations can be uploaded after reset
- Test that resetting one user doesn't affect other users' data

Also adds missing userSyncState.deleteMany mock to the test setup.
2026-01-05 15:47:43 +01:00
Johannes Millan
1a79592aca build: update links to match our new organization 2026-01-05 14:45:06 +01:00
Johannes Millan
f9635423d6 feat(server): add Account Settings page with reset and delete options
Add a dedicated Account Settings page to the SuperSync server web interface:

- Move Reset Account and Delete Account buttons from token display to
  separate Account Settings page for better UX
- Reset Account clears all synced data but keeps account active
- Delete Account permanently removes account and all data
- Add E2E tests for account reset functionality

Closes #5848
2026-01-05 12:54:53 +01:00
Johannes Millan
386c636e5f feat(effects): consolidate task update actions in PluginHooksEffects 2026-01-04 13:03:28 +01:00
Johannes Millan
85fa50974b Merge branch 'master' into feat/operation-logs
* master:
  refactor(e2e): improve test infrastructure for easier expansion
  chore(e2e): remove broken/empty skipped tests
  test(e2e): fix flaky plugin and WebDAV sync tests
  refactor(e2e): replace waitForTimeout with condition-based waits
  perf(e2e): remove ineffective waits to speed up test runs
  docs(e2e): add CLAUDE.md reference and barrel export for easier test creation
  build: update dep
  refactor(e2e): simplify waits and fix flaky tests
  feat(e2e): streamline e2e test development with improved infrastructure
  perf(e2e): optimize wait utilities and addTask method for faster test execution
  16.8.1

# Conflicts:
#	e2e/pages/base.page.ts
#	e2e/pages/project.page.ts
#	e2e/tests/reminders/reminders-schedule-page.spec.ts
#	e2e/tests/sync/webdav-sync-advanced.spec.ts
#	e2e/tests/sync/webdav-sync-expansion.spec.ts
#	e2e/tests/sync/webdav-sync-full.spec.ts
#	e2e/utils/waits.ts
2026-01-03 18:51:51 +01:00
Johannes Millan
cbeecfd39a fix(sync): multi-tab vector clock staleness + shared code extraction
Bug fix:
- Fix vector clock cache staleness in multi-tab scenarios by clearing
  cache when acquiring operation write lock. Each browser tab has its
  own in-memory cache, so Tab B's cache could be stale if Tab A wrote
  while Tab B was waiting for the lock.

Shared code extraction (client/server consistency):
- Extract vector clock comparison to @sp/shared-schema
  - Client wraps shared impl with null handling
  - Server imports directly from shared
- Extract entity types to @sp/shared-schema
  - Single source of truth for ENTITY_TYPES array
  - Removes duplicated "must match" comments

Files:
- packages/shared-schema/src/vector-clock.ts (new)
- packages/shared-schema/src/entity-types.ts (new)
- src/app/op-log/store/operation-log-store.service.ts (cache clear)
- src/app/op-log/capture/operation-log.effects.ts (call cache clear)
2026-01-03 18:05:11 +01:00
Johannes Millan
9ddced5648 feat(sync-server): sync email input across all auth forms
- Email is now shared between login, register, and lost passkey forms
- Email persists to localStorage across page reloads
- Typing in any email field updates all others in real-time
2026-01-03 15:50:15 +01:00
Johannes Millan
868ed71c4a fix(sync-server): add migration script for passkey credential IDs
Existing passkeys were stored with double-encoded credential IDs due to
a bug where SimpleWebAuthn's credentialInfo.id (UTF-8 bytes of base64url
string) was stored directly instead of being decoded to raw bytes first.

This migration script converts existing passkeys from the old format
(ASCII bytes of base64url string) to the correct format (raw credential
ID bytes).

Run with: npx ts-node prisma/migrations/migrate-passkey-credentials.ts
2026-01-03 14:44:18 +01:00
Johannes Millan
a57a197d44 fix(sync-server): fix double encoding of passkey credential ID
SimpleWebAuthn's credentialInfo.id is a Uint8Array containing the
base64url-encoded credential ID as UTF-8 bytes, NOT the raw credential
ID bytes. We were storing these ASCII bytes directly, then encoding
them again as base64url during lookup.

During login, the browser sends the original base64url string, which
we decoded to raw bytes - but this didn't match the double-encoded
value stored in the database.

The fix decodes the base64url string from credentialInfo.id before
storing:
1. Convert Uint8Array to UTF-8 string (the base64url string)
2. Decode base64url to get raw credential ID bytes
3. Store raw bytes in database

Now login correctly looks up by raw credential ID bytes.
2026-01-03 13:32:37 +01:00
Johannes Millan
c07d0a4588 fix(sync-server): look up passkey by credential ID instead of email
With discoverable credentials, the user can select any passkey for
this RP. We need to look up the passkey by the credential ID that
comes back from the browser, not by the email the user entered.

This fixes the 401 error when the user's passkey credential ID
doesn't match what we expected based on email lookup.
2026-01-03 13:20:34 +01:00
Johannes Millan
0f8d2cbc42 chore: code review improvements for operation-logs branch
Phase 1 - Code Quality:
- Add clarifying comment in lww-update.meta-reducer.ts explaining
  Date.now() choice for LWW conflict resolution
- Document multi-instance deployment limitations in README.md
  (passkey challenges, snapshot locks)

Phase 2 - Testing:
- Add TODAY_TAG selector edge case tests (deleted/archived tasks)

Phase 3 - Minor Polish:
- Add createValidationErrorResponse() helper to hide Zod validation
  details in production (sync.routes.ts)
- Add database index @@index([userId, opType]) for faster restore
  point queries
2026-01-03 13:17:42 +01:00
Johannes Millan
374ba9873a fix(sync-server): use discoverable credentials for passkey login
Instead of providing allowCredentials (which requires the browser to
match specific credential IDs), let the browser discover all resident
credentials for this RP automatically.

This matches how passkeys.io works and should fix the "no passkeys
available" issue on mobile.
2026-01-03 13:16:01 +01:00
Johannes Millan
f1eab1d8ca debug(sync-server): add detailed credential ID logging for passkey
Log the full credential ID (both hex and base64url) during:
- Registration: to see exactly what's being stored
- Login: to see exactly what's being retrieved from DB

This will help debug why passkeys aren't being found during login.
2026-01-03 13:01:34 +01:00
Johannes Millan
253e55cd2c fix(sync-server): use properly minified SimpleWebAuthn browser v13.2.2
The previous version was reformatted by prettier into 362 lines.
This version is the original minified bundle with version header.
2026-01-03 12:32:50 +01:00
Johannes Millan
d5e196b82b fix(sync-server): use v13 API format in passkey recovery page
The recovery page was using the old SimpleWebAuthn API format:
  startRegistration(options)

Updated to use the v13 format:
  startRegistration({ optionsJSON: options })

This was causing "nothing happens" when clicking Register New Passkey.
2026-01-03 12:14:47 +01:00
Johannes Millan
1fad43d198 fix(sync-server): update SimpleWebAuthn browser library to v13.2.2
The server was updated to @simplewebauthn/server v13.2.2 but the
browser library was still at pre-v13. The v13 API expects options
wrapped as { optionsJSON: options }, causing allowCredentials to be
lost during login with the old library.

This caused "no passkeys found" errors when users tried to login
after registering.
2026-01-03 12:08:04 +01:00