Skip to content

feat(ux): show permission-aware empty state when CC fetch returns 403 #152

Description

@MrCoder

Summary

Once #148 surfaces direct-fetch HTTP status on customcontent_orphan_observed, the viewer can also use that information at render time to distinguish "user lacks permission to the underlying CC's source page" from generic "load failed". This unlocks a more actionable empty state — pointing the user toward requesting access rather than just offering a retry.

Prerequisite

Depends on #148 — currently loadCustomContentWithOrphanRecovery returns directFetchStatus: 'other_error' for both 403 and 5xx and thrown failures. The viewer cannot tell which it was without that issue's work.

Also stacks on #151 — the generic "couldn't load" empty state is the universal fallback; this issue adds a smarter variant on top.

Why this matters

A real failure mode at scale: a Confluence page contains a macro whose customContent is owned by a different page that the viewing user does not have read permission for (common after page copies, space-level permission changes, or restricted-page hierarchies). Today these users see a silent blank macro and have no way to discover that the fix is "ask for access to the source page" rather than "report a bug".

Proposed UX

When the viewer detects the load failed with HTTP 403 (via the new direct_fetch_status / direct_fetch_http_status plumbed by #148):

┌─────────────────────────────────────────────┐
│  🔒 You may not have permission to view      │
│      this diagram's source content           │
│                                              │
│  The diagram is stored on a Confluence       │
│  page you can't access. Ask the page owner   │
│  for read access, or contact your admin.     │
│                                              │
│  [I have permission, retry]                  │
└─────────────────────────────────────────────┘
  • Lock icon and the phrase "permission" make the cause unambiguous
  • Retry button covers the case where the user thinks they should have access (e.g., admin granted but Confluence still caching)
  • No customContentId shown — the user can't use it for anything; admin can find it via the Mixpanel orphan event if needed

Decision: only render this for HTTP 403, not other auth-flavored failures

False positives on permission language (telling a user "you don't have permission" when they actually do) erode trust more than false negatives (saying "couldn't load" when it was really permission). Be conservative on what gets the lock-icon variant.

Out of scope

  • Server-side enrichment of the lock-state message with the actual source page title or URL (would require a separate read against the V2 API to look up container metadata, which by definition the user doesn't have access to). Keep the message generic.
  • Editor-mode equivalent — editors generally trigger their own permission errors during save, separate flow
  • Bulk admin tooling to identify which users hit which restricted pages — analytics task, not UX

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions