## PR Summary: Restrict shared report links to workspace members
**Title:** Restrict shared report links to workspace members
**Risk Area:** Data access / Authorization
---
### Key Changes
1. **Added workspace membership checks to report link reads**
- Previously, anyone with a valid report link token could access the underlying report data.
- Now, `GET /reports/:id` and related endpoints verify that the user is a member of the workspace that owns the report before returning data via a shared link.
2. **Moved link token parsing into a shared helper**
- Token extraction and validation logic extracted from individual controllers into `/lib/shared-link-token.ts` (or similar).
- Ensures consistent token parsing, expiration checks, and error types across endpoints.
3. **Updated error handling**
- New `403 Forbidden` response for non-members attempting to access via shared link (previously would succeed or return 404).
- Improved error messages to distinguish between "invalid token" and "valid token, but not a workspace member."
---
### Security Concerns
1. **Backward compatibility for existing links**
- Existing shared report links will now require workspace membership. If users previously shared links with non-members (clients, contractors), those recipients will lose access. Ensure migration plan or escalation process is documented.
2. **Token reuse across workspaces**
- The shared helper must validate that the token belongs to the *correct* workspace - a token from Workspace A should not grant access to a report in Workspace B. Verify the workspace ID in the token matches the report's workspace.
3. **Race condition on membership revocation**
- If a user is removed from a workspace after a shared link is resolved, but while the report data is being streamed, does the middleware re-check membership? Ideally, membership should be checked at the start of the request, not cached.
4. **Anonymous or logged-out access**
- Are shared links still usable without authentication? The PR implies membership checks require an authenticated user. If anonymous links were previously supported, this change breaks that. Confirm intent and communicate to stakeholders.
5. **Rate limiting / brute force**
- Token parsing helper should not leak information via timing side channels. Ensure constant-time comparison for token signatures.
---
### Reviewer Questions
1. **What happens when the report link token is valid but the user is not authenticated?**
- Is there a fallback to a 401 (Unauthorized) with a hint to log in, or does it simply throw a 403?
2. **Are there any admin or owner bypasses?**
- Should workspace admins be able to access any shared link in their workspace regardless of their own membership status?
3. **How is workspace membership determined?**
- Is it from an in-memory database lookup, a cached role, or a call to an external directory service? What is the latency/availability impact?
4. **Are audit logs updated?**
- Should access denials due to membership checks be logged with the token hash, user ID, and workspace ID for incident response?
5. **What is the TTL for the newly introduced "workspace membership" check?**
- If the membership service is cached (e.g., 5-minute TTL), a revoked user could still access the link for up to 5 minutes. Is that acceptable for your threat model?
6. **Are there any test cases covering edge cases?**
- Token expired, token tampered, token from different workspace, user removed mid-session, anonymous request.