Merge Huly - #5
Merged
Merged
Conversation
Signed-off-by: Artem Savchenko <armisav@gmail.com>
Signed-off-by: Artem Savchenko <armisav@gmail.com>
* feat(password): add email-confirmed password setup for SSO accounts SSO-only accounts (Google, GitHub, OIDC) now have a secure path to add a password credential without requiring direct session trust. **Problem:** Previously, password setup for SSO users either required an existing password (blocking SSO-only users entirely) or would have needed to trust the session token alone to create a persistent credential — a security gap where a compromised session could silently add a password. **Solution:** Email-confirmed flow that reuses the existing recovery infrastructure: 1. `checkHasPassword` RPC — authenticates via session token, returns whether the account has a password hash set (drives UI branching). 2. `requestPasswordSetup` RPC — authenticates via session token, looks up the account's verified email social ID, generates a recovery token (`restoreEmail` claim), and sends a "Password recovery" email via the existing mail service. No DB schema changes. 3. `PasswordRestore.svelte` (unchanged) handles the link click → calls the existing `restorePassword` RPC → password is set. **UI changes** (`Password.svelte`): - `hasPassword === false` → "Set a password" panel with description and "Send setup link" button - On success → "Check your email for a link to set your password." - On `SocialIdNotFound` → "No email address is linked to your account." with guidance to add one via Account Settings → Manage Identities - `hasPassword === true` → existing "Change password" form (unchanged) **Account client:** Added `checkHasPassword()` and `requestPasswordSetup()` methods to `AccountClientImpl`; both registered as platform resource functions (`login.function.CheckHasPassword` / `login.function.RequestPasswordSetup`). Signed-off-by: Don Kendall <dkendall@ledoweb.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> * test(password): add unit tests for SSO password setup RPCs ssoPassword.test.ts — 12 tests covering: - checkHasPassword: returns true/false for hash+salt presence, false for partial state (hash-only or salt-only), error for missing account - changePassword: rejects empty old/new passwords, rejects wrong oldPassword (hash mismatch) - requestPasswordSetup: sends email when email social ID exists, returns SocialIdNotFound when no email is linked, handles mail service failures gracefully (logs error, does not rethrow) signupTokenGuard.test.ts — added edge-case for empty-string token to document current guard behaviour (token != null passes empty string through; noted as a future hardening opportunity). Signed-off-by: Don Kendall <dkendall@ledoweb.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> * chore(dev): add dev-local webpack proxy for local Docker compose stack Adds a `dev-local` CLIENT_TYPE that proxies webpack dev server requests to a local Docker compose stack (nginx at localhost:8088), following the same pattern as the existing `dev-server`, `dev-huly`, etc. modes. Useful for developing frontend changes against a fully running local backend without needing `huly.local` DNS configuration. Signed-off-by: Don Kendall <dkendall@ledoweb.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> * feat(email): redesign transactional emails with proper HTML and dedicated password setup template All account service email templates were bare <p> tags with no styling, branding, or call-to-action buttons. Replaced with production-quality HTML emails using email-safe table layout and inline CSS. Design: Huly wordmark on dark (#18181B) header, white card body, dark CTA button, subtle border, system font stack. Plain-text versions updated to match for clients that prefer text. Templates improved: - RecoveryHTML/Text — password reset flow - ConfirmationHTML/Text — email verification on signup - InviteHTML/Text — workspace invitation - ResendInviteHTML/Text — re-invitation - OtpHTML/Text — sign-in code with large monospace code display New dedicated template for SSO password setup (PasswordSetupHTML/Text/ Subject) so the setup email has copy distinct from forgot-password recovery. requestPasswordSetup now uses these instead of RecoveryHTML. Subject: "Set a password for your Huly account". Other language files updated with the new PasswordSetup* keys (English copy as fallback — translations can follow separately). Signed-off-by: Don Kendall <dkendall@ledoweb.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> * fix(password): guard requestPasswordSetup against accounts with existing password Add server-side check that rejects requestPasswordSetup calls from accounts that already have a password hash+salt. The setup flow bypasses the old-password requirement in changePassword, so it must be restricted to SSO-only accounts. The UI already guards this branch but defence-in-depth requires the server to enforce it independently. Also adds JSDoc to requestPasswordSetup and extends unit test coverage: - TokenError path for checkHasPassword (invalid/expired token) - BadRequest guard for requestPasswordSetup on password-bearing accounts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> * fix: add missing locale keys and fix eslint/formatting for CI - Add 5 missing SSO password translation keys to all non-en locale files (SetPassword, SSOPasswordDescription, SendSetupLink, SSOPasswordEmailSent, SSONoEmailLinked) to fix locale parity test - Replace non-null assertions with type casts in ssoPassword.test.ts to fix @typescript-eslint/no-non-null-assertion errors - Revert unrelated tracker/github cosmetic changes that triggered pre-existing eslint errors in those packages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> * fix: address review — remove dev/prod changes, translate PasswordSetup strings - Revert dev/prod/webpack.config.js and package.json (per BykhovDenis) - Translate PasswordSetupText and PasswordSetupSubject for all 10 locales (cs, de, es, fr, it, pt-br, pt, ru, tr, zh) - PasswordSetupHTML stays in English (reviewer approved) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com> --------- Signed-off-by: Don Kendall <dkendall@ledoweb.com> Signed-off-by: Don Kendall <kendall@donkendall.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Two-Factor Authentication (2FA) Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Fix test Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Fix test Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Fix tests Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * More test fixes Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Fix tests Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> --------- Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
aonnikov
approved these changes
Mar 23, 2026
ArtyomSavchenko
added a commit
that referenced
this pull request
Jul 23, 2026
…error UX - ImportFromWord now gated: CanImportDocument visibilityTester (Draft + owner/co-author, mirrors editor $isEditable) + query state=Draft, so import can't overwrite In-Review/Approved/Effective/Archived bodies (#1) - remove dead DocContentProvider registry (providers.ts) (#2) - apply normalizeMarkup to candidate + current in /document-import (#3) - export.ts: one numbering instance per ordered list, so separate lists restart at 1 instead of sharing a counter (#4) - /document-import deletes the transient uploaded blob after conversion (#5) - export back to POST + Blob download (no bearer token in URL); revert global express.json to default (large body route was removed); surface apply failures via setPlatformStatus(unknownError) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tnsp7jnnjxrmt3jbyhhuml Signed-off-by: Artem Savchenko <armisav@gmail.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
No description provided.