Redesign transactional emails (embedded navy-violet templates) + display name endpoint - #204
Conversation
…dpoint
Extract all five transactional emails into embedded-resource HTML/text
templates with a shared layout and a single-pass {{token}} renderer (no
templating library), restyled on the navy-violet orbital system with
plain-text parts and preheaders; copy and subjects unchanged.
Add PUT /api/profile/name backed by SetNameCommand and User.SetName
(trimmed, 1-50 chars, no uniqueness).
Refs thomasluizon/orbit-ui-mobile#166
Refs thomasluizon/orbit-ui-mobile#167
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Two well-scoped features land cleanly here.
Email redesign (#166): The move from C# string-interpolated HTML blobs to embedded-resource templates with a shared layout is a clear improvement in maintainability. The single-pass Regex.Replace renderer correctly prevents token-injection (substituted values are never re-scanned), user content is HTML-encoded for HTML templates and URL-encoded for URLs, and the ConcurrentDictionary cache is properly scoped to the assembly lifetime. All five templates ship plain-text parts and preheaders; the HTML/text copy split (htmlCopy encodes userName, textCopy stays raw) is handled correctly. Test coverage is thorough: renderer tests hit every template for leftover tokens, verify the no-rescan invariant, and cover missing-template/missing-token failure paths; service tests verify encoding, gradient header, text-part presence, and the token-injection guard end-to-end.
Display name endpoint (#167): PUT /api/profile/name inherits the class-level [Authorize], uses HttpContext.GetUserId() (no IDOR risk), and the domain guard in User.SetName trims then validates — matching the FluentValidation layer. The DomainConstants.MaxUserNameLength constant flows cleanly through to AppConstants for the validator and the agent catalog description update is accurate. Command, validator, and domain tests cover the boundary cases (exact max, trimmed max, whitespace, accented characters, user-not-found).
|
AgentCatalogServiceTests.EveryControllerAction_IsMappedToTheCatalog requires every controller action be registered; add ChallengesController.GetMine and SetHabits to the Manage Social capability's controller-action registry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds ChallengeValidatorsTests for GetUserChallengesQueryValidator and SetChallengeHabitsCommandValidator (previously 0% covered), lifting new-code coverage above the 80% quality gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#276) * feat(api): challenges list endpoint, invite push, participant set-habits (#204) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(api): map challenges list + set-habits to agent catalog (#204) AgentCatalogServiceTests.EveryControllerAction_IsMappedToTheCatalog requires every controller action be registered; add ChallengesController.GetMine and SetHabits to the Manage Social capability's controller-action registry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(api): cover challenges list + set-habits validators (#204) Adds ChallengeValidatorsTests for GetUserChallengesQueryValidator and SetChallengeHabitsCommandValidator (previously 0% covered), lifting new-code coverage above the 80% quality gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>



Summary
#166 — Transactional email redesign. All five emails (verification code, welcome, account deletion, agent step-up reuse, internal support) move out of interpolated C# strings into embedded-resource
.html/.txttemplates undersrc/Orbit.Infrastructure/Email/Templates/with ONE shared layout. A single-pass{{token}}renderer (no templating library; values are never re-scanned, so user content cannot inject tokens) composes them. Restyled on the navy-violet orbital system, dark navy baked in:#020618canvas, flattened#111526cards, violet#7F46F7pill CTA with glow, gradient header band on welcome with solidbgcolorOutlook fallback, Rubik/Inter/Roboto stacks with system fallbacks, hosted no-bg logo with styled alt-text wordmark fallback. Every user-facing email now ships a plain-text part and a preheader. Copy and subjects are byte-identical (the 13 pre-existing email tests pass unchanged).IEmailServiceand all callers untouched.#167 (backend) — Editable display name.
PUT /api/profile/name→SetNameCommand→User.SetName(trims, rejects empty/whitespace, max 50 chars viaDomainConstants.MaxUserNameLength; no uniqueness, it is a display name). FluentValidation mirrors the domain rules. Action registered in the agent catalog underProfilePreferencesWrite.Refs thomasluizon/orbit-ui-mobile#166
Refs thomasluizon/orbit-ui-mobile#167
Paired frontend PR: thomasluizon/orbit-ui-mobile#171 — merge THIS PR first (API contract).
Manual render check (#166 acceptance — run before merge)
@import; gradient rendersValidation
dotnet build0 errors;dotnet test3,196/3,196 (Domain 358 / Infrastructure 1,020 / Application 1,818)🤖 Generated with Claude Code