can you help triage <https://linear.app/pageport/issue/HELP-608/private-meetings-visible-within-slant|HELP-608>
Kind
Dispatch
Status
Awaiting Feedback
Created
Apr 15, 2026 23:15
Duration
3m 30s
Ports
:3970 / :5972
Description
can you help triage <https://linear.app/pageport/issue/HELP-608/private-meetings-visible-within-slant|HELP-608>
Source
slack
Title
can you help triage <https://linear.app/pageport/issue/HELP-608/private-meeti...
Resolved play
triage
Agent
Apr 15, 23:19
Confirmed the bug. Here's my triage assessment and proposed comment.
---
**Internal comment draft (for Linear on HELP-608):**
**Problem:**
Private calendar events (Google and Outlook) display full details (title, time, participants, location) to other users in Slant's calendar. The lock icon correctly shows, but the details aren't actually hidden. Confirmed for all Sonoma users.
**Root cause:**
`CalendarEvent#can_view_private_details?` in `backend/app/models/calendar_event.rb:199-205` has a logic flaw. When `hide_private_events` is `false` (the default on `EmailIntegration`), the method falls through to return `true` unconditionally:
```ruby
def can_view_private_details?(viewer)
return true unless is_private
return false unless viewer.present?
return false if email_integration&.hide_private_events? && viewer.id != calendar&.user_id
true # ← falls through here when hide_private_events is false (the default)
end
```
The serializer in `backend/app/views/api/calendar_events/_calendar_event.json.jbuilder` correctly redacts title/location/description/participants when `can_view_private_details?` returns `false`, but it receives `true` because the permission check only kicks in when the setting is enabled. The frontend in `frontend/components/calendar/event-block.tsx:27-28` and `event-detail-popover.tsx:120-121` also correctly hide details when the backend says to — the issue is purely backend logic.
The same flaw exists in the companion method `private_event_redacted_for?` at line 207-209, which gates on `hide_private_events?` as well.
**Immediate workaround:**
Enable `hide_private_events` on the affected users' EmailIntegration records in Sonoma's book. This will cause the method to correctly return `false` for non-owners.
**Suggested fix:**
The default behavior of `can_view_private_details?` should deny non-owners when `is_private` is true, regardless of the `hide_private_events` setting. The simplest fix is changing line 204 from `true` to `viewer.id == calendar&.user_id`. The `hide_private_events` setting could then be repurposed to control whether private events create Meeting records and trigger prep emails (which is what SLNT-1345 originally asked for).
**Related tickets:**
- SLNT-1361: Original feature implementation (Done, assigned radley)
- SLNT-1345: Original customer request that led to the feature (Done)
**Severity:** High — privacy leak. Lock icon creates false sense of security.
**Affected:** Any customer with shared calendars who hasn't explicitly enabled `hide_private_events` (which defaults to off).
---
HELP-608 is a real privacy bug — Sonoma users can see private meeting details in Slant because the "hide private events" setting defaults to off. The lock icon shows correctly but doesn't actually hide anything unless that setting is manually enabled per calendar integration. This was introduced in SLNT-1361's implementation. Proposing a comment with the root cause, a workaround, and fix direction. Say 'ship it' to post.
Outcome: PROPOSE_COMMENT
You
Apr 15, 23:25
Make the comment
Agent
Apr 15, 23:26
Commented on HELP-608 with the root cause, workaround (enable `hide_private_events` on Sonoma's calendar integrations), and a suggested one-line fix for engineering. The immediate next step is flipping that setting for Sonoma to unblock them while the code fix gets scheduled.
Outcome: ANSWER
You
Apr 15, 23:36
I'm wondering if this just a raw data matching thing the behavior right now is right you should have to turn that setting on. Can you explain look at some out look meetings and see if our matching logic for what is private or not is wrong? Maybe we aren't catching outlook private meetings?
Agent
Apr 15, 23:47
OK, here's what I've found. Your instinct is right — there's strong evidence of a matching issue.
**The data tells the story:**
| User | Provider | hide_private | Private events flagged |
|------|----------|-------------|----------------------|
| shelby | microsoft | true | 63 |
| daren | microsoft | true | 20 |
| chris | microsoft | false | 8 |
| frankie | microsoft | false | 0 |
| russell | microsoft | false | 0 |
| kim | microsoft | false | 0 |
| kelly | exchange | false | 0 |
Frankie has 12 events with titles like "Out of Office" and "Block: Personal" — but NONE are flagged `is_private=true`. These events were backfilled on 2026-04-14 (after the feature shipped), so `sync_from_provider` WAS called. If Nylas returned privacy data, they'd be flagged.
**The detection logic:**
```ruby
def private_event?(event_data)
event_data[:is_private] == true ||
event_data[:private] == true ||
['private', 'confidential'].include?(event_data[:visibility].to_s.downcase)
end
```
This checks `is_private`, `private`, and `visibility` — but Microsoft/Outlook natively uses `sensitivity` (with values `normal`, `personal`, `private`, `confidential`). There is zero handling of `sensitivity` anywhere in the codebase. If Nylas passes through Microsoft's `sensitivity` field without normalizing it to `visibility`, we'd miss every Outlook private event.
**What I can't confirm from this sandbox:** Whether Nylas actually normalizes `sensitivity` → `visibility` for Microsoft events. The Nylas API is unreachable from here. But the data pattern is suspicious — the users whose events ARE flagged private might have had events re-synced under different conditions, or their specific Nylas grant configuration might differ.
**The two potential issues are:**
1. **Matching gap**: `private_event?` doesn't check `sensitivity`, so Outlook private events may not get `is_private=true` at all — meaning no lock icon, no redaction, nothing
2. **Visibility logic** (original finding): Even when events ARE flagged private, `can_view_private_details?` returns `true` for non-owners when `hide_private_events` is off (the default)
**To verify the matching theory**, an engineer could add temporary logging to `private_event?` to dump all keys from `event_data` for a Microsoft event sync, or check the Nylas API docs for what fields they return for Microsoft events. Adding `event_data[:sensitivity]&.downcase&.in?(['private', 'confidential'])` to `private_event?` would be a safe defensive fix either way.
Want me to update the Linear comment on HELP-608 with these revised findings?