plane: WorkItem state/labels/assignees are objects, not UUIDs#12
Merged
Conversation
Fixes the second real-deployment regression after v0.1.1's action-tense
fix. Real Plane CE v1.3.1 serializes nested objects for state, labels,
and assignees:
"state": {"id":"...","name":"Backlog","color":"#60646C","group":"backlog"},
"labels": [{"id":"...","name":"claude:DOCS-25","color":"#FAB287"}],
"assignees": [{"id":"...","display_name":"Alice"}]
v0.1.0 / v0.1.1 modelled them as `string` / `[]string` so every real
Plane webhook 400'd on payload decode after the action-tense fix
unblocked the verb-mismatch silent-drop.
Three changes:
1. internal/plane/types.go — added StateRef, LabelRef, AssigneeRef
types and pointed the WorkItem fields at them.
2. internal/sync/planeworkitem.go — extract UUIDs from
evt.WorkItem.Labels at the one read site that consumed them. The
resolver helper still takes []string; the LabelRef.Name field is
in-band on the wire now (so we could skip the UUID→name lookup),
but keeping the indirection means resolvePlaneLabelNames stays the
single source of truth for label naming.
3. internal/plane/testdata/work_item_{created,updated}.json updated
to the object form. Regression test
TestParse_RealPlaneWorkItemPayload_PFB24 pins decoding of a
captured-from-postgres real Plane payload so the next struct-shape
drift fails in CI instead of in production.
Docs in the same PR per the new convention:
- CHANGELOG.md added (Keep-a-Changelog format, entries for 0.1.0/0.1.1/0.1.2)
- README.md status header bumped to v0.1.2, image tags updated
- internal/plane/README.md Plane API notes section gains a #0 entry
documenting the nested-object wire shape
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Plane→forge e2e step builds a synthetic webhook payload with bare-string state, which the v0.1.2 type change rejects with the exact 400-malformed-payload error this PR fixes. The synthetic payload now matches the real Plane wire shape: StateRef object with id + name + color + group. Same UUID; just nested in the object the parser now expects. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Fixes the second real-deployment regression after v0.1.1's action-tense fix.
The bug
Real Plane CE v1.3.1 serializes nested objects for
state,labels, andassigneesin the work_item webhook payload:```json
"state": {"id":"...","name":"Backlog","color":"#60646C","group":"backlog"},
"labels": [{"id":"...","name":"claude:DOCS-25","color":"#FAB287"}],
"assignees": [{"id":"...","display_name":"Alice"}]
```
v0.1.0 / v0.1.1 modelled them as `string` / `[]string`, so every real Plane webhook 400'd on payload decode after the action-tense fix unblocked the verb-mismatch silent-drop:
```
WARN plane: malformed payload: work item: json: cannot unmarshal object into Go struct field WorkItem.state of type string
```
The fix
Docs in this PR
Following the new convention of shipping docs with the fix:
Test plan
When merged, tag v0.1.2 — this is a real-deployment-broken bug just like v0.1.1, same patch-release cadence.
🤖 Generated with Claude Code