Skip to content

docs(frontend): revise permission/persona spec pages - #1263

Open
manishdixitlfx wants to merge 12 commits into
mainfrom
docs/LFXV2-2913
Open

docs(frontend): revise permission/persona spec pages#1263
manishdixitlfx wants to merge 12 commits into
mainfrom
docs/LFXV2-2913

Conversation

@manishdixitlfx

Copy link
Copy Markdown
Contributor

Summary

  • Adopts permission-not-persona throughout both spec pages: Core Principle section, auditor vs viewer terminology (per Eric Searcy's June 25/26 review), resolves the Board Member/Contributor context-entry ambiguity, removes the ED persona-guard carve-out for writer actions, reworded P0 API-enforcement gate.
  • Fact-checks current status: PR fix(create): derive lens access from writer grants, not persona alone #1130 and feat(create): rebuild picker as lazy direct-grant tree + search #1193 shipped; LFXV2-2753 rescoped 2026-07-19 and now Discarded (not in progress); flags the ED fast path in writer.guard.ts/newsletter-access.guard.ts as likely a bug per PERMISSIONS.md.
  • Adds a Model Asks section for the platform team (ED relation removal, LF Staff Team → B2B Organization auditor inheritance).

Docs-only change, no application code touched.

LFXV2-2913

Test plan

  • yarn prettier --check on both changed files
  • yarn lint:check (no errors; pre-existing unrelated warning only)
  • Grepped both docs for "persona" — every hit is presentation-only or an explicit FGA-model reference
  • Re-read both docs for cross-doc consistency (terminology, defaulting ladders, ED capability question)

Adopt permission-not-persona throughout both spec pages: add a Core
Principle section, define auditor vs viewer terminology (per Eric
Searcy's June 25/26 review) and apply it consistently, resolve the
Board Member/Contributor context-entry ambiguity Eric flagged as his
most important feedback, remove the ED persona-guard carve-out for
writer actions, and reword the P0 API-enforcement gate per his
"UI guards are degradation, not enforcement" note.

Fact-check the current-status sections: PR #1130 and #1193 have
shipped; LFXV2-2753 was rescoped 2026-07-19 and is now Discarded, not
in progress; the ED fast path in writer.guard.ts and
newsletter-access.guard.ts still grants write, which PERMISSIONS.md
suggests is a bug rather than a deliberate model choice. Add a Model
Asks section for the platform team covering ED-relation removal and
LF Staff Team org-lens inheritance.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI balanced review requested due to automatic review settings July 29, 2026 21:00
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: Pro

Run ID: 1bcb3680-35f4-4ccf-a832-d317fa294024

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

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Two architecture documents define permission-based navigation and authorization for Me, Foundation, Project, and Discovery flows. They separate context access, action authority, persona presentation, discovery, defaulting, edge cases, implementation priorities, and operational metrics.

Changes

Permission and Persona Navigation

Layer / File(s) Summary
Decision axes and permission gates
docs/architecture/frontend/permission-persona-navigation-model-preread.md, docs/architecture/frontend/permission-persona-decision-matrix.md
Defines FGA relation semantics, selector and discovery gates, exact-context checks, and fail-closed authorization.
Context entry and writer authorization
docs/architecture/frontend/permission-persona-navigation-model-preread.md, docs/architecture/frontend/permission-persona-decision-matrix.md
Specifies target resolution and action-specific grants for Me, Foundation, Project, meetings, votes, surveys, and marketing features.
Persona presentation and discovery workflows
docs/architecture/frontend/permission-persona-navigation-model-preread.md, docs/architecture/frontend/permission-persona-decision-matrix.md
Limits personas to presentation, defines LF Staff Mode, and separates discovery actions from selector eligibility.
Persistence, enforcement, and validation
docs/architecture/frontend/permission-persona-navigation-model-preread.md, docs/architecture/frontend/permission-persona-decision-matrix.md
Defines default persistence, grant-loss handling, role priorities, regression cases, contract mappings, permission bundling, follow-ups, and metrics.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: ai-assisted

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the documentation changes to the frontend permission and persona specification pages.
Description check ✅ Passed The description directly explains the documentation updates, authorization model changes, implementation status, and validation performed.
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 docs/LFXV2-2913

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

Revises the frontend permission/persona specifications to make permissions authoritative and personas presentation-only.

Changes:

  • Defines selector, discovery, and contextual writer rules.
  • Adds persona scenarios, defaulting logic, platform-model questions, and operational metrics.
  • Updates status references for shipped permission work.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 13 comments.

File Description
permission-persona-navigation-model-preread.md Expands the target permission and navigation model.
permission-persona-decision-matrix.md Adds detailed permission and persona scenarios.
Comments suppressed due to low confidence (2)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:321

  • Steps 4 and 5 select from the same auditor/role-permitted set, so step 5 is unreachable and step 4 has no deterministic tie-breaker. This conflicts with the examples and acceptance text that require stable selection. Collapse each permission tier into an explicitly stable choice.
3. Choose a project where the user has a writer/manage grant.
4. Choose a project where the user has an auditor/explicit role grant.
5. Choose first grant-permitted project in stable sort order.

docs/architecture/frontend/permission-persona-decision-matrix.md:72

  • This defaulting chain lists an auditor/explicit-role choice and then a first grant-permitted choice, but those are the same candidate set. The latter branch can never run, while the former does not define how to choose among multiple grants. Match the stated stable-order contract by applying the stable tie-break within each permission tier.
- **Default order:** Existing selected project (if still auditor/role-permitted), last selected valid project (if still auditor/role-permitted), project with a writer/manage grant, project with an auditor/explicit role grant, first grant-permitted project in stable sort order, none -> stay in Me/discovery.

Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-decision-matrix.md Outdated
Comment thread docs/architecture/frontend/permission-persona-decision-matrix.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-decision-matrix.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
@manishdixitlfx
manishdixitlfx marked this pull request as ready for review July 29, 2026 21:12
@manishdixitlfx
manishdixitlfx requested a review from a team as a code owner July 29, 2026 21:12
@cursor

cursor Bot commented Jul 29, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Documentation and SVG only; no runtime or authorization behavior changes in this PR.

Overview
Docs-only refresh of the LFX Self Serve permission vs persona contract: guards and OpenFGA checks drive access; personas are presentation-only.

The navigation preread grows from a short meeting note into a full working spec: auditor (not legacy “view”) for Foundation/Project selector and context entry; action-specific permissions (writer, organizer, committee.writer, marketing permissions, etc.); a Current State table (shipped work, ED writerGuard fast path as likely bug, defaulting/selector risks); P0–P5 engineering priorities; and Model Asks for platform (e.g. executive_director grant retained, LF staff org access, named guards for Health Metrics / Marketing Impact / Campaigns).

Adds permission-persona-decision-matrix.md (routing, Me/Discovery/context-entry scenarios, feature rules, edge cases, metrics) and permission-model.svg (grants → permissions → check(user, action, object) → product gates vs personas).

Reviewed by Cursor Bugbot for commit 495a3ff. Bugbot is set up for automated code reviews on this repo. 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.

Actionable comments posted: 2

🤖 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 `@docs/architecture/frontend/permission-persona-navigation-model-preread.md`:
- Around line 302-322: Define a deterministic stable-sort tie-breaker for
equal-priority writer/manage and auditor/explicit-role candidates in the
foundation and project defaulting orders in
docs/architecture/frontend/permission-persona-navigation-model-preread.md:302-322,
then apply the identical ordering rule to the corresponding decision matrix
entries in
docs/architecture/frontend/permission-persona-decision-matrix.md:58-74. Preserve
the existing priority order and fallback behavior while ensuring API ordering
cannot change the selected context.
- Around line 168-184: Align the documentation and implementation guidance so
persona-only signals never grant Foundation/Project context entry: in
docs/architecture/frontend/permission-persona-navigation-model-preread.md:168-184,
state that only ED is a real relation and writer/auditor grants remain
independent authorization inputs; in
docs/architecture/frontend/permission-persona-decision-matrix.md:60-74, require
selector eligibility to ignore persona-role inputs; and at :151-154 and
:187-189, add explicit regression cases preserving the Board Member and
Contributor caveats.
🪄 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: 07272d0f-98ee-4fdc-ac55-d1e1bbb6575d

📥 Commits

Reviewing files that changed from the base of the PR and between c9c0220 and 756c6a3.

📒 Files selected for processing (2)
  • docs/architecture/frontend/permission-persona-decision-matrix.md
  • docs/architecture/frontend/permission-persona-navigation-model-preread.md

Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
- Fix internal contradiction between Core Principle ("never branch on
  role or persona") and the TL;DR/sidebar text implying role-based
  branching. Distinguish access decisions (permission only) from
  presentation decisions (persona allowed).
- Rename "Role pairs" to "Persona pairs" and narrow the "not discrete
  roles anywhere in LFX data" claim: Maintainer is a discrete value in
  CDP role data, just not an FGA relation (verified against
  persona-detection.service.ts).
- Correct the ED-relation write-capability claim: executive_director
  does inherit campaign_manager (write, Campaigns) in addition to
  auditor/marketing_auditor (read) per the live model.fga -
  PERMISSIONS.md's rendered table simply omits those rows. Rework the
  Model Asks ED-removal question to account for every affected ED
  losing marketing_auditor/campaign_manager, not just the one non-staff
  exception, and surface the live tension between Eric Searcy's "should
  probably be removed" and LFXV2-2236 building around keeping the
  relation.
- Reconcile "ED-shaped pages" with LFXV2-2236 (in review): Campaigns
  and Marketing Impact are migrating to named capabilities
  (campaign_manager/marketing_auditor); Health Metrics stays
  intentionally ED-gated. Confirmed via app.routes.ts /
  executive-director.guard.ts that main still gates all three on
  persona alone.
- Fix Me-lens and decision-matrix create/meeting rules that assumed
  Foundation/Project writer as the only path: the shipped picker also
  authorizes committee.writer (meetings/surveys/votes) and
  project.meeting_coordinator (meetings), per writer.guard.ts.
- Make cold-start defaulting deterministic: embed the stable-sort
  tie-breaker inside each grant tier instead of a separate unreachable
  tier, in both docs.
- Add explicit regression-case bullets for the Board Member/Contributor
  no-grant caveats in the decision matrix.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 30, 2026 21:43

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 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (10)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:57

  • The model does not define viewer as discoverability-only across resource types. Current permissions allow viewer-level access to data such as project documents and meeting registrants/RSVPs, so this definition would cause later designs to apply the wrong relation to reads. Describe viewer as resource-specific read eligibility and reserve auditor for each resource's privileged scope.
- **Viewer** — discoverability only. You can tell the thing exists (a public
  meeting, an active project) but you do not get access to what is inside it
  (participants, formation-stage child projects, private documents). Viewer
  is not ordinarily assigned directly: it is conditional on object attributes
  (public/conditional) or inherited from another role you hold (a committee

docs/architecture/frontend/permission-persona-navigation-model-preread.md:226

  • This formula omits the existing project.meeting_coordinator and committee.writer paths documented above and implemented by writerGuard. If the target change is followed literally, removing the ED branch would also regress legitimate meeting coordinators and committee writers. Express the change as retaining the resolved target's action-specific grant while removing only the persona shortcut.
Current writerGuard = Executive Director fast path or canWrite()
Target writerGuard = resolved target context + canWrite()

docs/architecture/frontend/permission-persona-navigation-model-preread.md:235

  • This embeds transient workflow state (in review) in an architecture document; the same pattern recurs for LFXV2-2236/LFXV2-2726 below. docs/reviews/docs-checklist.md §4 requires replacing status trackers because they silently go stale. Keep the ticket IDs and durable dependency/current-code facts, but remove nonterminal states such as “in review” and “not yet started.”
This migration is tracked in LFXV2-2236 ("Add Marketing Ops UI access (FGA guards)," in review as of this writing) — today, all three pages on `main` still gate solely on `executiveDirectorGuard` (a pure persona check with no FGA lookup). Until that ticket merges, treat "Current UI Facts" as describing the actual state, not this target state.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:461

  • The current model has additional non-marketing_ops paths to marketing_auditor: a direct [team#member] assignment and inheritance from a parent project's marketing_auditor. Only campaign_manager is exclusively ED-or-marketing-ops. Consequently, removing ED does not drop Marketing Impact from every non-marketing-ops ED; the impact analysis must distinguish users who retain one of those other read paths.
   - It is also, today, the sole non-`marketing_ops` path to
     `marketing_auditor` (read) and `campaign_manager` (write) — removing
     `executive_director` outright would silently drop marketing dashboard
     and Campaigns capability for **every** ED who is not separately on the
     `marketing_ops` team, not just the one non-staff exception. This has to

docs/architecture/frontend/permission-persona-navigation-model-preread.md:107

  • Documents are not covered by either named guard: DOCUMENT_ROUTES uses only authGuard, and DocumentsDashboardComponent.canUpload currently checks only that the page is project-scoped. Including documents in this ED-fast-path inventory is therefore factually wrong and hides a separate permission-affordance gap from the planned remediation.

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

- The Executive Director fast path is still present in `writerGuard` (`writer.guard.ts`) and in `newsletter-access.guard.ts` on `main` — both grant **write** access unconditionally to ED persona, covering meetings, votes, surveys, mailing lists, newsletters, and documents. The `executive_director` relation does carry one write-capable inheritance today — `campaign_manager`, scoped to the Campaigns feature (see Model Asks below) — but it does not inherit project `writer`, and none of the general write actions these two guards protect are backed by any ED-inherited relation. `PERMISSIONS.md`'s rendered Project table only shows `Executive Director` in view/read rows because it does not render the marketing/campaign relations at all, not because those relations don't exist in the live model (`model.fga`). Granting general project write through this fast path is very likely a bug, not a deliberate model choice, and is tracked separately for removal rather than treated as an open design question.

docs/architecture/frontend/permission-persona-decision-matrix.md:56

  • This top-level Me rule excludes the committee/group targets and meeting-coordinator grant that the same matrix explicitly supports at line 98. As written, it gives implementers conflicting requirements for valid create flows.
- **Create/manage rule:** Allowed only after the action resolves or asks for a target Foundation/Project context and writer permission passes.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:233

  • Keeping Health Metrics ED-persona-gated contradicts this spec's absolute rule that persona never decides whether a route opens or data is readable (Core Principle lines 32-39 and the companion matrix lines 113-116). The current executiveDirectorGuard is explicitly a pure persona check, so the target must either introduce/check a named Health Metrics capability (potentially inherited by ED/LF Staff) or clearly revise the core contract to define this exception.

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

- **Health Metrics** is the one page intended to stay ED-gated by design, not migrated to a shared capability.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:9

  • “Explicit role grant” is never defined, so the selector contract is not implementable. In the current project model, owner/writer/ED already inherit auditor, while meeting_coordinator is an explicit relation that does not; this wording therefore either adds nothing or admits meeting coordinators to contexts whose privileged read permission they lack. Specify the exact qualifying relations, or make project#auditor the single capability checked for context entry.

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

- **Where can I go?** An auditor or explicit role grant controls Foundation/Project context eligibility.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:232

  • This inheritance list omits the model's direct [team#member] assignment path for marketing_auditor. Since this section defines who the new capability guard should admit, leaving that path out makes the target behavior narrower than the actual FGA relation.

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

- **Marketing Impact** should check `marketing_auditor` (read-only, inherited from `executive_director`, `marketing_ops`, or a parent project).

docs/architecture/frontend/permission-persona-decision-matrix.md:12

  • This global rule excludes legitimate viewer-level reads. In the current model, many object details are intentionally guarded by resource viewer (for example project documents and meeting details/registrants), while auditor is reserved for more privileged reads. Define page/data visibility as the resource-specific read capability rather than defaulting every read to auditor or an explicit role.
Data/page visibility -> permission (auditor/explicit role or named capability)

Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
The Jul 29 Copilot review flagged that the ED-relation discussion
argued a position (keep vs. remove) instead of stating what the app
checks. Reframe per the app's own principle: it gates on named
permissions, never on which relation bundles them, so bundling is the
platform team's call, not this document's.

- Current UI Facts: narrow the writer.guard.ts/newsletter-access.guard.ts
  bug description - ED does not inherit project writer, but the model
  does route marketing_auditor/campaign_manager through
  executive_director, which PERMISSIONS.md's rendered table omits.
- Writer Actions: delete the "open model decision" framing (invented
  foundation_insights_viewer vs. open-to-auditors). State plainly that
  Campaigns/Marketing Impact gate on the existing campaign_manager/
  marketing_auditor permissions and Health Metrics stays ED-gated by
  design (LFXV2-2236, in review) - no new capability needed, no
  reference to executive_director from app code.
- Model Asks #1: replace "removal is acceptable provided..." and the
  Eric-vs-LFXV2-2236 tension framing with a neutral permission-bundling
  ask - the app checks auditor/writer/marketing_auditor/campaign_manager
  directly; the platform team may keep, rename, or remove
  executive_director as long as every affected user (the one non-staff
  ED, and the marketing permission edges for every ED) keeps those
  permissions through some bundle.
- Generalize the Me-lens rule blocks and the matching decision-matrix
  sections (Create Action From Me, Existing Item Action From Me,
  Meetings) from "target Foundation/Project + writer permission" to
  "resolved target object (project, foundation, committee, group) +
  the action-specific grant on that object," matching PERMISSIONS.md's
  actual Scheduled Meeting Organizer inheritance (Project Writer,
  Project Meeting Coordinator, Committee Writer).

Verified the Core Principle contradiction, role/persona terminology,
"not discrete roles" overclaim, and defaulting-ladder determinism
findings from the same review were already fixed by the prior
fix(review) commit; CodeRabbit confirmed both of its findings resolved.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 31, 2026 01:15

@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: 2

🤖 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 `@docs/architecture/frontend/permission-persona-decision-matrix.md`:
- Line 90: Update the permission description near the “Required permission”
entry to distinguish target types: use writer permission for Foundation/Project
targets, committee writer for committee or group targets, and scope
project.meeting_coordinator exclusively to meeting actions. Align the wording
with the existing authorization rules referenced by the committee.writer and
project.meeting_coordinator definitions.
- Line 212: Update the meeting “Create/manage” permission contract to match
writerGuard’s implemented executive-director behavior: either remove the
executive-director fast path from writerGuard so contextual organizer-granting
relations are always required, or explicitly add ED as an exception here and in
the downstream permission contract; keep the documented Project/Foundation
Writer, Project Meeting Coordinator, and Committee Writer rules aligned.
🪄 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: 8f2dd56c-62dd-4be2-8984-6eab29199d73

📥 Commits

Reviewing files that changed from the base of the PR and between e6b5e3e and fde6e89.

📒 Files selected for processing (2)
  • docs/architecture/frontend/permission-persona-decision-matrix.md
  • docs/architecture/frontend/permission-persona-navigation-model-preread.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/architecture/frontend/permission-persona-navigation-model-preread.md

Comment thread docs/architecture/frontend/permission-persona-decision-matrix.md Outdated
Comment thread docs/architecture/frontend/permission-persona-decision-matrix.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.

Pull request overview

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

Comments suppressed due to low confidence (10)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:229

  • This target-state formula drops the guard's existing action-specific paths. ProjectContextService.canWrite() checks only project.writer, while writerGuard also admits project.meetingCoordinator for meetings and committee.writer for meetings, surveys, and votes. Implementing the documented target would regress those authorized users; describe retaining the action-specific grant check and removing only the ED fast path.
Current writerGuard = Executive Director fast path or canWrite()
Target writerGuard = resolved target context + canWrite()

docs/architecture/frontend/permission-persona-decision-matrix.md:90

  • This scopes both alternatives to committee/group targets, but meeting_coordinator is a Project relation; only committee.writer applies when the target is a committee/group. The Create Action section correctly distinguishes these cases, so this existing-item rule should do the same to avoid an impossible permission lookup.
- **Required permission:** Viewer/discoverable eligibility or item eligibility for read actions. The action-specific grant on the item's resolved target object for write actions — writer permission for a Foundation/Project target, or committee writer / meeting coordinator when the target resolves to a committee or group.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:238

  • “In review as of this writing” is ephemeral ticket-state tracking and will become false without a code or architecture change. Per docs/reviews/docs-checklist.md:33-49, retain the current implementation summary and ticket link, but omit the mutable workflow status.
None of these three needs a new capability invented for it — the permissions already exist in the model. This migration is tracked in LFXV2-2236 ("Add Marketing Ops UI access (FGA guards)," in review as of this writing) — today, all three pages on `main` still gate solely on `executiveDirectorGuard` (a pure persona check with no FGA lookup). Until that ticket merges, treat "Current UI Facts" as describing the actual state, not this target state.

docs/architecture/frontend/permission-persona-decision-matrix.md:364

  • The direct-URL edge case again narrows authorization to contextual writer, so it conflicts with the documented committee-writer and meeting-coordinator routes. A direct meeting/survey/vote URL must run the same action-specific target check as the picker and writerGuard; otherwise valid committee writers and meeting coordinators are specified to fail closed.
- **Required permission:** Resolved target context plus writer permission.
- **Destination:** Requested route only if writer check passes.
- **Allowed actions:** Continue if authorized.
- **Denied actions:** Redirect or fail closed if target context is missing or writer permission fails.

docs/architecture/frontend/permission-persona-decision-matrix.md:56

  • This still limits Me creates to Foundation/Project writer access, contradicting the corrected Create Action section below and the shipped committee/group target path. Meetings, surveys, and votes may use committee.writer, and meetings may use project.meeting_coordinator, so the top-level Me rule must preserve action-specific targets and grants.

This issue also appears in the following locations of the same file:

  • line 90
  • line 361
- **Create/manage rule:** Allowed only after the action resolves or asks for a target Foundation/Project context and writer permission passes.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:161

  • These examples revert from the action-specific contract above to generic context writer/viewer checks. Scheduled-meeting management follows the organizer-granting relation (which can come from meeting coordinator or committee writer), and vote/survey results have a distinct results-viewer permission rather than following ordinary viewer/discoverability. As written, implementers could deny valid meeting managers or expose results under the wrong read check.

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

- **Pending agenda action:** resolve the target group/project/foundation; allow agenda management only if writer permission applies.
- **Meeting card:** open the meeting with its context; edit/manage only if writer permission applies.
- **Vote or survey:** open the item; view/results follow viewer/discoverable eligibility for that item, edit/close follows writer permission.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:9

  • Making an “explicit role grant” an independent context-entry authority contradicts the key/core contract below that application code never branches on roles and consumes capabilities instead. It is also materially ambiguous: the live model's meeting_coordinator is an explicit Project role that inherits viewer, not auditor, so this wording does not say whether it should open the full Project context. Define selector eligibility as a named capability (for example, auditor inherited through qualifying roles), or model a separate context-entry capability, rather than treating an unspecified role grant as permission.
- **Where can I go?** An auditor or explicit role grant controls Foundation/Project context eligibility.

docs/architecture/frontend/permission-persona-decision-matrix.md:11

  • This role-based selector rule conflicts with the companion spec's rule that application code never branches on roles and checks capabilities. The distinction affects real grants: meeting_coordinator is an explicit Project role in the live model but grants viewer, not auditor, so “auditor or explicit role” leaves its context-entry behavior undefined. Use a named context-entry capability (possibly inherited through qualifying roles) rather than an unspecified role alternative.
Context selector eligibility -> auditor or explicit role grant

docs/architecture/frontend/permission-persona-navigation-model-preread.md:236

  • “Not yet started” is a mutable ticket status that will silently stale in an architecture document. The repository documentation checklist (docs/reviews/docs-checklist.md:33-49) says to replace status tracking with a concise statement of what is implemented and link the outstanding work item; keep the design decision and ticket reference without recording workflow state.

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

- **Health Metrics** stays ED-gated by design — this page does not migrate to a shared capability (LFXV2-2726 is evaluating an LF Staff answer, not yet started).

docs/architecture/frontend/permission-persona-navigation-model-preread.md:480

  • The live b2b_org.auditor relation already accepts [team#member]; the schema itself does not identify an LF Staff team. Project's “global LF Staff Team” entry in PERMISSIONS.md is preserved external inheritance/provisioning metadata, not an expression in model.fga. Therefore a model-only change cannot grant org access: this ask must specify how the LF Staff team tuple is provisioned for every existing and newly created B2B organization (or define a new global relation together with that provisioning), otherwise the requested inheritance remains ineffective.
2. **Org lens for LF staff.** LF staff should get org-lens switching the same
   way they get project/foundation access today — through team inheritance,
   not impersonation. `PERMISSIONS.md` shows Project's Auditor relation
   already inherits from the global LF Staff Team; the B2B Organization
   section does not have the equivalent inheritance. This needs an LF Staff
   Team → B2B Organization auditor inheritance added to the model — a model
   change, not a UI workaround.

Eric reviewed the PR directly (15 inline comments) with a much more
precise, authoritative correction of how OpenFGA actually works than
either bot review captured:

- Core Principle was flatly wrong about the model: roles are not
  "bundles of permissions" and permissions are not "assigned to
  roles." Rewrote per his explanation - relations form a graph
  evaluated transitively across objects, tuples are the concrete data
  edges, and permissions are RuleSets gating API routes, not labels
  attached to a relation. Fixed the "role" -> "relation" mislabeling
  throughout (OpenFGA has no "role" concept).
- Fixed the "code never branches on role or persona" claim - code
  correctly branches on evaluated relation checks; it must never
  branch on persona labels for access decisions. Reworded the key
  rule and the paragraph Eric flagged as self-contradictory.
- TL;DR: "auditor is the only relation that matters for context
  entry" replaces the vaguer "auditor or explicit role grant," per his
  point that any higher relation includes auditor by inheritance.
  "What can I do" no longer flattens to "writer permission" - stated
  as the action-specific relation its API call requires (organizer,
  poll author, etc. are not writer).
- Viewer/Auditor definitions tightened to his exact phrasing
  (privileged data + subordinate/connected objects, not "inside").
- "Current UI Facts": corrected "grants write access unconditionally"
  - the guard only skips its own client-side check and lets the route
    render; it cannot grant an actual write, which is enforced
    downstream. Tied the open question (dead-end vs. real gap) to the
    existing P0 verification ask.
- Model Asks #1 resolved, not left open: per Eric, executive_director
  stays as an FGA relation. Model Asks #2 now points to a filed ticket
  (LFXV2-2936) instead of a dangling "ask," per his push to not leave
  open questions unresolved in an architecture doc.
- LF Staff Mode reframed as an explicitly open product question in
  both docs - Eric's challenge (staff already get broad auditor via
  team inheritance; what would "mode" add beyond that?) has no answer
  in this document, so stop asserting it as a settled requirement.
- Renamed "Meeting Ask" -> "Contract Summary": referencing an
  undefined meeting was out of place; PR review is the actual
  agreement mechanism.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 31, 2026 01:23
CodeRabbit ran the repo's actual guard code and cross-referenced the
existing persona-content-matrix.md (a code-verified reference doc
neither prior pass had linked to):

- Existing Item Action From Me: fixed imprecise wording that implied
  meeting_coordinator applies to committee/group targets - it's scoped
  to meeting actions only; committee.writer covers committee/group
  targets across meetings/surveys/votes.
- Meetings feature decision: this doc states the target model, but
  writer.guard.ts on main still has an unconditional ED-persona fast
  path ahead of the organizer-grant check. Said so explicitly and
  cross-linked persona-content-matrix.md's Meetings write paths table
  instead of letting the two docs silently disagree.
- Cross-linked persona-content-matrix.md from both docs' intros (the
  code-verified current-state reference the "align the persona content
  matrix" follow-up was gesturing at) and updated that follow-up to
  reflect that the matrix already exists.
- Replaced the vague "verify with the platform team" P0 ask with a
  reference to the ticket that already covers it - LFXV2-1662, "Review
  backend write enforcement per managed domain" - found via
  persona-content-matrix.md's own cross-reference.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>

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 2 out of 2 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (18)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:91

  • “Explicit role” is broader than auditor: the live model makes Project Meeting Coordinator directly assignable, but it inherits viewer, not auditor. The later selector/defaulting rules therefore admit meeting coordinators even though lines 9 and 75–78 say evaluated auditor is the sole context-entry relation. Use auditor consistently, or explicitly enumerate any non-auditor roles that should enter a context.
Terminology pass applied throughout this document: everywhere a gate on
selector eligibility or context entry previously said "view permission," it
now reads "auditor or explicit role"; everywhere the meaning was
discoverability only, it reads "viewer/discoverable."

docs/architecture/frontend/permission-persona-decision-matrix.md:93

  • Meeting Coordinator is a Project relation; it does not apply when the resolved target is a committee/group. writerGuard checks project.meetingCoordinator for project-targeted meetings and checks committee.writer for committee/group targets. The current wording attaches both alternatives to the committee/group branch and then incorrectly falls back to writer-only behavior on the next lines.
- **Required permission:** Viewer/discoverable eligibility or item eligibility for read actions. The action-specific grant on the item's resolved target object for write actions: writer permission for Foundation/Project targets; `committee.writer` for committee/group targets; and `project.meeting_coordinator` only for meeting actions.
- **Destination:** Stay in Me or open the item detail/drawer with target context attached.
- **Allowed actions:** Read actions follow item eligibility. Create/manage actions are visible or enabled when writer permission passes.
- **Denied actions:** If writer permission fails, keep eligible view/read actions only.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:246

  • This is not the current writerGuard contract: after the ED shortcut it checks project.writer, Project Meeting Coordinator for meetings, and Committee Writer for meetings/surveys/votes; it does not call a single canWrite(). The target should remove only the ED shortcut while preserving those action-specific paths, otherwise this spec appears to regress the shipped committee/meeting-coordinator support described at line 165.
Current writerGuard = Executive Director fast path or canWrite()
Target writerGuard = resolved target context + canWrite()

docs/architecture/frontend/permission-persona-navigation-model-preread.md:475

  • This also contradicts the Writer Actions decision at line 257, which says retaining, renaming, or removing executive_director remains the platform team's call. Here the same spec marks “keep” as resolved. Choose one status so the target model does not simultaneously leave and settle the platform decision.

1. **Permission bundling for ED-derived capabilities — resolved: keep
   `executive_director` as an FGA relation.** The app checks `auditor`,
   `writer`, `marketing_auditor`, and `campaign_manager` directly and never
   branches on the `executive_director` relation itself (see Writer Actions
   above). Per Eric Searcy's review, the relation stays in the model rather

docs/architecture/frontend/permission-persona-decision-matrix.md:56

  • This still restricts Me create/manage to a Foundation/Project writer, contradicting the supported committee/group targets documented at line 98 and shipped in PR #1193. Committee writers must be able to start meeting/survey/vote flows from Me, and Project Meeting Coordinators can start meetings without project writer.
- **Create/manage rule:** Allowed only after the action resolves or asks for a target Foundation/Project context and writer permission passes.

docs/architecture/frontend/permission-persona-decision-matrix.md:361

  • Direct write URLs have the same non-writer authorization paths as picker navigation: committee-targeted meeting/survey/vote routes use Committee Writer, and project meeting routes accept Project Meeting Coordinator. Requiring writer here contradicts the matrix's own feature decisions and would specify a fail-closed redirect for valid deep links.
- **Required permission:** Resolved target context plus writer permission.
- **Destination:** Requested route only if writer check passes.
- **Allowed actions:** Continue if authorized.
- **Denied actions:** Redirect or fail closed if target context is missing or writer permission fails.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:409

  • These Me acceptance cases reintroduce the writer-only restriction that the Me Lens rules above removed. A committee writer or Project Meeting Coordinator can legitimately complete the supported target-specific flow without project writer, so acceptance must test the action-specific relation instead.
Selected Foundation/Project context + no writer permission = read-only context experience
Me-originated task + target context + writer permission = allowed action

docs/architecture/frontend/permission-persona-decision-matrix.md:109

  • Pending shared-resource actions are not uniformly project-writer operations. Agenda/meeting management uses the meeting Organizer relation, while personal responses use their owner/participant relation. Requiring writer for every modification repeats the same false restriction this matrix avoids in its top-level decision rule.
- **Required permission:** Viewer/discoverable eligibility for the pending item. Writer permission only for actions that modify the target context.
- **Destination:** Pending action detail or target context.
- **Allowed actions:** View/complete personal response actions when eligible. Manage shared resources only with writer permission.
- **Denied actions:** Do not expose target-context management controls when writer permission is absent.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:400

  • This work plan would audit all affordances and Me actions against contextual writer, even though meetings and committee-targeted flows intentionally use other relations. That would direct the implementation to remove valid Meeting Coordinator/Committee Writer paths. Inventory each affordance against its API-required relation instead.

- Inventory every create/manage affordance in Foundation/Project pages.
- Confirm each affordance is gated by contextual writer permission.
- Confirm direct create/edit/admin routes are guarded.
- Confirm backend/downstream writes remain authoritative.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:239

  • The action list immediately above includes meetings, votes, and surveys, but this rule says absence of project writer makes the whole context read-only. That contradicts the documented Project Meeting Coordinator and Committee Writer paths. Gate each affordance by its action-specific relation; do not make project writer a universal switch.
Selected Foundation/Project context + writer permission = create/manage affordances
No writer permission = read-only context experience

docs/architecture/frontend/permission-persona-navigation-model-preread.md:9

  • This extends the auditor-only entry contract to Organization, but the companion matrix never defines Org entry and the current AccountContextService.hasOrgSelectorAccess also admits persona-seeded availableAccounts() with no writer/auditor grant. Either scope this statement to Foundation/Project or document the intended Org migration; otherwise it silently invalidates the existing Board Member Org path without any corresponding decision or work item.

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

- **Where can I go?** Outside of Me, `auditor` access (explicit or inherited) is what's needed to browse into a Foundation/Project/Organization context. It's the only relation that matters for context entry: any higher relation (writer, owner) includes `auditor` by inheritance.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:500

  • The summary reverts to writer-only authorization even though this document's TL;DR and Me rules correctly require the action-specific relation. Project meeting coordinators, committee writers, direct meeting organizers, and response owners can perform supported writes without project writer; this summary would make the agreed contract reject them.
Sidebar/page/content visibility -> persona (presentation only)
Action authority -> existing contextual writer permission
Campaigns/Marketing Impact -> named capability (campaign_manager/marketing_auditor), not ED persona
Health Metrics -> stays ED-gated by design, pending an LF Staff answer (LFXV2-2726)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:475

  • The PR summary says this Model Ask is for ED relation removal, while the document now records the opposite decision: keep executive_director. Update the PR description or this section so approval is not presented as agreement to two contradictory platform asks.

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


1. **Permission bundling for ED-derived capabilities — resolved: keep
   `executive_director` as an FGA relation.** The app checks `auditor`,
   `writer`, `marketing_auditor`, and `campaign_manager` directly and never
   branches on the `executive_director` relation itself (see Writer Actions
   above). Per Eric Searcy's review, the relation stays in the model rather

docs/architecture/frontend/permission-persona-navigation-model-preread.md:124

  • writerGuard is not attached to any Documents route: DOCUMENT_ROUTES contains only the dashboard guarded by authGuard, and the changed route inventory has no document create/edit route. This current-state paragraph therefore incorrectly attributes the ED fast path to document routes. Remove Documents from this list or name the actual guarded route if one exists.
- The Executive Director fast path is still present in `writerGuard` (`writer.guard.ts`) and in `newsletter-access.guard.ts` on `main`: both skip their own permission check for ED persona and let the route open — for meetings, votes, surveys, mailing lists, newsletters, and document create/edit routes. That does not mean the write itself is granted; the UI is subordinate to the API's enforcement, and an ED cannot get project `writer` access just because a guard let the route render. It is very likely a guard bug (a misleading UI-only affordance that a downstream write would then reject) rather than a permission the model grants: `executive_director` does not inherit project `writer`, so none of those general write actions are backed by any ED-inherited relation. Whether this is purely a confusing dead-end (guard says yes, API says no) or an actual gap depends on whether the downstream API independently enforces `writer` for these routes — see the P0 verification ask below. The model does route two _intentional_ marketing permissions through `executive_director` — `marketing_auditor` (read) and `campaign_manager` (write, scoped to Campaigns) — which `PERMISSIONS.md`'s rendered Project table omits entirely, so it looks like ED grants nothing but reads even though the live model (`model.fga`) says otherwise. See Writer Actions and Model Asks below for how the app should check these.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:74

  • viewer is not uniformly “discoverability only” in the live model. Scheduled Meeting viewer access includes registrants/RSVPs, and Committee viewer access includes members, invites, and applications; those viewer relations can come from participant/member grants as well as public flags. Scope this definition to Project/Foundation context discovery instead of teaching that viewer never exposes connected participant data, or implementers may choose the wrong read relation for other object types.
- **Viewer** — discoverability only. You can tell the thing exists and see
  limited (typically public) data about it, but not privileged data or its
  subordinate/connected objects (participants, formation-stage child
  projects, private documents). Viewer is not ordinarily assigned directly:
  it is conditional on object attributes (public/conditional) or inherited
  from another relation you hold (a committee `member` relation always
  inherits `viewer`, too). Maps to Discovery.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:178

  • Vote/survey results do not follow the ordinary viewer relation. The model defines a separate results_viewer relation, and participant result access is conditionally enabled, so a user can view the item but still be denied results. Keep details and result eligibility separate here.
- **Vote or survey:** open the item; view/results follow viewer/discoverable eligibility for that item, edit/close follows writer permission.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:177

  • Existing meeting management is gated by the meeting's organizer relation, not only by project writer. The model also grants organizer through Project Meeting Coordinator, Committee Writer, and direct organizer tuples, so this example incorrectly classifies those authorized users as read-only.

This issue also appears in the following locations of the same file:

  • line 238
  • line 245
  • line 396
  • line 408
- **Meeting card:** open the meeting with its context; edit/manage only if writer permission applies.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:300

  • Group/working-group authorization is already modeled as committee.writer and is already used by the shipped meeting/survey/vote flows described at line 165. Saying the permission still needs to be modeled contradicts the current model and this document's own status. If the remaining gap is coverage for additional group actions, name that gap instead.
- Model group-scoped and working-group-scoped writer permission this cycle.

Comment thread docs/architecture/frontend/permission-persona-decision-matrix.md Outdated
Copilot AI review requested due to automatic review settings July 31, 2026 01:32

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 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (17)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:124

  • This current-state inventory incorrectly includes document create/edit routes: DOCUMENT_ROUTES exposes only the dashboard and neither writerGuard nor newsletterAccessGuard protects it. Conversely, committee create/edit routes do use writerGuard. Correcting the domain list is important because this paragraph drives the later guard-removal inventory.
- The Executive Director fast path is still present in `writerGuard` (`writer.guard.ts`) and in `newsletter-access.guard.ts` on `main`: both skip their own permission check for ED persona and let the route open — for meetings, votes, surveys, mailing lists, newsletters, and document create/edit routes. That does not mean the write itself is granted; the UI is subordinate to the API's enforcement, and an ED cannot get project `writer` access just because a guard let the route render. It is very likely a guard bug (a misleading UI-only affordance that a downstream write would then reject) rather than a permission the model grants: `executive_director` does not inherit project `writer`, so none of those general write actions are backed by any ED-inherited relation. Whether this is purely a confusing dead-end (guard says yes, API says no) or an actual gap depends on whether the downstream API independently enforces `writer` for these routes — see the P0 verification ask below. The model does route two _intentional_ marketing permissions through `executive_director` — `marketing_auditor` (read) and `campaign_manager` (write, scoped to Campaigns) — which `PERMISSIONS.md`'s rendered Project table omits entirely, so it looks like ED grants nothing but reads even though the live model (`model.fga`) says otherwise. See Writer Actions and Model Asks below for how the app should check these.

docs/architecture/frontend/permission-persona-decision-matrix.md:93

  • After line 90 correctly defines action-specific grants, these outcomes again treat project writer as the only write authority. That misclassifies committee writers, meeting coordinators, and organizers; keep the outcome phrased in terms of the required relation.
- **Allowed actions:** Read actions follow item eligibility. Create/manage actions are visible or enabled when writer permission passes.
- **Denied actions:** If writer permission fails, keep eligible view/read actions only.

docs/architecture/frontend/permission-persona-decision-matrix.md:109

  • Pending actions are not uniformly controlled by contextual writer: the document's core principle already cites author-only response edits, and meeting management uses resource-specific organizer authority. Requiring writer for every modification would hide valid personal/resource actions.
- **Required permission:** Viewer/discoverable eligibility for the pending item. Writer permission only for actions that modify the target context.
- **Destination:** Pending action detail or target context.
- **Allowed actions:** View/complete personal response actions when eligible. Manage shared resources only with writer permission.
- **Denied actions:** Do not expose target-context management controls when writer permission is absent.

docs/architecture/frontend/permission-persona-decision-matrix.md:361

  • Direct routes use the same action-specific authorization as other entry points; they are not uniformly project-writer-only. Current meeting routes admit meeting coordinators or committee writers for creation, and existing-resource edits may require a resource relation such as meeting organizer. This edge-case contract would incorrectly fail those valid deep links.
- **Required permission:** Resolved target context plus writer permission.
- **Destination:** Requested route only if writer check passes.
- **Allowed actions:** Continue if authorized.
- **Denied actions:** Redirect or fail closed if target context is missing or writer permission fails.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:181

  • These examples revert to project writer even though the rule immediately above is target object plus action-specific relation. In particular, managing an existing meeting is authorized by the meeting's organizer relation, while committee-scoped meeting/vote/survey flows can use committee.writer; readers implementing from these examples would reject valid users.
- **Pending agenda action:** resolve the target group/project/foundation; allow agenda management only if writer permission applies.
- **Meeting card:** open the meeting with its context; edit/manage only if writer permission applies.
- **Vote or survey:** open the item; view/results follow viewer/discoverable eligibility for that item, edit/close follows writer permission.
- **Document row:** open the document context; upload/folder/link actions follow writer permission.
- **Newsletter draft:** open the draft with its target audience context; edit/delete/send follows writer permission for that context.
- **Newsletter create:** ask for the target Foundation/Project and audience first; then apply writer permission.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:253

  • This leaves Health Metrics persona-gated while the surrounding target contract says ED-shaped pages must use named permissions and never a persona guard. The next paragraph confirms the current Health Metrics guard is the pure executiveDirectorGuard, and this bullet names no capability to replace it, so the target state has an unresolved authorization exception. Either define its permission gate or explicitly revise the core “persona never access” contract.
- **Health Metrics** stays ED-gated by design — this page does not migrate to a shared capability (LFXV2-2726 is evaluating an LF Staff answer, not yet started).

docs/architecture/frontend/permission-persona-navigation-model-preread.md:475

  • This says the platform decision is resolved in favor of retaining executive_director, but line 257 says whether that relation stays, is renamed, or is bundled differently remains the platform team's call. The PR description also presents relation removal as a model ask. These are mutually exclusive statuses; update the document and PR summary to the actual decision.
1. **Permission bundling for ED-derived capabilities — resolved: keep
   `executive_director` as an FGA relation.** The app checks `auditor`,
   `writer`, `marketing_auditor`, and `campaign_manager` directly and never
   branches on the `executive_director` relation itself (see Writer Actions
   above). Per Eric Searcy's review, the relation stays in the model rather

docs/architecture/frontend/permission-persona-navigation-model-preread.md:501

  • The summary collapses all action authority back to contextual writer checks, contradicting the document's own core rule and supported committee-writer, meeting-coordinator, and meeting-organizer paths. Because this block is the proposed contract, it should preserve “resolved target object + action-specific relation.”
Action authority -> existing contextual writer permission
Campaigns/Marketing Impact -> named capability (campaign_manager/marketing_auditor), not ED persona
Health Metrics -> stays ED-gated by design, pending an LF Staff answer (LFXV2-2726)
Me-originated actions -> carry target context before writer checks

docs/architecture/frontend/permission-persona-decision-matrix.md:45

  • This P0 gate contradicts the matrix's governing rule on line 14 by requiring writer for every write. Supported writes also use committee.writer, project.meeting_coordinator, and resource-specific relations such as meeting organizer; making this the generic gate would deny valid create/manage paths.
- **Required permission:** Resolved target context plus server-enforced writer permission.
- **Destination:** Write flow only after UI and API permission checks agree.
- **Allowed actions:** Continue when contextual writer permission passes.
- **Denied actions:** Fail closed if the target context is missing, stale, no-grant, or not writer-permitted.

docs/architecture/frontend/permission-persona-decision-matrix.md:56

  • This excludes the shipped committee/group targets and meeting-coordinator path described later on line 98. Me create/manage actions must resolve any supported target object and check its action-specific relation, not require a Foundation/Project writer in every case.
- **Create/manage rule:** Allowed only after the action resolves or asks for a target Foundation/Project context and writer permission passes.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:246

  • This guard summary is already false for the current implementation and would regress the target: writerGuard also accepts project.meetingCoordinator and committee.writer, and the proposed model repeatedly says to preserve action-specific relations. Removing only the ED fast path must not collapse those supported paths to canWrite().
Current writerGuard = Executive Director fast path or canWrite()
Target writerGuard = resolved target context + canWrite()

docs/architecture/frontend/permission-persona-navigation-model-preread.md:410

  • These Me acceptance cases again require contextual writer, excluding the committee-writer and meeting-coordinator paths documented earlier. Since acceptance criteria are likely to become implementation tests, retain the target-object/action-specific-relation contract here.
Me-originated task + target context + writer permission = allowed action
Me create action + selected target context + writer permission = allowed action

docs/architecture/frontend/permission-persona-navigation-model-preread.md:419

  • A direct edit without project writer is not necessarily unauthorized: existing meeting updates can be authorized by the meeting's organizer relation, and committee-scoped routes have their own relation paths. Phrase this regression around failure of the action-specific relation rather than writer alone.
- Direct edit route without writer permission fails closed or redirects.

docs/architecture/frontend/permission-persona-decision-matrix.md:90

  • This is the “Existing Item” case, but its write list contains only creation/context grants and omits resource-level authority. The current meeting path, for example, requires organizer on the existing meeting for update/delete/registrant operations. Define existing-item writes by their resource/action-specific relation rather than this incomplete grant list.
- **Required permission:** Viewer/discoverable eligibility or item eligibility for read actions. The action-specific grant on the item's resolved target object for write actions: writer permission for Foundation/Project targets; `committee.writer` for committee/group targets; and `project.meeting_coordinator` only for meeting actions.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:401

  • This work item narrows Me-originated actions to writer checks, although the same section's accepted model includes committee writer, meeting coordinator, and resource-specific relations. Make the implementation task resolve the action-specific relation so it does not undo the corrected Me contract.
- Confirm Me-originated actions resolve target context before applying writer checks.

docs/architecture/frontend/permission-persona-decision-matrix.md:209

  • This combines creation and management under project/committee-level creator relations, but the current write-path documentation states that update/delete/registrant operations require organizer on the existing meeting. Without that distinction, the target matrix incorrectly grants or denies existing-meeting management based on the creation relation.
- **Create/manage:** Requires the organizer-granting relation for the target — Project/Foundation Writer, Project Meeting Coordinator (meetings only), or Committee Writer when the target is a committee/group — per `PERMISSIONS.md`'s Scheduled Meeting inheritance (`Organizer` inherits from Project Meeting Coordinator, Committee Writer, Project Writer). This is the target state; `writerGuard` on `main` still has an unconditional ED-persona fast path ahead of this check (documented in [`persona-content-matrix.md`](./persona-content-matrix.md#meetings-write-paths), tracked for removal per Current UI Facts in the preread).

docs/architecture/frontend/permission-persona-navigation-model-preread.md:123

  • PR #1193 already shipped composed BFF endpoints at /api/create-picker/{tree,tree/children,search} that answer what the user can create and where, including committee targets. If this means there is no replacement upstream platform API, say that explicitly; as written, “no committed replacement” contradicts the shipped implementation cited on the preceding line.

This issue also appears in the following locations of the same file:

  • line 124
  • line 176
  • line 245
  • line 253
  • line 401
  • ...and 4 more
- A backend "what can I create, and where" API covering group/committee targets (LFXV2-2753) was rescoped after #1130 shipped and its ticket status is now Discarded — it is not in progress. There is no committed replacement work item for that API today.

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 31, 2026 13:48

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 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (12)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:177

  • This reverts to a blanket writer check even though the target model above explicitly names meeting organizer as an action-specific authority, and the code-verified matrix documents update/delete as guarded by organizer on the meeting. A meeting organizer must not be described as unable to manage the meeting merely because they lack current project writer access.
- **Meeting card:** open the meeting with its context; edit/manage only if writer permission applies.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:410

  • This acceptance block again makes project/foundation writer the universal action gate, so it excludes the already-supported committee-writer and meeting-coordinator paths described at line 165 and in the companion matrix. P3 should consistently evaluate the API-required relation on the resolved target; the same blanket wording also appears in the “Confirm each affordance” bullet above.
Selected Foundation/Project context + writer permission = create/manage affordance visible/enabled
Selected Foundation/Project context + no writer permission = read-only context experience
Me-originated task + target context + writer permission = allowed action
Me create action + selected target context + writer permission = allowed action

docs/architecture/frontend/permission-persona-navigation-model-preread.md:124

  • This inventory also omits Group/Committee create and edit routes: committees.routes.ts applies writerGuard to both with writeFeature: 'committees', so ED persona currently bypasses their project-writer check too. Include that domain so the proposed fast-path removal and regression inventory cover every affected route.
- The Executive Director fast path is still present in `writerGuard` (`writer.guard.ts`) and in `newsletter-access.guard.ts` on `main`: both skip their own permission check for ED persona and let the route open — for meetings, votes, surveys, mailing lists, newsletters, and document create/edit routes. That does not mean the write itself is granted; the UI is subordinate to the API's enforcement, and an ED cannot get project `writer` access just because a guard let the route render. It is very likely a guard bug (a misleading UI-only affordance that a downstream write would then reject) rather than a permission the model grants: `executive_director` does not inherit project `writer`, so none of those general write actions are backed by any ED-inherited relation. Whether this is purely a confusing dead-end (guard says yes, API says no) or an actual gap depends on whether the downstream API independently enforces `writer` for these routes — see the P0 verification ask below. The model does route two _intentional_ marketing permissions through `executive_director` — `marketing_auditor` (read) and `campaign_manager` (write, scoped to Campaigns) — which `PERMISSIONS.md`'s rendered Project table omits entirely, so it looks like ED grants nothing but reads even though the live model (`model.fga`) says otherwise. See Writer Actions and Model Asks below for how the app should check these.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:246

  • This summary drops the existing meeting-coordinator and committee-writer branches from both the current and target guard. The intended change is to remove only the ED-persona shortcut while retaining every action-specific relation check; otherwise implementers could regress the supported committee meeting/survey/vote and meeting-coordinator flows documented above.
Current writerGuard = Executive Director fast path or canWrite()
Target writerGuard = resolved target context + canWrite()

docs/architecture/frontend/permission-persona-navigation-model-preread.md:239

  • This rule still treats project/foundation writer as the only source of every listed affordance, despite the meeting-coordinator and committee-writer exceptions established earlier. Permission absence is also per action: a non-writer meeting coordinator can have a read-only project generally while still receiving the meeting affordance.
Selected Foundation/Project context + writer permission = create/manage affordances
No writer permission = read-only context experience

docs/architecture/frontend/permission-persona-decision-matrix.md:81

  • Explicit context selection should not turn the action model back into a universal writer check. A selected context can legitimately expose a meeting action through meeting_coordinator or a committee-scoped action through committee.writer; keep the permission decision action-specific.
- **Allowed actions:** Explicit selection wins over defaulting. Create/manage follows writer permission for the selected context.

docs/architecture/frontend/permission-persona-decision-matrix.md:73

  • This would hide all create/manage actions from a project meeting coordinator who lacks project writer, even though the Meetings decision below authorizes that relation. Apply the action-specific relation rule instead of collapsing Project context to writer-only.
- **Allowed actions:** Read context data. Create/manage only if writer permission exists for the selected project.

docs/architecture/frontend/permission-persona-decision-matrix.md:116

  • This framing omits non-writer action relations, and the “without writer” scenarios below consequently deny all create/manage work even when the user could hold meeting_coordinator or committee.writer. Writer presence alone cannot classify the whole presentation as writable/read-only; either scope each denial to writer-backed resources or state that no applicable action-specific grant exists.
Persona changes what the experience looks like (layout, emphasis, copy,
ordering). It never decides whether the user can enter the context, read its
data, or write to it — those outcomes are stated below purely in permission
terms (auditor grant, writer grant, named capability).

docs/architecture/frontend/permission-persona-navigation-model-preread.md:257

  • This still presents retention or removal of executive_director as an open platform decision, but Model Ask 1 now says the decision is resolved and the relation will remain. Leaving both positions in the target spec makes the platform contract ambiguous; update this paragraph to reflect the resolved decision.
Whether the `executive_director` relation itself stays in the model, is renamed, or is bundled differently is the platform team's call, not the app's (see Model Asks below) — the app checks `marketing_auditor` and `campaign_manager` directly and does not care which relations feed them. Create/edit/manage routes should not use ED as an authorization shortcut unless the user also has writer permission for the selected target context.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:124

  • The document write paths are not covered by either guard named here. documents.routes.ts protects only the dashboard with authGuard, and DocumentsDashboardComponent.canUpload checks only that a project/foundation context is active, so Upload File/New Folder/Add Link are currently shown without a writer check. Classifying Documents as another ED-fast-path case hides a distinct current-state gap that the P0 verification should inventory separately.

This issue also appears in the following locations of the same file:

  • line 124
  • line 177
  • line 238
  • line 245
  • line 407
- The Executive Director fast path is still present in `writerGuard` (`writer.guard.ts`) and in `newsletter-access.guard.ts` on `main`: both skip their own permission check for ED persona and let the route open — for meetings, votes, surveys, mailing lists, newsletters, and document create/edit routes. That does not mean the write itself is granted; the UI is subordinate to the API's enforcement, and an ED cannot get project `writer` access just because a guard let the route render. It is very likely a guard bug (a misleading UI-only affordance that a downstream write would then reject) rather than a permission the model grants: `executive_director` does not inherit project `writer`, so none of those general write actions are backed by any ED-inherited relation. Whether this is purely a confusing dead-end (guard says yes, API says no) or an actual gap depends on whether the downstream API independently enforces `writer` for these routes — see the P0 verification ask below. The model does route two _intentional_ marketing permissions through `executive_director` — `marketing_auditor` (read) and `campaign_manager` (write, scoped to Campaigns) — which `PERMISSIONS.md`'s rendered Project table omits entirely, so it looks like ED grants nothing but reads even though the live model (`model.fga`) says otherwise. See Writer Actions and Model Asks below for how the app should check these.

docs/architecture/frontend/permission-persona-decision-matrix.md:134

  • This scenario incorrectly makes an ED without project writer entirely read-only, even though the preread establishes that campaign_manager is a write-capable named capability inherited by executive_director. The matrix should preserve Campaigns writes when that capability passes while denying unrelated project writes.
- **Allowed actions:** Read ED-shaped pages only where the named capability
  behind them (see Model Asks in the preread) is granted — not because the ED
  persona is detected.
- **Denied actions:** Create/edit/manage routes and affordances.

docs/architecture/frontend/permission-persona-decision-matrix.md:64

  • The Foundation default case falls back to blanket project writer authorization, contradicting the matrix's P0 rule and its supported meeting-coordinator/committee-writer paths. Context entry still requires auditor access, but each affordance must use its own API-required relation.

This issue also appears in the following locations of the same file:

  • line 73
  • line 81
  • line 113
- **Allowed actions:** Read context data. Create/manage only if writer permission exists for the selected foundation.

Embed permission-model.svg in the preread (right after Core
Principle) and point to it from the decision matrix.

Two labels in the diagram have drifted from the current doc text -
flagging rather than silently shipping the mismatch:

- Diagram subtitle: "Roles are bundles of permissions in OpenFGA."
  Eric Searcy's review corrected this exact claim in the Core
  Principle text (relations are a transitively-evaluated graph;
  permissions are RuleSets on API routes, not labels attached to a
  relation) - the diagram was drawn before that correction landed.
- Diagram footer: "Keep, rename, or remove any bundle (ED relation,
  teams) - the platform team's call," presenting the ED-relation
  question as still fully open. Model Asks #1 now states this is
  resolved: per Eric's review, executive_director stays as an FGA
  relation.

Everything else checked clean against the final doc text: the four
product gates (viewer / auditor-or-explicit-role / campaign_manager +
marketing_auditor / action-specific relation on resolved target),
persona-as-presentation-only, and the bundling examples
(LF Staff Team -> auditor, executive_director -> marketing_auditor +
campaign_manager, committee member -> viewer, project writer ->
committee.writer) all match model.fga and the current doc revisions.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 31, 2026 14:26

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 2 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (8)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:93

  • “Explicit role grant” is broader than auditor: a direct project meeting_coordinator tuple is an explicit user/object grant, but the live model includes it in viewer, not auditor. This wording would therefore make a grant that this spec intentionally supports only from Me eligible for Foundation/Project context entry, contradicting lines 77–80 and 167. Use the evaluated auditor relation for selector/context eligibility; qualifying writer/owner/ED grants already inherit it.
Terminology pass applied throughout this document: everywhere a gate on
selector eligibility or context entry previously said "view permission," it
now reads "auditor or explicit role"; everywhere the meaning was
discoverability only, it reads "viewer/discoverable."

docs/architecture/frontend/permission-persona-navigation-model-preread.md:503

  • The contract summary falls back to blanket contextual writer checks even though this spec now preserves action-specific paths such as committee writer, meeting coordinator, and response owner. Those users may legitimately lack project writer, so implementers following the summary would regress supported actions. Keep the condensed contract aligned with the target-object + API-required relation rule.
Action authority -> existing contextual writer permission
Campaigns/Marketing Impact -> named capability (campaign_manager/marketing_auditor), not ED persona
Health Metrics -> stays ED-gated by design, pending an LF Staff answer (LFXV2-2726)
Me-originated actions -> carry target context before writer checks

docs/architecture/frontend/permission-persona-navigation-model-preread.md:259

  • This paragraph still says the ED relation may be removed or renamed, but Model Ask 1 below now records the resolved decision to keep executive_director. Reconcile this target-state paragraph with that decision; otherwise the same spec gives platform implementers opposite requirements.
Whether the `executive_director` relation itself stays in the model, is renamed, or is bundled differently is the platform team's call, not the app's (see Model Asks below) — the app checks `marketing_auditor` and `campaign_manager` directly and does not care which relations feed them. Create/edit/manage routes should not use ED as an authorization shortcut unless the user also has writer permission for the selected target context.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:412

  • These Me-originated acceptance cases still require blanket writer permission, contradicting the action-specific contract added earlier. Committee writers and meeting coordinators can perform supported creates without project writer, and response owners can perform personal actions without any writer relation. Acceptance should validate the API-required relation on the resolved target instead.
Me-originated task + target context + writer permission = allowed action
Me create action + selected target context + writer permission = allowed action

docs/architecture/frontend/permission-persona-decision-matrix.md:14

  • This alternative admits more than the target auditor relation. For example, project#meeting_coordinator is an explicit role tuple but does not inherit auditor in the live model; the preread explicitly says such a user may act from Me without project-level auditor access. Making every explicit role selector-eligible contradicts that flow. Define context entry solely by the evaluated auditor relation.
Authoritative role/permission model -> selector eligibility and defaulting
Context selector eligibility -> auditor or explicit role grant
Data/page visibility -> permission (auditor/explicit role or named capability)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:478

  • The PR summary says this Model Ask concerns removing the ED relation, but the updated section now records the opposite decision: keep executive_director. Update the PR description so reviewers and future readers are not given a stale statement of the change’s purpose.
1. **Permission bundling for ED-derived capabilities — resolved: keep
   `executive_director` as an FGA relation.** The app checks `auditor`,
   `writer`, `marketing_auditor`, and `campaign_manager` directly and never
   branches on the `executive_director` relation itself (see Writer Actions
   above). Per Eric Searcy's review, the relation stays in the model rather
   than being removed or replaced — it remains the bundle that carries

docs/architecture/frontend/permission-persona-navigation-model-preread.md:126

  • The current-state route inventory is inaccurate: writerGuard protects meetings, committees, mailing lists, surveys, and votes, while newsletterAccessGuard protects newsletters; Documents has only an authenticated dashboard route and its write controls are inline rather than create/edit routes. Replace Documents with Committees here so this fact-check section matches the route tables.
- The Executive Director fast path is still present in `writerGuard` (`writer.guard.ts`) and in `newsletter-access.guard.ts` on `main`: both skip their own permission check for ED persona and let the route open — for meetings, votes, surveys, mailing lists, newsletters, and document create/edit routes. That does not mean the write itself is granted; the UI is subordinate to the API's enforcement, and an ED cannot get project `writer` access just because a guard let the route render. It is very likely a guard bug (a misleading UI-only affordance that a downstream write would then reject) rather than a permission the model grants: `executive_director` does not inherit project `writer`, so none of those general write actions are backed by any ED-inherited relation. Whether this is purely a confusing dead-end (guard says yes, API says no) or an actual gap depends on whether the downstream API independently enforces `writer` for these routes — see the P0 verification ask below. The model does route two _intentional_ marketing permissions through `executive_director` — `marketing_auditor` (read) and `campaign_manager` (write, scoped to Campaigns) — which `PERMISSIONS.md`'s rendered Project table omits entirely, so it looks like ED grants nothing but reads even though the live model (`model.fga`) says otherwise. See Writer Actions and Model Asks below for how the app should check these.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:62

  • The image alternative text repeats both stale abstractions that the accompanying prose rejects: relations/roles are not permission bundles, and the access check evaluates a relation rather than an API action. Correct the alt text as well as the visible SVG so screen-reader and image-fallback users receive the same model.

This issue also appears in the following locations of the same file:

  • line 90
  • line 259
  • line 411
  • line 500
![LFX SS permission-based access model: FGA grant bundles resolve to permissions; the app asks check(user, action, object); product gates consume permissions; personas shape presentation only](./permission-model.svg)

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 31, 2026 14:55

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 2 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (5)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:126

  • This current-state inventory incorrectly includes document create/edit routes under the ED fast paths. documents.routes.ts defines only the dashboard route with authGuard; document writes are in-page controls, while writerGuard actually protects committee create/edit routes (as the linked persona-content-matrix.md also records). Keeping this list as written sends the P3 guard audit toward a nonexistent document route and omits a real guarded domain.
- The Executive Director fast path is still present in `writerGuard` (`writer.guard.ts`) and in `newsletter-access.guard.ts` on `main`: both skip their own permission check for ED persona and let the route open — for meetings, votes, surveys, mailing lists, newsletters, and document create/edit routes. That does not mean the write itself is granted; the UI is subordinate to the API's enforcement, and an ED cannot get project `writer` access just because a guard let the route render. It is very likely a guard bug (a misleading UI-only affordance that a downstream write would then reject) rather than a permission the model grants: `executive_director` does not inherit project `writer`, so none of those general write actions are backed by any ED-inherited relation. Whether this is purely a confusing dead-end (guard says yes, API says no) or an actual gap depends on whether the downstream API independently enforces `writer` for these routes — see the P0 verification ask below. The model does route two _intentional_ marketing permissions through `executive_director` — `marketing_auditor` (read) and `campaign_manager` (write, scoped to Campaigns) — which `PERMISSIONS.md`'s rendered Project table omits entirely, so it looks like ED grants nothing but reads even though the live model (`model.fga`) says otherwise. See Writer Actions and Model Asks below for how the app should check these.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:255

  • This exception contradicts the target contract stated throughout these artifacts: lines 18–20 say every access gate is an evaluated relation check, the companion matrix says persona never decides whether data can be read, and the diagram says persona “never gates access.” An ED persona guard for Health Metrics is still an access decision. Either assign this page a named capability like the other pages, or explicitly revise the core contract, matrix, and diagram to document a deliberate persona-authorized exception.
- **Health Metrics** stays ED-gated by design — this page does not migrate to a shared capability (LFXV2-2726 is evaluating an LF Staff answer, not yet started).

docs/architecture/frontend/permission-persona-navigation-model-preread.md:477

  • The PR summary says this Model Asks section proposes removing the ED relation, but the changed spec now records the opposite resolved outcome: keep executive_director as the bundle for the named capabilities. Update the PR description so reviewers and linked-ticket readers are not given the superseded platform ask.
1. **Permission bundling for ED-derived capabilities — resolved: keep
   `executive_director` as an FGA relation.** The app checks `auditor`,
   `writer`, `marketing_auditor`, and `campaign_manager` directly and never
   branches on the `executive_director` relation itself (see Writer Actions
   above). Per Eric Searcy's review, the relation stays in the model rather

docs/architecture/frontend/permission-persona-navigation-model-preread.md:257

  • This architecture doc reintroduces volatile implementation-status prose (not yet started on line 255 and in review as of this writing here), which will become stale as soon as either ticket moves. The repository’s documentation checklist explicitly says to replace status trackers with stable implementation facts and ticket links (docs/reviews/docs-checklist.md:33-49). Keep the verified current guard behavior, but link the tickets without snapshotting their workflow state.
None of these three needs a new capability invented for it — the permissions already exist in the model. This migration is tracked in LFXV2-2236 ("Add Marketing Ops UI access (FGA guards)," in review as of this writing) — today, all three pages on `main` still gate solely on `executiveDirectorGuard` (a pure persona check with no FGA lookup). Until that ticket merges, treat "Current UI Facts" as describing the actual state, not this target state.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:9

  • This “auditor is the only relation” rule conflicts with the selector contract repeated later as “auditor or explicit role grant.” The Core Principle defines an explicit role grant as any direct user-object tuple, and the live Project model has a concrete counterexample: meeting_coordinator: [user] does not imply Project auditor. Under line 9 that user cannot enter the Project context; under lines 208/270 and the companion matrix they can. Define which explicit relations qualify for context entry, or make the contract consistently auditor-only.

This issue also appears in the following locations of the same file:

  • line 126
  • line 255
  • line 257
  • line 473
- **Where can I go?** Outside of Me, `auditor` access (explicit or inherited) is what's needed to browse into a Foundation/Project/Organization context. It's the only relation that matters for context entry: any higher relation (writer, owner) includes `auditor` by inheritance.

Lexicon pass across both spec pages per the team's agreed vocabulary
(model / grants / permissions / guards / personas): retires "role" and
"grant bundle"/"bundling" except where quoting legacy code identifiers
or UI copy (cdp_roles' `role` field, the "Roles" filter chip) - both
marked legacy inline. "Relation" is retired wherever it meant an
evaluated permission ("the action-specific relation the API requires"
-> "the action-specific permission..."); it stays only where it
describes the model's own graph structure. "auditor or explicit role
grant" -> "auditor or another explicit permission" throughout. Core
Principle rewritten around the agreed doctrine sentence; the
role-as-bundle paragraph is gone, replaced by the one agreed line
("Grants and the model are the platform team's domain").

Compression pass: preread's Core Principle and terminology sections
(now a five-term Terminology section replacing the old Viewer/Auditor
discussion, folding those two in as permission examples) tightened
substantially; "Why This Is Needed" cut (it restated the TL;DR in new
words); "Current UI Facts" collapsed from narrative to a status table;
"Open Follow-Ups" folded into P3's regression-test bullets and cut
otherwise. Decision matrix keeps its scenario structure unchanged -
lexicon pass only.

Added the open Health Metrics question exactly as posed to Eric
Searcy (Model Ask #3): writer permission on a context should surface
Health Metrics too, via either a model change (writer feeds
marketing_auditor) or a guard change (Health Metrics accepts writer OR
marketing_auditor) - not resolved here.

Diagram replaced with the fully-relabeled ~/lfx/permission-model.svg
(GRANTS / evaluated by the model / PERMISSIONS / GUARDS / personas
outside the model). Two labels remain drifted from the doc text after
this pass - flagging rather than silently shipping the mismatch:

- Context Entry gate chip still reads "auditor / explicit role" (the
  doc now says "auditor or another explicit permission").
- Create/Manage Actions gate chip still reads "action-specific
  relation on target" (the doc now says "...permission on target").

Consistency grep: zero unmarked "role"/"bundle" instances in either
doc.

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings August 3, 2026 14:37
@manishdixitlfx

Copy link
Copy Markdown
Contributor Author

@emsearcy the lexicon pass is up (63a0a7e).

  • Both spec pages now use the agreed vocabulary throughout (model / grants / permissions / guards / personas); "role" and "grant bundle"/"bundling" are retired except where quoting legacy code identifiers or UI copy (marked legacy inline). Core Principle rewritten around the doctrine sentence; bundling talk collapsed to the one agreed line.
  • Preread is noticeably shorter: "Why This Is Needed" cut, "Current UI Facts" collapsed to a status table, terminology tightened into a five-term section.
  • Decision matrix keeps its scenario structure, lexicon pass only.
  • Diagram swapped to the fully-relabeled version. Two gate-chip labels in the SVG are still drifted from the doc text after this pass (Context Entry still says "auditor / explicit role", Actions still says "action-specific relation on target") — flagged in the commit message rather than silently shipped; let me know if you want those chips relabeled too.
  • Added the Health Metrics / writer-vs-marketing_auditor question to Model Asks exactly as posed to you — left open, not resolved unilaterally.

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 2 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (8)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:221

  • Keeping Health Metrics behind the pure persona-based executiveDirectorGuard in the target state contradicts the preceding “never on a persona guard” rule, the Core Principle, and the companion matrix's permission-only page-visibility rule. Since Model Ask #3 is unresolved, describe this as a current exception awaiting a named permission decision rather than a settled target, or qualify the permission-only contract.
- **Health Metrics** stays ED-gated by design — this page does not migrate to a shared permission (LFXV2-2726 is evaluating an LF Staff answer, not yet started; see also the open Paul/Jim question in Model Asks).

docs/architecture/frontend/permission-persona-navigation-model-preread.md:27

  • This blanket prohibition still contradicts the next paragraph and the companion matrix, both of which require persona-driven presentation. Restrict it to authorization/data-access decisions so implementers are not told both to shape the UI by persona and never branch on persona.

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

App code never branches on personas. Every gate is a permission check — can
user U do action A on object O. Guards define which permission each action
needs.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:132

  • These examples revert to blanket writer checks immediately after documenting action-specific alternatives. Meeting organizers can derive authority from Meeting Coordinator or Committee Writer, and vote/survey writers can derive from the committee target, so these examples would mis-specify valid Me actions.
- **Pending agenda action:** resolve the target group/project/foundation; allow agenda management only if writer permission applies.
- **Meeting card:** open the meeting with its context; edit/manage only if writer permission applies.
- **Vote or survey:** open the item; view/results follow viewer/discoverable eligibility for that item, edit/close follows writer permission.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:212

  • canWrite() is the project-writer check, so this proposed target would discard the Meeting Coordinator and Committee Writer paths documented just above. Keep the target guard aligned with the spec's resolved-object/action-specific-permission contract.
Target writerGuard = resolved target context + canWrite()

docs/architecture/frontend/permission-persona-navigation-model-preread.md:89

  • The current-state inventory is inaccurate: documents.routes.ts:7-12 has only authGuard, and the document toolbar is gated by project scope rather than either ED fast path. Conversely, Group/Committee create and edit routes do use writerGuard. Correcting the route list matters because this table claims to be code-verified.
| ED fast path in `writerGuard`/`newsletter-access.guard.ts` | Needs verification (P0) | Skips the permission check for ED persona on meetings/votes/surveys/mailing lists/newsletters/document routes. Does not grant the write itself — API enforcement is separate, and `executive_director` does not inherit project `writer`. Very likely a guard bug (a misleading UI-only affordance a downstream write would reject), not a permission the model grants. Whether it's a confusing dead-end or an actual gap depends on independent API enforcement — see P0. |

docs/architecture/frontend/permission-persona-navigation-model-preread.md:480

  • The stated baseline is wrong: Health Metrics currently checks the ED persona, not marketing_auditor alone, and the earlier target text says it does not migrate to a shared permission. Make the first option include that guard migration and compare the second option with the actual ED eligibility.
   imply. Two ways to close that gap: either `writer` starts feeding
   `marketing_auditor` in the model, or the Health Metrics guard accepts
   `writer` OR `marketing_auditor` instead of `marketing_auditor` alone.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:452

  • The PR summary says this section proposes removing the ED relation and adding LF Staff Team inheritance for B2B Organization auditor access, but the added spec records the opposite outcomes: ED stays, and org-wide access uses distinct per-object global relations rather than project-style team/root inheritance. Update the PR description so reviewers see the decisions actually being proposed.
1. **`executive_director` stays as a grant in the model — resolved.** The
   app checks `auditor`, `writer`, `marketing_auditor`, and
   `campaign_manager` directly and never branches on the
   `executive_director` grant itself (see Writer Actions above). Per Eric
   Searcy's review, it stays rather than being removed or replaced — it

docs/architecture/frontend/permission-persona-decision-matrix.md:118

  • The matrix says persona never decides whether a user can read page data, but the preread's target state keeps Health Metrics behind the pure persona-based executiveDirectorGuard. Resolve or explicitly mark that exception in both specs; otherwise this companion matrix cannot be used as the target decision contract.
Persona changes what the experience looks like (layout, emphasis, copy,
ordering). It never decides whether the user can enter the context, read its
data, or write to it — those outcomes are stated below purely in permission
terms (auditor permission, writer permission, named permission).

Replace the parked Health Metrics open question with the decision
from Slack (Eric + Manish, Jul 31-Aug 4):

- Guards check a single permission; inheritance belongs in the model
  (Eric's rule) - no multi-permission ORs in any guard.
- Health Metrics guards on auditor: anyone who can audit the context
  sees its health (auditor alone never implies write).
- Marketing Impact guards on marketing_auditor; the model adds
  writer -> marketing_auditor so context writers see it without the
  guard knowing about writer (model change, platform team).
- Campaigns stays guarded on campaign_manager (write authority is not
  implied by writer) - unchanged, just no longer framed as open.

executiveDirectorGuard on these three routes is replaced by three
single-permission guards, not a persona check or a multi-permission
OR. Updated Writer Actions, Model Asks #3, and the Contract Summary;
grepped both docs for open-question language - nothing left.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings August 4, 2026 18:31

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 2 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (2)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:212

  • This collapses writerGuard to canWrite(), but the current guard also admits project.meetingCoordinator and committee.writer, and this spec's own general rule requires the action-specific permission. Following this target would regress committee writers and meeting coordinators. Describe the current guard as the ED fast path plus its action-specific checks, and the target as resolved target object plus action-specific permission. The stale blanket wording also remains in P3/Contract Summary and in the companion matrix's line 58, which requires a Foundation/Project target while naming committee.writer.
Current writerGuard = Executive Director fast path or canWrite()
Target writerGuard = resolved target context + canWrite()

docs/architecture/frontend/permission-persona-navigation-model-preread.md:27

  • This blanket prohibition contradicts the next paragraph and the companion matrix, which require persona-based presentation branching for layout, emphasis, copy, and ordering. The same overstatement appears in permission-model.svg at lines 7 and 59. Limit the prohibition to access and action-authority decisions so implementers do not remove the presentation behavior this spec explicitly requires.

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

App code never branches on personas. Every gate is a permission check — can
user U do action A on object O. Guards define which permission each action
needs.

Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
Comment thread docs/architecture/frontend/permission-persona-navigation-model-preread.md Outdated
…ecision

Per Eric Searcy's second-round review: guards must check exactly one
permission on the action's own resolved object; container-permission
inheritance belongs in the model, not re-derived as an OR across
project/committee/coordinator checks in the UI.

- Me Lens target/permission paragraph (preread): reworked the PR #1193
  create-flow explanation to distinguish create-time target resolution
  (one permission per chosen parent) from edit/manage of an existing
  item (one permission on the item's own object - a meeting checks
  `organizer`, which the model already inherits from Project Meeting
  Coordinator, Committee Writer, and Project Writer).
- Examples bullets (preread): "Pending agenda action" -> "Pending action
  item," permission validated per action-item type (agenda itself has no
  writeable action); "Meeting card" and "Vote or survey" now name the
  single permission checked; "Akrites package" flagged explicitly as an
  exception to the OpenFGA model (no package/stewardship relation
  exists).
- ED-shortcut paragraph (preread): removed the "unless the user also has
  writer permission" carve-out - there is no authorization shortcut,
  full stop.
- Decision matrix: reworded the meeting write-candidate/existing-item
  permission language to `organizer`; split the Meetings Create/manage
  bullet into Create (single permission on the chosen target) and
  Manage-existing (single `organizer` check on the meeting); reworded
  Votes and Surveys Create/manage bullets to drop the literal "OR"
  guard phrasing in favor of "permission on the chosen target."

Health Metrics guard decision (Eric's threads asking whether Health
Metrics needs an additional staff-only AND-guard) was already recorded
in the prior commit (9cdce56): guards on `auditor` alone, no AND-staff
guard - anyone who can audit the context sees its health.

Diagram: synced permission-model.svg from the design source - card 4
now reads "the action's own permission on its object" with the
meeting -> organizer example. Same pre-existing lexicon drift as
flagged in the prior round remains baked into the SVG's own labels
("auditor / explicit role" contains "role"; "executive_director
relation" and "evaluated relationships" contain "relation") - not
hand-edited per established precedent (commit af714dd); flagging
here again since the retired terms are still present.

Consistency grep for guard-level "OR" language across both docs found
none remaining outside this explanatory paragraph itself.

LFXV2-2913

Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org>
Copilot AI review requested due to automatic review settings August 4, 2026 21:52
@manishdixitlfx

Copy link
Copy Markdown
Contributor Author

Round 2 review feedback addressed

Commit: 8ba162f

Changes made (per @emsearcy)

  • Me Lens target/permission paragraph (preread): split create-time target resolution (unchanged — one permission per chosen parent) from edit/manage of an existing item, which now checks the single permission the model resolved onto that item's own object — a meeting checks organizer, inherited from Project Meeting Coordinator, Committee Writer, and Project Writer, not a re-derived OR in the UI.
  • Examples bullets: "Pending agenda action" → "Pending action item" (permission validated per action-item type); "Meeting card" and "Vote or survey" now name the single permission checked; "Akrites package" flagged as an explicit exception to the OpenFGA model.
  • ED-shortcut paragraph: removed the "unless the user also has writer permission" carve-out — no shortcut, full stop.
  • Decision matrix: reworded the write-candidate/existing-item permission language to organizer; split the Meetings Create/manage bullet into Create (single permission on the chosen target) and Manage-existing (single organizer check); reworded Votes/Surveys Create/manage bullets to drop the literal "OR" phrasing.
  • Health Metrics staff-AND-guard question: decided auditor-only (no staff AND-guard) — recorded in 9cdce56 (prior commit) and referenced again here; anyone who can audit a context sees its Health Metrics, auditor alone never implies write.
  • Diagram: synced permission-model.svg — card 4 now reads "the action's own permission on its object" with the meeting → organizer example.

Note on the diagram

Same pre-existing lexicon drift flagged in the prior round is still baked into the SVG's own labels ("auditor / explicit role" contains "role"; "executive_director relation" / "evaluated relationships" contain "relation"). Not hand-edited per established precedent (af714dd) — flagging again since it's still there.

Threads resolved

8 of 8 unresolved threads addressed and resolved in this iteration.

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 2 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (7)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:126

  • This describes the shipped flow as already making one permission check, but current writerGuard separately tests project.writer, then project.meetingCoordinator, and then committee.writer when applicable (writer.guard.ts:80-100). The companion current-state matrix also records the API's project permission as meetings_creator. Distinguish the current multi-check UI guard from the target single meetings_creator check; otherwise the spec marks the migration as complete when it is not.
`committee_uid` is present, and accepts `project.meeting_coordinator` when
the target is a project and no meeting object exists yet — each create
checks exactly one permission on the chosen parent, never several checked
together.

docs/architecture/frontend/permission-persona-decision-matrix.md:212

  • This target rule still lists the underlying writer/meeting_coordinator sources and then says only one permission is checked. The API contract already exposes the resolved project action as meetings_creator (persona-content-matrix.md:193); the target should check that on a project/foundation target, or writer on a committee target. Keeping the source relations here would preserve the multi-permission OR that the spec explicitly rejects.
- **Create:** Requires the create-granting permission on the chosen target — `writer` or `meeting_coordinator` when the target is a Project, `writer` when the target is a Foundation, `committee.writer` when the target is a committee/group. One permission checked on the chosen target, not several checked together.

docs/architecture/frontend/permission-persona-decision-matrix.md:248

  • As with Votes, this collapses parent-scoped creation and item-scoped management even though the document's core rule says existing actions check the item's own resolved permission. This would direct implementers to keep checking the project/committee when editing or closing an existing survey instead of checking the survey relation enforced by its API.
- **Create/manage:** Requires the create-granting permission on the chosen target — `writer` when the target is Foundation/Project, `committee.writer` when the target is a committee/group.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:27

  • The current wording still prohibits all persona branching, but this spec immediately defines personas as the input for presentation branching, and the app currently does exactly that for sidebar composition (sidebar-nav.service.ts:307). Narrow this principle to authorization/access decisions so implementers do not read the target model as forbidding the presentation behavior the document requires.

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

App code never branches on personas. Every gate is a permission check — can
user U do action A on object O. Guards define which permission each action
needs.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:89

  • This current-state inventory does not match the route table. writerGuard also protects committee/group create and edit routes (committees.routes.ts:16-30), while document routes use only authGuard (documents.routes.ts:7-13) and the document toolbar is enabled solely by project scope (documents-dashboard.component.ts:105-110). Including documents under this ED fast path while omitting committees hides the actual document authorization gap and gives the P0 audit the wrong scope.
| ED fast path in `writerGuard`/`newsletter-access.guard.ts` | Needs verification (P0) | Skips the permission check for ED persona on meetings/votes/surveys/mailing lists/newsletters/document routes. Does not grant the write itself — API enforcement is separate, and `executive_director` does not inherit project `writer`. Very likely a guard bug (a misleading UI-only affordance a downstream write would reject), not a permission the model grants. Whether it's a confusing dead-end or an actual gap depends on independent API enforcement — see P0. |

docs/architecture/frontend/permission-persona-decision-matrix.md:100

  • The model does not make the current guard's two relation checks into “one resolved permission”: the code explicitly checks writer and then meeting_coordinator (writer.guard.ts:80-100). The existing current-state matrix names the API relation as meetings_creator (persona-content-matrix.md:193). Name that action permission as the target and state that writerGuard still needs migration, rather than claiming the current guard already performs the target check.

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

- **Required permission:** User must choose a target object (project, foundation, committee, or group), then the action-specific permission on that object must pass. For most creates the target is Foundation/Project and the permission is `writer`. For Create Meeting, Create Survey, and Create Vote, the target can also be a committee/group, authorized by `committee.writer`. Create Meeting's project-target check is a single permission — the model grants project-level meeting-creation authority to both `project.writer` and `project.meeting_coordinator`, so the guard checks the one resolved permission, never two separate calls in the UI.

docs/architecture/frontend/permission-persona-decision-matrix.md:241

  • Combining create and manage here contradicts this spec's existing-item rule at lines 92–95 and the preread's rule that an existing item's own permission is authoritative. A committee writer may authorize creation through the parent, but management of an existing vote should check the permission resolved on that vote, not re-derive the parent grant.

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

- **Create/manage:** Requires the create-granting permission on the chosen target — `writer` when the target is Foundation/Project, `committee.writer` when the target is a committee/group.

Copilot AI review requested due to automatic review settings August 5, 2026 00:19

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 2 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (4)

docs/architecture/frontend/permission-persona-navigation-model-preread.md:9

  • The permission-only rule includes Organization, but the target never accounts for current Board Member Org access. AccountContextService.hasOrgSelectorAccess accepts persona-seeded accounts (account-context.service.ts:68-76), and those accounts come from board_member detections (persona-detection.service.ts:418-440); Model Ask #2 only creates Org permissions for LF staff. Applying this rule as written would therefore remove Board Members from their organizations. Either scope this statement to Foundation/Project or define how Board Member organizations receive a named Org permission and add the corresponding Org cases to the matrix.
- **Where can I go?** Outside of Me, `auditor` permission (direct or inherited via the model) is what's needed to browse into a Foundation/Project/Organization context. It's the only permission that matters for context entry: any higher permission (writer, owner) includes `auditor` by inheritance.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:89

  • The current-state route inventory is inaccurate. Document routes use only authGuard (documents.routes.ts:7-12), while the ED fast path actually affects writerGuard routes for meetings, surveys, votes, mailing lists, and committees, plus newsletter manager routes. Including documents while omitting committees makes the P0 audit scope incomplete; update this row to match the mounted guards.
| ED fast path in `writerGuard`/`newsletter-access.guard.ts` | Needs verification (P0) | Skips the permission check for ED persona on meetings/votes/surveys/mailing lists/newsletters/document routes. Does not grant the write itself — API enforcement is separate, and `executive_director` does not inherit project `writer`. Very likely a guard bug (a misleading UI-only affordance a downstream write would reject), not a permission the model grants. Whether it's a confusing dead-end or an actual gap depends on independent API enforcement — see P0. |

docs/architecture/frontend/permission-persona-decision-matrix.md:100

  • This says the UI performs one resolved permission check, but writerGuard currently checks project.writer and then separately requests meeting_coordinator for non-writers (writer.guard.ts:80-95), while the code-verified current-state matrix identifies the API's composed Project permission as meetings_creator (persona-content-matrix.md:188-193). If the target is one action relation, name meetings_creator and describe the current UI OR as migration work; otherwise remove the one-check claim. The same inconsistency appears at line 212 and in the preread at lines 122-126.
- **Required permission:** User must choose a target object (project, foundation, committee, or group), then the action-specific permission on that object must pass. For most creates the target is Foundation/Project and the permission is `writer`. For Create Meeting, Create Survey, and Create Vote, the target can also be a committee/group, authorized by `committee.writer`. Create Meeting's project-target check is a single permission — the model grants project-level meeting-creation authority to both `project.writer` and `project.meeting_coordinator`, so the guard checks the one resolved permission, never two separate calls in the UI.

docs/architecture/frontend/permission-persona-navigation-model-preread.md:27

  • The current wording still prohibits every persona branch, contradicting the next paragraph and the companion matrix's rule that persona drives presentation. It also rules out the intended dashboard/sidebar composition visible in dashboard.component.ts:54-57 and sidebar-nav.service.ts:313. Limit the prohibition to access and action gating; presentation code must remain allowed to branch on persona. The diagram repeats the same absolute wording on line 7.
App code never branches on personas. Every gate is a permission check — can
user U do action A on object O. Guards define which permission each action
needs.

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