Skip to content

fix(adcp/v3): keep an empty approved_sellers list on the wire - #593

Closed
garvitkaushik-123 wants to merge 1 commit into
mainfrom
claude/serene-keller-t99bes
Closed

garvitkaushik-123 wants to merge 1 commit into
mainfrom
claude/serene-keller-t99bes

Conversation

@garvitkaushik-123

@garvitkaushik-123 garvitkaushik-123 commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Plan.ApprovedSellers was tagged omitempty, so []string{} was dropped on encode exactly like nil:

Buyer sets Before After
nil (any seller) key omitted null
[]string{} (no seller approved) key omitted []
[]string{"https://s.example"} ["https://s.example"] unchanged

The schema (sync-plans-request.json) defines null as "any seller" and says nothing about an omitted key. A Go buyer sending a plan that approves no sellers could therefore lose that meaning and look unrestricted to the governance agent. Decoding was already correct; only encoding was lossy.

Change

  • adcp/v3/governance_types.go: drop omitempty on approved_sellers. The Go type is unchanged, so no caller code breaks.
  • adcp/v3/plan_validate_test.go: TestPlan_ApprovedSellers_EmptyIsNotNull covers nil, [] and a listed seller on encode, and that nil versus empty survives a round trip. It fails on main (the nil and [] cases) and passes with the fix.

Plan is hand-written and in lint EXEMPT, so the generator-level Optional[T] work in #536 slice B can't reach this field. Slice B will name it as a hand edit; this PR fixes the empty-list case now.

Wire note for reviewers

Go buyers that never set ApprovedSellers now send "approved_sellers": null instead of omitting the key. That is the schema's own encoding of "any seller", so the meaning is unchanged, but the bytes differ. That matters for byte-level payload comparisons and for the JCS-based plan_hash of those plans. The field's schema is identical in 3.1.29, 3.2.2 and 3.3.0-beta.0 (["array","null"], no minItems), so no version-translation pathway is needed. I've kept this as fix:, not fix!:, because the exported type and the field's meaning are unchanged.

Validation

  • go test ./... in adcp/v3 (Go 1.26.2): pass
  • go vet ./...: pass
  • gofmt -l on the changed files: clean
  • python3 lint.py --strict against the pinned 3.2.2 bundle: pass
  • golangci-lint not run locally: the installed binary was built with Go 1.25 and refuses the 1.26.2 module, so CI covers it.

Plan.ApprovedSellers was tagged omitempty, so an empty list (no seller
approved) was dropped on encode exactly like nil. The schema defines
null as "any seller", so a plan meant to approve no sellers could reach
the governance agent with no seller restriction at all.

Drop omitempty on that one field: [] now encodes as [], and nil encodes
as null, which the schema already defines as "any seller". The Go type
is unchanged. The schema for this field is the same in 3.1, 3.2 and
3.3.0-beta.0.

Refs #536

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019tMquArX2EYTUkWaEcowyx

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve.

Checked: drops omitempty on Plan.ApprovedSellers (adcp/v3/governance_types.go:24) so []string{} ("no seller approved") no longer serializes identically to nil ("any seller") — a real fail-open fix on an approval boundary. Schema/type coherence holds: Plan is hand-written and present in both KNOWN_TYPES and EXEMPT, no schema change, no regen owed. Version pathway is correct — field schema is identical ["array","null"] across 3.1/3.2/3.3.0-beta.0, decode stays backward compatible, so fix: (not fix!:) is appropriate. Validate() never reads the field and no fixture does byte comparison, so no collateral breakage. Test covers nil/[]/listed plus round-trip. The nil→null wire/plan_hash shift is flagged by the author and is the schema's canonical encoding.

No critical/high/medium findings. Not gated (gated_paths: false), high_risk false, no author team gate. Rows 1–8 do not fire → row 9 approve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants