Skip to content

feat(profile): add about me bio field to profile edit and panel - #1285

Merged
fayazg merged 5 commits into
mainfrom
feat/LFXV2-2933
Jul 31, 2026
Merged

feat(profile): add about me bio field to profile edit and panel#1285
fayazg merged 5 commits into
mainfrom
feat/LFXV2-2933

Conversation

@fayazg

@fayazg fayazg commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a free-text About Me (bio) field to the LFX One profile, persisted in Auth0 user_metadata under the bio key (matches the lfx-v2-auth-service contract).
  • Shared types: bio? on UserMetadata, aboutMe? on ProfileHeaderData.
  • Server-side length guard in validateUserMetadata() and client-side Validators.maxLength(...) on the drawer control, both driven by a shared PROFILE_BIO_MAX_LENGTH constant.
  • Edit drawer: lfx-textarea (fixed-height, vertically resizable per the v2 prototype), placed as the first field in Personal Information; wired through onSubmit, populateForm, and the Flow C management-token redirect path.
  • Profile panel: bound the previously-unwired [aboutMe] input (renders with whitespace-pre-line so multi-line bios keep their line breaks).
  • E2E: fill → save → drawer close → optimistic panel update → user_metadata.bio envelope assertion.

External References

Fixes LFXV2-2933

Persist a free-text "About Me" bio in Auth0 user_metadata under the
`bio` key (matches the auth-service contract). Adds the shared type,
a 2000-char server-side length guard, an autoresizing textarea in the
edit drawer, and the panel display binding that was previously unwired.

LFXV2-2933

Signed-off-by: Fayaz G <5818912+fayazg@users.noreply.github.com>
@fayazg
fayazg requested a review from a team as a code owner July 31, 2026 16:10
Copilot AI review requested due to automatic review settings July 31, 2026 16:10
@cursor

cursor Bot commented Jul 31, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches profile user_metadata save/read paths and relies on a not-yet-deployed auth-service contract; changes are narrow and mirror existing profile fields.

Overview
Adds an About Me free-text field stored as Auth0 user_metadata.bio, with shared PROFILE_BIO_MAX_LENGTH (2000) driving the drawer textarea, reactive-form validator, and BFF validateUserMetadata check.

The profile edit drawer gains an About Me lfx-textarea as the first Personal Information field (vertically resizable styling). Save, form seeding, Flow C pending-save replay, and optimistic header updates all include bio. The layout maps profile.bio → panel aboutMe and passes it into lfx-profile-panel; the About block uses whitespace-pre-line so line breaks display correctly.

Shared types add bio? on UserMetadata and aboutMe? on ProfileHeaderData. E2E S4 stubs PATCH /api/profile and asserts drawer close, optimistic panel text, and user_metadata.bio in the request body.

Note: Persistence through NATS depends on the upstream auth-service bio contract being deployed.

Reviewed by Cursor Bugbot for commit f11fe93. Bugbot is set up for automated code reviews on this repo. Configure here.

@fayazg fayazg added the do-not-merge Indicates that the pull request should NOT be merged. label Jul 31, 2026
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4e3f753d-93b3-4f34-a70a-3982f7927b6f

📥 Commits

Reviewing files that changed from the base of the PR and between dafa553 and adfb642.

📒 Files selected for processing (1)
  • apps/lfx-one/src/app/layouts/profile-layout/profile-panel/profile-panel.component.html
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/lfx-one/src/app/layouts/profile-layout/profile-panel/profile-panel.component.html

Walkthrough

The profile edit drawer now supports a 2,000-character About Me bio. The bio is validated, saved in user metadata, restored during profile authorization, and displayed in the profile panel. An end-to-end test covers the update flow.

Changes

Profile About Me support

Layer / File(s) Summary
Bio data contract and validation
packages/shared/src/constants/profile.constants.ts, packages/shared/src/interfaces/profile.interface.ts, packages/shared/src/interfaces/user-profile.interface.ts, apps/lfx-one/src/server/services/user.service.ts
The shared interfaces define aboutMe and bio. A shared constant sets the 2,000-character limit. Server validation rejects longer bios.
Bio editing and persistence
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/...
The profile drawer adds a resizable About Me textarea, loads existing bio values, and sends bio in profile update metadata.
Profile display and flow restoration
apps/lfx-one/src/app/layouts/profile-layout/..., apps/lfx-one/src/app/layouts/profile-layout/profile-panel/profile-panel.component.html
The profile layout maps persisted bio data to the panel and restores bio during Flow C saves. The panel preserves newline characters.
End-to-end update coverage
apps/lfx-one/e2e/profile-edit-drawer.spec.ts
The E2E test verifies the PATCH request, drawer closure, optimistic panel update, and user_metadata.bio envelope.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes adding the About Me bio field to the profile editor and panel.
Description check ✅ Passed The description directly explains the bio field, persistence, validation, UI changes, testing, and upstream dependency.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/LFXV2-2933

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an Auth0-backed About Me bio to profile editing and display.

Changes:

  • Adds shared bio/profile types and 2,000-character validation.
  • Integrates bio editing, persistence, Flow C replay, and panel display.
  • Adds E2E coverage for saving and optimistic rendering.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/shared/src/interfaces/user-profile.interface.ts Adds Auth0 bio metadata type.
packages/shared/src/interfaces/profile.interface.ts Adds panel About Me data.
apps/lfx-one/src/server/services/user.service.ts Validates bio length.
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts Wires bio into editing and saving.
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html Adds the bio textarea.
apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts Maps bio to panel and Flow C.
apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.html Binds About Me to the panel.
apps/lfx-one/e2e/profile-edit-drawer.spec.ts Tests bio save and optimistic display.

Comment thread apps/lfx-one/src/server/services/user.service.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
apps/lfx-one/src/server/services/user.service.ts (2)

256-259: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Use one shared constant for the bio length limit.

The server check repeats 2000, which is also hard-coded in the client validator and textarea. Add a runtime PROFILE_BIO_MAX_LENGTH constant under packages/shared/src/constants/, export it, and use it in all three layers. Use the constant in the error message.

As per coding guidelines, “Keep shared types, constants, enums, and validators in packages/shared/ (@lfx-one/shared) when they define contracts shared across the application and BFF.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/lfx-one/src/server/services/user.service.ts` around lines 256 - 259, Add
and export a shared PROFILE_BIO_MAX_LENGTH constant under
packages/shared/src/constants, then replace the hard-coded bio limit in the
server validation, client validator, and bio textarea configuration with that
constant. Update the server error message in the user service validation to
interpolate the shared value, and import it through the existing `@lfx-one/shared`
exports.

Source: Coding guidelines


257-258: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Centralize the bio length contract.

The server validator, form validator, and textarea repeat the same 2000 literal. A future change can make the client and server accept different limits.

  • apps/lfx-one/src/server/services/user.service.ts#L257-L258: use an exported shared PROFILE_BIO_MAX_LENGTH constant in the comparison and error message.
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts#L60-L60: use the shared constant in Validators.maxLength.
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html#L40-L40: bind [maxlength] to the component value backed by the shared constant.

As per coding guidelines, “Keep shared types, constants, enums, and validators in packages/shared/ (@lfx-one/shared) when they define contracts shared across the application and BFF.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/lfx-one/src/server/services/user.service.ts` around lines 257 - 258,
Centralize the shared bio-length contract in `@lfx-one/shared` by exporting
PROFILE_BIO_MAX_LENGTH. In
apps/lfx-one/src/server/services/user.service.ts:257-258, use it for validation
and the error message; in
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts:60,
use it with Validators.maxLength; and in
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html:40,
bind maxlength to a component value backed by the shared constant.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/lfx-one/src/server/services/user.service.ts`:
- Around line 256-259: Add and export a shared PROFILE_BIO_MAX_LENGTH constant
under packages/shared/src/constants, then replace the hard-coded bio limit in
the server validation, client validator, and bio textarea configuration with
that constant. Update the server error message in the user service validation to
interpolate the shared value, and import it through the existing `@lfx-one/shared`
exports.
- Around line 257-258: Centralize the shared bio-length contract in
`@lfx-one/shared` by exporting PROFILE_BIO_MAX_LENGTH. In
apps/lfx-one/src/server/services/user.service.ts:257-258, use it for validation
and the error message; in
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts:60,
use it with Validators.maxLength; and in
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html:40,
bind maxlength to a component value backed by the shared constant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8042561e-2a84-403c-8bf7-2d019277fb87

📥 Commits

Reviewing files that changed from the base of the PR and between 00d9025 and 5d26a7e.

📒 Files selected for processing (8)
  • apps/lfx-one/e2e/profile-edit-drawer.spec.ts
  • apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.html
  • apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • packages/shared/src/interfaces/profile.interface.ts
  • packages/shared/src/interfaces/user-profile.interface.ts

Drop autoResize and add a scoped override so the bio field renders as a
fixed-height box with a vertical resize handle (field-sizing: fixed,
min-height 80px, resize: vertical), matching the v2 prototype instead of
collapsing to a single line.

LFXV2-2933

Signed-off-by: Fayaz G <5818912+fayazg@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 31, 2026 16:22
@fayazg

fayazg commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Commit 844ac13d — About Me textarea sizing fix

Adjusted the About Me (bio) field in the profile edit drawer to match the v2 prototype:

  • Removed [autoResize]="true" from the lfx-textarea, which (combined with the shared wrapper's field-sizing: content) was collapsing an empty bio to a single line and hiding the resize grip.
  • Added a scoped SCSS override on the bio instance only (.about-me-textarea.p-textarea): field-sizing: fixed; min-height: 80px; resize: vertical; — a taller fixed-height box with a bottom-right drag handle, matching the prototype's .field-block textarea.

The shared lfx-textarea wrapper (used by 16 other call-sites) is untouched — the override is limited to a marker class on this field.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 844ac13. Configure here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.scss (1)

4-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Scope the deep selector to the drawer.

Line [7] removes Angular style encapsulation for the selector that follows. Any matching .about-me-textarea.p-textarea element can receive these styles. Prefix the selector with :host.

Based on learnings, scope component-specific deep selectors to minimize their blast radius.

Proposed fix
-::ng-deep .about-me-textarea.p-textarea {
+:host ::ng-deep .about-me-textarea.p-textarea {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.scss`
around lines 4 - 11, Scope the deep selector in the profile edit drawer
stylesheet by prefixing `.about-me-textarea.p-textarea` with `:host`, while
preserving the existing field-sizing, minimum-height, and vertical-resize
declarations.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.scss`:
- Around line 4-11: Scope the deep selector in the profile edit drawer
stylesheet by prefixing `.about-me-textarea.p-textarea` with `:host`, while
preserving the existing field-sizing, minimum-height, and vertical-resize
declarations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06bdb70e-d96a-4218-aced-7abe4c7feebc

📥 Commits

Reviewing files that changed from the base of the PR and between 5d26a7e and 844ac13.

📒 Files selected for processing (3)
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.scss
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts:219

  • Converting an empty bio to undefined makes JSON omit the key. The PATCH therefore leaves an existing bio unchanged, and applyOptimisticProfileUpdate deliberately drops undefined values, so users cannot clear About Me once it has been set. Preserve the empty string so both persistence and the panel are cleared.
      bio: formValue.bio || undefined,

apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts:254

  • The Flow C replay path also converts an empty bio to undefined, so clearing About Me still fails whenever the save requires management-token authorization. Preserve the empty string here as in the normal drawer save path.
      bio: formData.bio || undefined,

postal_code?: string;
phone_number?: string;
t_shirt_size?: string;
bio?: string;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct that bio isn't in lfx-v2-auth-service main yet — that's the intended landing order. The upstream contract change is in auth-service PR linuxfoundation/lfx-v2-auth-service#65 (feat(user-metadata): add bio (About Me) field), currently open. This self-serve PR is second in the sequence and should merge/deploy after #65; until then the NATS round-trip drops bio as you describe. Added an External References note to the PR description and leaving this thread open as the gating dependency.

- profile-panel: add whitespace-pre-line so a multi-line About Me keeps
  its line breaks in the panel (per cursor)
- profile-edit-drawer.scss: scope the deep selector with :host to limit
  its blast radius (per coderabbitai)
- shared: add PROFILE_BIO_MAX_LENGTH and use it in the server validator,
  form validator, and textarea maxlength instead of the repeated 2000
  literal (per coderabbitai)

LFXV2-2933

Signed-off-by: Fayaz G <5818912+fayazg@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 31, 2026 16:35
@fayazg

fayazg commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Review Feedback Addressed

Commit: dafa5536a

Changes Made

  • profile-panel.component.html: added whitespace-pre-line so a multi-line About Me keeps its line breaks in the panel (per cursor)
  • profile-edit-drawer.component.scss: scoped the deep selector with :host to limit its blast radius (per coderabbitai)
  • packages/shared + user.service.ts + drawer: added a shared PROFILE_BIO_MAX_LENGTH constant and used it in the server validator, the reactive-form validator, and the textarea maxlength, replacing the repeated 2000 literal (per coderabbitai)

No Change Needed (repo-wide pattern, responded on-thread)

  • profile-edit-drawer.component.ts / profile-layout.component.ts — empty bio → undefined (can't clear): all 11 profile fields use the same field || undefined mapping; none clear-to-empty today. Deferred as a form-wide change rather than special-casing bio (per copilot).
  • user.service.tstypeof guard on bio length: the six sibling validators in this method use the same field && field.length > N shape with no type check; hardening belongs across all fields, not just bio (per copilot).

Still Open

Threads Resolved

4 of 5 unresolved threads resolved; 1 intentionally left open (upstream dependency).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/shared/src/constants/profile.constants.ts (1)

20-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an explicit type annotation to the exported constant.

Declare the type of PROFILE_BIO_MAX_LENGTH explicitly because it is part of the shared public contract.

Proposed fix
-export const PROFILE_BIO_MAX_LENGTH = 2000;
+export const PROFILE_BIO_MAX_LENGTH: number = 2000;

As per coding guidelines, TypeScript files must use type annotations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/constants/profile.constants.ts` at line 20, Update the
exported PROFILE_BIO_MAX_LENGTH constant with an explicit number type
annotation, preserving its current value and public contract.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/lfx-one/src/app/layouts/profile-layout/profile-panel/profile-panel.component.html`:
- Line 71: Update the bio container rendering aboutMe() to apply break-words or
an equivalent overflow-wrap style, preserving the existing whitespace-pre-line
styling while ensuring long unbroken text cannot overflow the profile rail.

---

Nitpick comments:
In `@packages/shared/src/constants/profile.constants.ts`:
- Line 20: Update the exported PROFILE_BIO_MAX_LENGTH constant with an explicit
number type annotation, preserving its current value and public contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9056649c-2b46-41cf-b95a-2f31dbda61c4

📥 Commits

Reviewing files that changed from the base of the PR and between 844ac13 and dafa553.

📒 Files selected for processing (6)
  • apps/lfx-one/src/app/layouts/profile-layout/profile-panel/profile-panel.component.html
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.scss
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts
  • apps/lfx-one/src/server/services/user.service.ts
  • packages/shared/src/constants/profile.constants.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.html
  • apps/lfx-one/src/server/services/user.service.ts
  • apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (3)

apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts:222

  • An existing bio cannot be cleared: converting the form's empty string to undefined makes Angular omit bio from the JSON body, so the backend leaves the previous Auth0 value unchanged. Send an empty string so deleting the text is persisted.
      bio: formValue.bio || undefined,

apps/lfx-one/src/app/layouts/profile-layout/profile-layout.component.ts:254

  • The Flow C retry also drops an intentionally cleared bio by converting '' to undefined; after authorization, the PATCH therefore preserves the old value. Keep the empty string in this retry payload just as in the direct-save path.
      bio: formData.bio || undefined,

apps/lfx-one/src/server/services/user.service.ts:260

  • This runtime guard assumes bio is a string, but the controller casts untrusted JSON directly to ProfileUpdateRequest. Values such as an object, number, or short array pass this check and are forwarded over NATS despite violating the auth-service string contract. Validate the type before applying the length limit.
    if (metadata?.bio && metadata.bio.length > PROFILE_BIO_MAX_LENGTH) {
      throw new Error(`Bio is too long (max ${PROFILE_BIO_MAX_LENGTH} characters)`);

Add break-words to the panel's About Me block so a long unbroken token
or URL can't overflow the profile rail; whitespace-pre-line alone only
wraps normal whitespace. Matches the email field's existing wrapping.

LFXV2-2933

Signed-off-by: Fayaz G <5818912+fayazg@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 31, 2026 16:41
@fayazg

fayazg commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Review Feedback Addressed

Commit: adfb64209

Changes Made

  • profile-panel.component.html: added break-words alongside whitespace-pre-line so a long unbroken token/URL in About Me wraps instead of overflowing the profile rail — matches the email field's existing wrapping (per coderabbitai)

Threads Resolved

1 of 2 unresolved threads addressed this iteration.

Still Open

  • user-profile.interface.ts — auth-service contract missing bio (per copilot): intentionally left open as the gating dependency. Blocked on lfx-v2-auth-service#65 (open); this PR must merge/deploy after it. See External References in the PR description.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

apps/lfx-one/src/server/services/user.service.ts:259

  • The length check uses JavaScript UTF-16 code units, but the upstream auth-service contract in PR #65 defines the 2,000-character limit with Go runes and explicitly tests multibyte input. This rejects valid bios containing characters outside the BMP—for example, 1,001 emoji have 1,001 runes but a JavaScript .length of 2,002. The Angular Validators.maxLength and native maxlength added in this PR have the same mismatch. Use a code-point-aware count on both server and client (and replace the native maxlength constraint with equivalent code-point-aware enforcement) so the BFF and UI match the upstream contract.
    if (metadata?.bio && metadata.bio.length > PROFILE_BIO_MAX_LENGTH) {
      throw new Error(`Bio is too long (max ${PROFILE_BIO_MAX_LENGTH} characters)`);

Copilot AI review requested due to automatic review settings July 31, 2026 18:52
@fayazg fayazg removed the do-not-merge Indicates that the pull request should NOT be merged. label Jul 31, 2026

@audigregorie audigregorie left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Clean, well-wired full-stack change. The shared PROFILE_BIO_MAX_LENGTH constant driving both client and server validation is the right pattern, the optimistic-update path is extended consistently across all three save paths, and the E2E stub avoids mutating the real test profile. No line-level defects found — the findings below are all meta / outside-the-diff.

Major — outside the diff

Stale doc comment in profile-panel.component.ts:20-21 — The class docstring still says "About me and LinkedIn are stubbed for now (no source yet) and therefore stay hidden until wired in a follow-up." This PR wires aboutMe from user_metadata.bio (the layout [aboutMe] binding + mapToHeaderData), so the "About me" half of that comment is now inaccurate. The PR touches profile-panel.component.html but not the .ts; update the docstring in the same change so it doesn't mislead future readers.

PR shape — commit subjects missing the (LFXV2-2933) ticket suffix — Per the repo commit rules (global-rules.mdc / .claude/rules/commit-workflow.md), every commit subject must end with the ticket reference derived from the branch (feat/LFXV2-2933(LFXV2-2933)). None of the 5 commits carry the suffix. The branch also contains a merge commit (Merge branch 'main' into feat/LFXV2-2933); /lfx-self-serve-pr-readiness will flag this — rebase before opening the PR.

Upstream sequencing risk (acknowledged but worth guarding) — The PR description notes bio is not yet in lfx-v2-auth-service main (PR #65), so the NATS round-trip drops the value until #65 ships. UX impact: the user types a bio, Save closes the drawer, the optimistic update shows it — but a refetch loses it. The author already states this should merge/deploy after #65; flagging so the merge order is enforced at PR time (block merge until #65 is deployed).

Minor — outside the diff

  • No server-side unit test for the bio length guard. validateUserMetadata now rejects bio.length > PROFILE_BIO_MAX_LENGTH, but there's no unit test covering the new branch. The E2E covers the happy path only. A one-line assertion in the user.service spec would lock in the contract.
  • E2E doesn't exercise the maxlength boundary. S4 fills a short bio and asserts the envelope. It doesn't verify the 2000-char cap is enforced client-side (Validators.maxLength + textarea [maxlength]). A test pasting 2001 chars and asserting Save stays disabled would close the loop.

What's done well

  • Single shared PROFILE_BIO_MAX_LENGTH constant drives the BFF validator, the reactive-form validator, and the textarea [maxlength] — one contract across client and server.
  • whitespace-pre-line break-words on the panel preserves multi-line bios and prevents overflow in the 300px rail.
  • The optimistic-update path (onSubmit, populateForm, Flow C handleProfileAuthReturn, mapToHeaderData) is extended consistently — no half-wired field.
  • E2E stubs PATCH /api/profile so the real test profile is never mutated, and asserts the user_metadata.bio envelope shape.

Rating: 4/5 — solid implementation; the blockers are merge-ordering and PR-shape hygiene, not code defects.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (2)

apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts:222

  • The optimistic value can differ from what is persisted because auth-service trims bio before storing it, but this path emits the raw form value. Leading/trailing whitespace—or a whitespace-only bio—appears in the panel and on drawer reopen until a reload, after which it changes or disappears. Normalize with trim() before building userMetadata, and apply the same normalization in the Flow C replay at profile-layout.component.ts:254.
      bio: formValue.bio || undefined,

apps/lfx-one/src/app/modules/profile/components/profile-edit-drawer/profile-edit-drawer.component.ts:64

  • The 2,000-character limit does not match the upstream contract for non-BMP text. Angular's maxLength, the native maxlength, and the BFF's string.length count UTF-16 code units, while auth-service PR #65 deliberately caps bio at 2,000 Go runes. A bio containing emoji is therefore rejected at roughly half the upstream allowance (for example, 1,001 emoji). Please enforce the shared limit by Unicode code-point count on both client and server and avoid native maxlength, which cannot express that metric.

This issue also appears on line 222 of the same file.

    bio: ['', [Validators.maxLength(PROFILE_BIO_MAX_LENGTH)]],

@fayazg
fayazg merged commit bc4a122 into main Jul 31, 2026
17 checks passed
@fayazg
fayazg deleted the feat/LFXV2-2933 branch July 31, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants