feat(people): access tab on member details, per connected integration#3349
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
4 issues found across 13 files
Confidence score: 3/5
- In
apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeAccess.tsx,MATCH_BADGE[source.matchType]has no fallback for unexpected API values, so a new/unknownmatchTypecan produceundefinedand break rendering in the employee access view — add a defensive default badge (or guard) and a test for unknown match types before merging. - In
apps/api/src/integration-platform/services/evidence-extraction.service.ts(evidenceMentionsEmail/buildAiExcerpt), rawincludes(email)matching can misidentify mentions when emails overlap as substrings, leading to incorrect evidence excerpts and attribution — switch to boundary-aware/normalized email matching and cover overlapping-address cases with tests. - In
apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeAccess.tsx, usingkey={i}for access entries risks React reusing the wrong row after reorder/update, which can show stale or mismatched access details — use a stable unique key from the entry data before merging; theparts.join('\n')loop cost inapps/api/src/integration-platform/services/evidence-extraction.service.tslooks lower-risk and can be a follow-up optimization.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
New tab on the member page aggregating the latest Employee Access check results from every connected integration bound to the Employee Access evidence task (CheckResultsService consumer #2). Rows show logo, name, access summary, and an honest match state (found / no match for this member / check not run); expanding reveals curated fields plus the raw record. Extractor tolerates both check shapes: per-user rows and org-level rosters embedded in evidence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nce extraction Shared EvidenceExtractionService: deterministic shape matching, then an email pre-gate (absent email = confident not-found, no AI call), then a claude-haiku-4-5 structured-output fallback for unknown evidence shapes. Access tab consumes it; AI-extracted entries are labeled in the UI and unreadable shapes surface as 'Needs manual review' instead of a blank. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ctly — drop AI extraction Person-scoped checks now emit one row per person (resourceType 'user', resourceId = lowercased email), so matching a member's access is a plain filter. Removes EvidenceExtractionService (deterministic ladder + AI fallback), its spec, module wiring, and the AI badge / unparsed state in the UI. New 'no-person-data' state distinguishes sources whose vendor API has no roster. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013WLGUUjG6uLd6xvNhUpge1
af7d03c to
4701387
Compare
Fallback badge for unknown matchType values (the union is compile-time only; deserialized JSON can carry states this build doesn't know), and content-derived entry keys so uncontrolled <details> elements follow their entry through reorders instead of the array index. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013WLGUUjG6uLd6xvNhUpge1
|
Triage of the 4 findings:
|
|
@cubic-dev-ai review it |
@tofikwest I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
1 issue found across 8 files
Confidence score: 4/5
- In
apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeAccess.tsx, the row key built from${entry.summary}::${JSON.stringify(entry.fields)}can collide for distinct results that differ only in nestedrawevidence, which may cause React to reuse the wrong row and show stale/mismatched access details—switch to a truly unique key (for example a stable result ID or hash that includes nested evidence) before merging.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
|
Fixed with the cleaner variant of your first suggestion: rather than growing the composite key (serializing |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013WLGUUjG6uLd6xvNhUpge1
There was a problem hiding this comment.
1 issue found across 4 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
Expose the IntegrationCheckResult id through the CheckResultRow envelope and use it as the entry id — unique and stable by construction, no positional derivation. Also order a run's result rows deterministically in the repository (Postgres guarantees no order without one). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013WLGUUjG6uLd6xvNhUpge1
|
Fixed properly this time — took your "expose a true database row id" option: |
|
@cubic-dev-ai review it |
@tofikwest I have started the AI code review. It will take a few minutes to complete. |
# [3.97.0](v3.96.1...v3.97.0) (2026-07-06) ### Bug Fixes * **people:** polish the redesigned People tab (requirement columns, filters, per-employee 2FA) ([#3347](#3347)) ([75758ec](75758ec)) ### Features * **integrations:** emit per-user rows from the Google Workspace employee-access check ([#3352](#3352)) ([0b54252](0b54252)) * **people:** access tab on member details, per connected integration ([#3349](#3349)) ([83f188c](83f188c)), closes [#2](https://github.com/trycompai/comp/issues/2)
|
🎉 This PR is included in version 3.97.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
What
Adds an Access section to the member detail page: for every connected integration whose check is bound to the Employee Access evidence task, shows what this person can access — role, account status, and the raw evidence record — matched deterministically by email.
GET /v1/people/:id/access(PeopleAccessService) — consumer of the universalCheckResultsService.EmployeeAccesscard on the member page with per-integration rows, expandable to field lists + raw record.How matching works
Person-scoped checks emit one result row per person (
resourceType: 'user',resourceId= lowercased email) — the standard shape all employee-access checks now follow. A member's access is exactly the rows whose resourceId equals their email. No evidence parsing, no heuristics.Tests
people-access.service.spec— email matching, entry building, all four source states, unconnected-source skip, no-email member.EmployeeAccess.test.tsx— list rendering, state badges, expansion with fields + raw record, empty state.🤖 Generated with Claude Code
https://claude.ai/code/session_013WLGUUjG6uLd6xvNhUpge1