Skip to content

feat(meetings): meeting details v2 redesign - #3249

Draft
nunoeufrasio wants to merge 25 commits into
mainfrom
feat/meeting-details-v2
Draft

nunoeufrasio wants to merge 25 commits into
mainfrom
feat/meeting-details-v2

Conversation

@nunoeufrasio

@nunoeufrasio nunoeufrasio commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Draft — do not merge. This is the single release PR for the meeting details V2 redesign (epic #1765). Every piece of the epic lands in feat/meeting-details-v2 through its own reviewed PR. Nothing reaches main, and so production, until this PR merges, once the whole project is built. It stays a draft labelled do-not-merge until then.

Why it's open now

  • It's the only place the full check suite runs on the combined code. quality-check.yml (lint, types, unit tests, build) only triggers on PRs into main, so every merge into feat/meeting-details-v2 re-runs it here.
  • It's the running index of what the release contains.

Merged into the integration branch so far

PR Plan ID What
#2914 E0-01 Handoff spec (specs/011-meeting-details-redesign/spec.md)
#2935 E0-01 State matrix, requirements (FR / SC), data model
#2913 E0-04 Testid contract
#2911 E0-05 Scoped design tokens (also edits protected AGENTS.md: needs code-owner review)
#2909 E0-02 View model and action-slot resolver (@lfx-one/shared)
#2910 V2-01 + V2-02 Flag gate on /meetings/:id + V2 scaffold; V1 moved to meeting-join-v1/ byte-identical
#3267 V2-03 Rollout and retirement plan (specs/011-meeting-details-redesign/rollout.md)
#3268 E0-03 ADR: public vs admin meeting surface boundary (docs/architecture/frontend/meeting-surface-boundary.md)
#3270 — Review fixes on the foundation: RSVP surfaces on ended meetings, fail-closed rule, reactive rollback, FR-011
#3269 E1-01 V2 page shell, its meeting lookup (MeetingDetailsStateService) and the gate's TransferState seed handoff
#3272 E1-02 Sticky identity bar (replaces lfx-header on V2): date tile, status subtitle, sign-in / account menu
#3283 E1-03 Header: project context, title, badge row (recurring, type, committees, features), copy link
#3291 E1-04 Privacy chip (resolvePrivacy)
#3295 E1-05 Status pill and shared meetingStatus (adds "Starting soon" before the scheduled start)
#3297 E1-06 Time banner in the rail: date, time range, timezone, announced phase line; shared selected occurrence
#3310 — Rollout decision: #2920 declined, no percentage ramp (rollout.md)
#3313 E2-01 Action slot on the resolver: Join (loading/ready/error, auto-join), interim copy per kind, Organized by
#3321 E2-03 Invitation required: organizer mailto, support-chat fallback
#3322 E2-02 Register: shared registration dialog, optimistic flip to the registrant state
#3323 E2-06 Guest join form, shared join-link fetch, different-email escape hatch
#3344 E2-04 Viewer's own RSVP: status pill, data-my-rsvp, setMyRsvp; BFF /rsvp/me now surfaces lookup failures
#3348 E2-05 RSVP card: answers, confirmation + Change, inline series scope step
#3350 N-01 Meetings without RSVP tracking: explained rsvp-unavailable state, off-state pinned

Still to build before this merges

See specs/011-meeting-details-redesign/spec.md § Work order:

Before marking ready

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings October 4, 2026 23:10
@nunoeufrasio nunoeufrasio added do-not-merge Indicates that the pull request should NOT be merged. meetings An epic, feature, story, task, or bug related to meetings. labels Oct 4, 2026
@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: bfd5b090-1ddb-40c1-be3f-6990bb2e5955

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Copilot review overview

🔵 Needs a closer look

The draft release remains intentionally incomplete and has unresolved past-roster contract inconsistencies.

Review effort: Balanced
Findings: 1 Medium severity · 3 Low severity

Open (4)
What changed in this PR

This draft integration PR establishes the meeting-details V2 foundation behind the existing feature flag while preserving V1.

Changes:

  • Adds the SSR-safe V1/V2 gate and V2 scaffold.
  • Adds view-model resolvers, tests, and scoped design tokens.
  • Documents the redesign’s state model, requirements, selectors, and architecture.
File Description
AGENTS.md Documents scoped token exception.
.claude/​rules/​development-rules.md Adds V2 testid guidance.
.claude/​rules/​styling.md Defines scoped token rules.
apps/​lfx-one/​e2e/​meetings-v2-flag-gate.spec.ts Tests the page gate end-to-end.
apps/​lfx-one/​src/​app/​app.routes.ts Routes meeting details through the gate.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-gate/​meeting-details-gate.component.html Selects deferred V2 or V1.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-gate/​meeting-details-gate.component.spec.ts Tests gate states and fallback.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-gate/​meeting-details-gate.component.ts Implements hydration-safe flag gating.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​meeting-details-page.component.html Adds the temporary V2 scaffold.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​meeting-details-page.component.ts Defines the V2 page component.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-details-page/​meeting-details-page.tokens.scss Adds scoped visual tokens.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-join-v1/​meeting-join.component.html Moves the unchanged V1 template.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-join-v1/​meeting-join.component.spec.ts Moves the unchanged V1 tests.
apps/​lfx-one/​src/​app/​modules/​meetings/​meeting-join-v1/​meeting-join.component.ts Moves the unchanged V1 component.
docs/​architecture/​frontend/​component-architecture.md Documents the dual-tree architecture.
docs/​architecture/​frontend/​public-meeting-join.md Updates V1 location and gate behavior.
docs/​architecture/​frontend/​styling-system.md Documents scoped token layers.
docs/​architecture/​shared/​package-architecture.md Documents Angular compiler test setup.
packages/​shared/​src/​interfaces/​index.ts Exports V2 interfaces.
packages/​shared/​src/​interfaces/​meeting-view-model.interface.ts Defines V2 view-model contracts.
packages/​shared/​src/​utils/​index.ts Exports V2 resolvers.
packages/​shared/​src/​utils/​meeting-calendar.utils.spec.ts Clarifies compiler preloading.
packages/​shared/​src/​utils/​meeting-view-model.utils.spec.ts Tests resolver matrices.
packages/​shared/​src/​utils/​meeting-view-model.utils.ts Implements V2 state resolvers.
packages/​shared/​src/​utils/​meeting.utils.ts Centralizes meeting-end timing.
specs/​011-meeting-details-redesign/​README.md Indexes the feature specification.
specs/​011-meeting-details-redesign/​checklists/​requirements.md Adds specification checks.
specs/​011-meeting-details-redesign/​data-model.md Documents payload-to-state mapping.
specs/​011-meeting-details-redesign/​design-token-deviations.md Records token deviations.
specs/​011-meeting-details-redesign/​requirements.md Defines functional requirements.
specs/​011-meeting-details-redesign/​spec.md Defines scope and rollout invariants.
specs/​011-meeting-details-redesign/​state-matrix.md Defines viewer/state behavior.
specs/​011-meeting-details-redesign/​testid-contract.md Defines stable test selectors.
specs/​011-meeting-details-redesign/​v2-scaffold.md Defines V1/V2 structure and retirement.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/shared/src/utils/meeting-view-model.utils.ts Outdated
Comment thread packages/shared/src/interfaces/meeting-view-model.interface.ts Outdated
Comment thread specs/011-meeting-details-redesign/README.md Outdated
Comment thread specs/011-meeting-details-redesign/state-matrix.md Outdated
nunoeufrasio added a commit that referenced this pull request Oct 5, 2026
* docs(meetings): add the v2 rollout and retirement plan

Adds specs/011-meeting-details-redesign/rollout.md for V2-03. It
separates the two controls: the integration branch decides whether the
code is in production at all (nothing reaches main until release PR
#3249), and MEETING_V2_ENABLED_FLAG decides who sees V2 once it is.

Defines eight stages (build, release, internal testers, extended
testers, signed-in percentage, anonymous, soak, retire), each with who
decides and exit criteria. States that the code default never changes
and targeting is the switch. Gives the anonymous plan: a code change
that needs #2920's server-side evaluation, then an anonymous
LaunchDarkly context ramped by percentage. Adds what is measured, a
rollback table, and flag retirement: this page drops its read of the
shared flag, and the flag itself retires only with the composer.

The V1-deletion checklist is filed as #3266. The README's contents
table now lists the files that actually exist.

Refs #2875

Signed-off-by: Nuno Eufrasio <nmeufrasio@gmail.com>

* docs(meetings): reconcile v2 spec cross-references after the merge

The foundation PRs (#2909, #2910, #2911, #2913, #2914, #2935) now sit
together on feat/meeting-details-v2, so the "pending sibling, not on
main yet" notes they carried are stale. They become plain
cross-references in spec.md, state-matrix.md, data-model.md,
requirements.md, testid-contract.md, v2-scaffold.md and the
meeting-view-model resolver comments.

Also records the newly filed Phase 1 issues (#3250-#3265) in spec.md's
work order and requirements.md's traceability table, and the V1
retirement issue #3266.

Refs #1766

Signed-off-by: Nuno Eufrasio <nmeufrasio@gmail.com>

* docs(meetings): fix rollout plan gating and rollback guidance

Make #2920 the stage 4 entry gate rather than a release blocker,
scope R05 and FR-001 to the stages before the anonymous stage, give
the V1 rollback a targeted-revert path, and stop reusing the D-2 label.

Refs #2875

Signed-off-by: Nuno Eufrasio <nmeufrasio@gmail.com>

* docs(meetings): address review feedback on the rollout plan

Make FR-001 platform-neutral with the signed-in and post-hydration
rules scoped to their stages, limit stage 2 to signed-in states, define
the baseline once a V1 cohort is gone, and re-wrap a spec paragraph.

Refs #2875

Signed-off-by: Nuno Eufrasio <nmeufrasio@gmail.com>

---------

Signed-off-by: Nuno Eufrasio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 5, 2026 00:30

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.

Comment thread specs/011-meeting-details-redesign/requirements.md Outdated
Comment thread specs/011-meeting-details-redesign/rollout.md Outdated
Comment thread specs/011-meeting-details-redesign/spec.md Outdated

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.

Comment on lines +41 to +44
<span class="block bg-[var(--md-accent)] py-[1.5px] text-[8px] font-bold uppercase tracking-[0.05em] text-[var(--md-surface-card)]">{{
startTime | date: 'MMM'
}}</span>
<span class="flex flex-1 items-center justify-center text-[16px] font-bold text-[var(--md-text-heading)]">{{ startTime | date: 'd' }}</span>
protected readonly userMenuItems: MenuItem[] = [
{ label: 'Profile', icon: 'fa-light fa-user', routerLink: '/profile' },
{ separator: true },
{ label: 'Logout', icon: 'fa-light fa-sign-out', url: '/logout', target: '_self' },
Comment on lines +115 to +118
* The attempt is the page's, not this instance's (`claimAutoJoin`), so a remounted slot does not
* open the meeting again. Known limitation until V1 is retired: on a full page load V1 mounts
* first, and if its join URL resolves before the feature flag, V1 auto-joins too, so the viewer can
* get a second tab of the same link. V1 cannot be edited to coordinate (R01).
Comment on lines +135 to +137
| Token | V2 value | Nearest `lfxColors` | Difference | Adopt upstream? |
| ----------------- | --------- | ------------------- | ---------- | ---------------------- | ------------------------------------------------------------------- | ------------------------------ |
| `--md-feature-ai` | `#7c3aed` | n/a | n/a | `violet.600` `#7F22FE` | AI-summary icon only (non-text); prototype violet is less saturated | Yes — converge on `violet.600` |
* feat(meetings): add the v2 invitation-required action

Closes #2879

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): address pre-pr review of the invitation-required action

Refs #2879

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): format the organizer email date in the meeting timezone

Refs #2879

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

---------

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 6, 2026 13:15

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.

* feat(meetings): add the v2 register action

Closes #2878

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): address pre-pr review of the register action

Refs #2878

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): scope a page registration to its own meeting

Refs #2878

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): keep the register handler before private members

Refs #2878

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): key the optimistic registration to its meeting

Refs #2878

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

---------

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 6, 2026 13:41

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.

Copilot review overview

🔵 Needs a closer look

It remains an incomplete draft and contains unresolved credential-replay, SSR-timezone, TransferState-retirement, and documentation issues.

Review effort: Balanced
Findings: 1 High severity · 4 Medium severity · 6 Low severity

Open (11)
Previously missed (2)

In code that hasn't changed since last review

Low severity Update stale ownership description for centralized state

specs/​011-meeting-details-redesign/​v2-scaffold.md:73

This ownership description is stale: MeetingDetailsStateService now derives viewer role, privacy, meeting status, action slot, early-join eligibility, and the shared sign-in URL. Saying the sections derive those states independently misdocuments the centralization that prevents sections from disagreeing.

Low severity Preserve MeetingDetailsSeedService ownership during direct routing

specs/​011-meeting-details-redesign/​v2-scaffold.md:110

Directly routing to the page removes the only MeetingDetailsSeedService provider, while the page state service injects it optionally. The browser would then ignore the server's ready/error TransferState seed, refetch, and initially render a different branch. Include relocating seed ownership in this checklist rather than asserting that the page needs no change.

Comment on lines +107 to +110
<a
[href]="signInHref()"
class="hidden h-[34px] flex-none items-center whitespace-nowrap rounded-full border border-[var(--md-border-strong)] px-[15px] text-[13px] font-semibold text-[var(--md-text-heading)] hover:bg-[var(--md-surface-hover)] focus-visible:shadow-[var(--md-shadow-focus)] focus-visible:outline-none min-[641px]:inline-flex"
data-testid="meeting-identity-bar-create-account">
* feat(meetings): add the v2 guest join form

Closes #2882

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): address pre-pr review of the guest join form

Refs #2882

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): reject a blank guest name and drop a duplicate log

Refs #2882

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

---------

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 08:47

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.

Comment on lines +125 to +129
// A field edited back to invalid since the fetch: hold Join until the form is valid again.
if (value && this.form.invalid) {
return { status: 'idle' };
}
return { status: 'ready', url: buildJoinUrlWithParams(link.url, null, { name: value.name?.trim(), organization: value.organization?.trim() }) };
Comment on lines +60 to +63
public constructor() {
// An IntersectionObserver rather than a scroll listener, re-attached whenever the header element
// changes (it exists only in the `ready` branch). `afterRenderEffect` never runs on the server.
afterRenderEffect((onCleanup) => {
Comment on lines +47 to +49
export class MeetingDetailsPageComponent {
protected readonly state = inject(MeetingDetailsStateService);
protected readonly userService = inject(UserService);
* feat(meetings): load the viewer's own rsvp on the v2 page

Closes #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): address pre-pr review of the viewer's own rsvp

Refs #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): retry and scope the viewer's rsvp, and surface bff failures

Refs #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): read rsvp lookups strictly and keep a saved rsvp

Refs #2880

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

---------

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 09:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

return null;
}

const registrants = await this.getMeetingRegistrantsForUser(req, meetingUid, email, username);
* feat(meetings): add the v2 rsvp card

Closes #2881

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): address pre-pr review of the rsvp card

Refs #2881

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): keep an in-flight rsvp save on its own occurrence

Refs #2881

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

---------

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 11:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Comment on lines +270 to +272
if (input.viewerRole === 'organizer' || input.viewerRole === 'registrant') {
if (input.inviteResponsesEnabled) {
return 'rsvp';
* feat(meetings): explain v2 meetings without rsvp tracking

Closes #3263

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

* fix(meetings): address pre-pr review of the no-rsvp-tracking state

Refs #3263

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

---------

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 12:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Signed-off-by: Nuno Eufrásio <nmeufrasio@gmail.com>

# Conflicts:
#	packages/shared/src/constants/meeting.constants.ts
Copilot AI balanced review requested due to automatic review settings October 9, 2026 14:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge Indicates that the pull request should NOT be merged. meetings An epic, feature, story, task, or bug related to meetings.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants