From 3c27ca34f7b6180ce5be8edfab600a089848bc8e Mon Sep 17 00:00:00 2001 From: pikann22 Date: Sun, 30 Aug 2026 16:39:39 +0000 Subject: [PATCH 1/2] fix: give locally-scoped JSONBody[T] body types unique names TinyGo's generic-function monomorphization keys plugin.JSONBody[T] instantiations by T's bare type name rather than its full declaration site. This package declared 8 locally-scoped `type bodyT struct{...}` types across integration.go, branches.go, and pull_requests.go -- same name, different fields per handler. TinyGo collapsed them into one shared field layout, so json.Unmarshal silently decoded most call sites against the wrong struct: fields came out zeroed with no error, indistinguishable from an empty request body. Renamed every JSONBody[T] body type to a name unique within the package (e.g. setTokenBody, linkRepositoryBody). Verified by building with the exact TinyGo version CI uses and driving the real binary through the actual host runtime -- previously-broken routes now correctly see their decoded fields. Fixes Paca-AI/paca#445. --- backend/branches.go | 8 ++++---- backend/integration.go | 8 ++++---- backend/pull_requests.go | 16 ++++++++-------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/backend/branches.go b/backend/branches.go index 949f561..070102c 100644 --- a/backend/branches.go +++ b/backend/branches.go @@ -28,12 +28,12 @@ func (p *githubPlugin) createBranch(req *plugin.Request, res *plugin.Response) { projectID := req.Caller.ProjectID taskID := req.PathParam("taskId") - type bodyT struct { + type createBranchBody struct { RepoID string `json:"repo_id"` BranchName string `json:"branch_name"` SourceBranch string `json:"source_branch"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[createBranchBody](req) if err != nil || b.RepoID == "" || b.BranchName == "" { apiError(res, 400, "BAD_REQUEST", "repo_id and branch_name are required") return @@ -113,11 +113,11 @@ func (p *githubPlugin) linkBranchToTask(req *plugin.Request, res *plugin.Respons projectID := req.Caller.ProjectID taskID := req.PathParam("taskId") - type bodyT struct { + type linkBranchToTaskBody struct { RepoID string `json:"repo_id"` BranchName string `json:"branch_name"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[linkBranchToTaskBody](req) if err != nil || b.RepoID == "" || b.BranchName == "" { apiError(res, 400, "BAD_REQUEST", "repo_id and branch_name are required") return diff --git a/backend/integration.go b/backend/integration.go index b6d0caa..1507d36 100644 --- a/backend/integration.go +++ b/backend/integration.go @@ -117,10 +117,10 @@ func (p *githubPlugin) getIntegration(req *plugin.Request, res *plugin.Response) func (p *githubPlugin) setToken(req *plugin.Request, res *plugin.Response) { projectID := req.Caller.ProjectID - type bodyT struct { + type setTokenBody struct { Token string `json:"token"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[setTokenBody](req) if err != nil || b.Token == "" { apiError(res, 400, "BAD_REQUEST", "token is required") return @@ -277,11 +277,11 @@ func (p *githubPlugin) listRepositories(req *plugin.Request, res *plugin.Respons func (p *githubPlugin) linkRepository(req *plugin.Request, res *plugin.Response) { projectID := req.Caller.ProjectID - type bodyT struct { + type linkRepositoryBody struct { Owner string `json:"owner"` RepoName string `json:"repo_name"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[linkRepositoryBody](req) if err != nil || b.Owner == "" || b.RepoName == "" { apiError(res, 400, "BAD_REQUEST", "owner and repo_name are required") return diff --git a/backend/pull_requests.go b/backend/pull_requests.go index cc51574..13be30c 100644 --- a/backend/pull_requests.go +++ b/backend/pull_requests.go @@ -76,11 +76,11 @@ func (p *githubPlugin) linkPRToTask(req *plugin.Request, res *plugin.Response) { projectID := req.Caller.ProjectID taskID := req.PathParam("taskId") - type bodyT struct { + type linkPRToTaskBody struct { RepoID string `json:"repo_id"` PRNumber int `json:"pr_number"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[linkPRToTaskBody](req) if err != nil || b.RepoID == "" || b.PRNumber == 0 { apiError(res, 400, "BAD_REQUEST", "repo_id and pr_number are required") return @@ -210,14 +210,14 @@ func (p *githubPlugin) createPullRequest(req *plugin.Request, res *plugin.Respon projectID := req.Caller.ProjectID taskID := req.PathParam("taskId") - type bodyT struct { + type createPullRequestBody struct { RepoID string `json:"repo_id"` Title string `json:"title"` HeadBranch string `json:"head_branch"` BaseBranch string `json:"base_branch"` Body string `json:"body"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[createPullRequestBody](req) if err != nil || b.RepoID == "" || b.Title == "" || b.HeadBranch == "" || b.BaseBranch == "" { apiError(res, 400, "BAD_REQUEST", "repo_id, title, head_branch, and base_branch are required") return @@ -563,10 +563,10 @@ func (p *githubPlugin) addPullRequestComment(req *plugin.Request, res *plugin.Re taskID := req.PathParam("taskId") prID := req.PathParam("prId") - type bodyT struct { + type addPullRequestCommentBody struct { Body string `json:"body"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[addPullRequestCommentBody](req) if err != nil || b.Body == "" { apiError(res, 400, "BAD_REQUEST", "body is required") return @@ -603,11 +603,11 @@ func (p *githubPlugin) createReview(req *plugin.Request, res *plugin.Response) { taskID := req.PathParam("taskId") prID := req.PathParam("prId") - type bodyT struct { + type createReviewBody struct { Event string `json:"event"` Body string `json:"body"` } - b, err := plugin.JSONBody[bodyT](req) + b, err := plugin.JSONBody[createReviewBody](req) if err != nil { apiError(res, 400, "BAD_REQUEST", "event is required") return From 40dcce738a5042a4e516662bdea4468b5aa1c9b4 Mon Sep 17 00:00:00 2001 From: pikann22 Date: Sun, 30 Aug 2026 16:49:59 +0000 Subject: [PATCH 2/2] chore: bump patch version in plugin.json --- plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.json b/plugin.json index 26c9f33..9b27990 100644 --- a/plugin.json +++ b/plugin.json @@ -2,7 +2,7 @@ "id": "com.paca.github", "displayName": "GitHub Integration", "description": "Integrates GitHub repositories, pull requests, and branches with Paca projects and tasks.", - "version": "0.3.4", + "version": "0.3.5", "minCoreVersion": "v0.13.3", "capabilities": ["repository"], "permissions": ["db.read", "db.write"],