feat(api): expose work item subscribers on the API-key surface - #3
Merged
Conversation
Upstream exposes issue subscribers only on the session-authenticated app API, where `subscribe` can act on `request.user` and nobody else. That is unusable for an integration: an API token authenticates as its own bot user, so there is no way for an external system to say "notify THIS person about THIS work item". We need exactly that. Bug reports filed from the Psyclo apps land in Intake as work items owned by the token user, and a reporter who agreed to be contacted has to receive Plane's own comment notification email for the thread to be two-way. Everything else that loop needs already exists on /api/v1/ -- workspace invitations, project members, work item comments -- this was the one gap. Adds GET/POST/DELETE on workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/subscribers/ POST takes either `subscriber` (a user id) or `email`, because a calling system generally knows the person by address and would otherwise have to page the whole member list to translate it. Reads are ProjectEntityPermission; changing someone else's notifications is not ordinary entity access, so writes require ProjectAdminPermission. The project-membership check in POST is deliberate rather than merely documented: `bgtasks/notification_task.py` filters recipients to active ProjectMember rows before intersecting with IssueSubscriber, so accepting a non-member would create a row that looks correct in the database and silently never delivers anything. Better to reject it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SsBurBNYE4Wxpx2k6atqcj
|
React Doctor found no new issues. 🎉 Reviewed by React Doctor for commit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Upstream exposes issue subscribers only on the session-authenticated app API (
/api/workspaces/.../issues/<id>/issue-subscribers/), wheresubscribecan act onrequest.userand nobody else. That is unusable for an integration: an API token authenticates as its own bot user, so there is no way for an external system to say "notify this person about this work item".We need exactly that. Bug reports filed from the Psyclo apps land in Intake as work items owned by the token user, and a reporter who agreed to be contacted has to receive Plane's own comment notification email for the thread to be two-way.
Everything else that loop needs already exists on
/api/v1/— workspace invitations, project members, work item comments. This was the one gap.What
GET/POST/DELETEon:POSTaccepts eithersubscriber(a user id) oremail, because a calling system generally knows the person by address and would otherwise have to page the whole member list to translate it.Design notes
Permissions are split by method. Reading who is subscribed is ordinary
ProjectEntityPermission. Changing someone else's notification settings is not ordinary entity access, so writes requireProjectAdminPermission.The project-membership check in
POSTis enforced, not merely documented.bgtasks/notification_task.pyfilters recipients to activeProjectMemberrows before intersecting withIssueSubscriber, so accepting a non-member would create a row that looks correct in the database and silently never delivers anything. Rejecting it with a clear 400 is better than a subscription that quietly does nothing.get_or_create, so a repeated call is a 200 rather than a duplicate or an error — the calling integration is written to be re-runnable.Files
plane/api/views/subscriber.py— newplane/api/urls/subscriber.py— newplane/api/urls/__init__.py,plane/api/views/__init__.py— registration onlyFollows the
ProjectMemberListCreateAPIEndpointshape:BaseAPIView, slug-scoped,drf_spectacularannotations for the generated OpenAPI schema.Verification
Syntax checked and every import verified to resolve (
IssueSubscriber,ProjectMember, both permission classes, all five openapi symbols).Not verified: Django has not been started against this, so the endpoint has never actually executed. Worth a smoke test on staging before it is relied on.
Consumer
Ushadow-io/psyclo#398
🤖 Generated with Claude Code
https://claude.ai/code/session_01SsBurBNYE4Wxpx2k6atqcj