Individual account approval resources (go) - #23
Open
lucasmiranda-stark wants to merge 1 commit into
Open
Conversation
lucasmiranda-stark
force-pushed
the
feature/account-approval
branch
from
May 29, 2026 23:49
bc555fe to
faf6984
Compare
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.
Context
The account-approval feature —
IndividualAccountRequestandIndividualAccountAttachment(each with a read-only.Log) — for the go infra SDK. Generated from contractsindividual-account-request.md(v3) andindividual-account-attachment.md(v3). Run-type: generate. Run artifacts:runs/20260528-182857-account-approval/go/.What changed
IndividualAccountRequest(create/get/query/page/update + read-only.Log) with a structuredAddresssub-resource (nested object, never flattened).IndividualAccountAttachment(create/get/query/page/cancel + read-only.Log); the constructor encodescontent+contentTypeinto adata:<contentType>;base64,…URL client-side;contentTypeis input-only.Test plan
runs/20260528-182857-account-approval/go/test-run-success.md)Risk & Rollback
Contract review (Phase 7)
Contract Review
Run metadata
Checklist
IndividualAccountRequest (M1–M12)
createaccepts a list ofIndividualAccountRequestand returns the same shape with server-assignedid,status,accountType,created,updatedpopulatedTestIndividualAccountRequestPost@ sdk-infra/go/tests/sdk/individual_account_request_test.go:51-67addressis a nested object (not a string, not flattened) with all required sub-fields; serialized as nested JSONTestIndividualAccountRequestPostAddressIsObject@ sdk-infra/go/tests/sdk/individual_account_request_test.go:71-100get(id)returns a singleIndividualAccountRequestby idTestIndividualAccountRequestInfoGet@ sdk-infra/go/tests/sdk/individual_account_request_test.go:159-201queryreturns a channel ofIndividualAccountRequest, acceptinglimit,after,before,status,tags,idsTestIndividualAccountRequestQuery@ sdk-infra/go/tests/sdk/individual_account_request_test.go:104-129pagereturns([]IndividualAccountRequest, cursor, err)and accepts the same params as query pluscursorTestIndividualAccountRequestPage@ sdk-infra/go/tests/sdk/individual_account_request_test.go:133-153update(id, ...)PATCHes the request accepting any subset ofname,taxId,address,income,status,tags; replaces address as a whole objectTestIndividualAccountRequestUpdate+TestIndividualAccountRequestUpdateAddressObject@ sdk-infra/go/tests/sdk/individual_account_request_test.go:206-297statusenum is exactlyapproved|created|denied|processing|updated(v1'ssuccess/failed/cancelednot used); status-enum test asserts membershipTestIndividualAccountRequestInfoGetassertsassert.Contains(t, []string{"approved","created","denied","processing","updated"}, getRequest.Status)@ sdk-infra/go/tests/sdk/individual_account_request_test.go:196IndividualAccountRequest.Logis read-only, exposed underindividualaccountrequest/log, providesget,query,page; Log'srequestfield is the parent type (not a string id)Request IndividualAccountRequest.IndividualAccountRequestat line 26)TestIndividualAccountRequestLogGetassertsgetLog.Request.Id@ sdk-infra/go/tests/sdk/individual_account_request_log_test.go:87-128Log.queryandLog.pageacceptlimit,after,before,types,accountRequestIdstypesandaccountRequestIdsper docstring lines 66-68, 106-108TestIndividualAccountRequestLogQueryusesparams["types"]+params["accountRequestIds"]@ sdk-infra/go/tests/sdk/individual_account_request_log_test.go:40-42createdandupdatedare parsed to*time.Time(native datetime type); pattern matches existing SDKCreated *time.Time,Updated *time.Time)TestIndividualAccountRequestInfoGetassertsassert.NotNil(t, getRequest.Created)@ sdk-infra/go/tests/sdk/individual_account_request_test.go:198accountType,flags,id,status,created,updatedare output-only (declared in struct; ignored by API on POST)TestIndividualAccountRequestPostassertsassert.Equal(t, "individual", request.AccountType)@ sdk-infra/go/tests/sdk/individual_account_request_test.go:65nameempty,taxIdinvalid,addressmissing sub-fields,income < 0,statusinvalid transition, unknownid) has a test that assertsInputErrorstype raised — code-agnostic (non-nilerr.Errors)Error.StarkErrorsTestIndividualAccountRequestPostInvalidName(line 308),TestIndividualAccountRequestPostInvalidTaxId(line 321),TestIndividualAccountRequestPostInvalidAddress(line 334),TestIndividualAccountRequestPostInvalidIncome(line 349),TestIndividualAccountRequestUpdateInvalidStatus(line 363),TestIndividualAccountRequestGetNotFound(line 399) @ sdk-infra/go/tests/sdk/individual_account_request_test.go — all asserterr.Errors != nilonlyIndividualAccountAttachment (M1–M14)
createaccepts a list ofIndividualAccountAttachmentand returns the same shape with server-assignedid,status,createdpopulatedTestIndividualAccountAttachmentPost@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:62-77content+contentTypeintodata:<contentType>;base64,<payload>URL client-side before serializationfmt.Sprintf("data:%s;base64,%s", ...))TestIndividualAccountAttachmentPostEncodesDataUrlassertsstrings.HasPrefix(attachments[0].Content, "data:image/png;base64,")@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:83-104contentTypeis input-only: after constructor builds the data URL,contentTypeis blanked and never sent as its own wire fieldattachments[i].ContentType = "")TestIndividualAccountAttachmentPostEncodesDataUrlassertsassert.Equal(t, "", attachments[0].ContentType)@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:103get(id)returns a singleIndividualAccountAttachmentby idTestIndividualAccountAttachmentInfoGet@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:173-214queryreturns a channel ofIndividualAccountAttachment, acceptinglimit,after,before,status,tags,idsTestIndividualAccountAttachmentQuery@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:121-146pagereturns([]IndividualAccountAttachment, cursor, err)and accepts the same params as query pluscursorTestIndividualAccountAttachmentPage@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:149-169cancel(id)maps toDELETEand returns resource withstatus = "deleted"(not"canceled"); cancel is idempotent — second cancel succeedsutils.Delete)TestIndividualAccountAttachmentCancelassertsassert.Equal(t, "deleted", canceled.Status)@ line 240;TestIndividualAccountAttachmentCancelIdempotentasserts second cancel succeeds @ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:246-273individualaccountattachment(notaccountrequestattachment)package individualaccountattachment)individualaccountattachment)IndividualAccountAttachment.Logis read-only, exposed underindividualaccountattachment/log, providesget,query,page; Log'sattachmentfield is the parent type (not a string id)Attachment IndividualAccountAttachment.IndividualAccountAttachmentat line 26)TestIndividualAccountAttachmentLogGetassertsgetLog.Attachment.Id@ sdk-infra/go/tests/sdk/individual_account_attachment_log_test.go:128Log.queryandLog.pageacceptlimit,after,before,types,attachmentIds(notaccountRequestIds)attachmentIdsper docstring lines 67, 108TestIndividualAccountAttachmentLogQueryusesparams["attachmentIds"]@ sdk-infra/go/tests/sdk/individual_account_attachment_log_test.go:44-45;TestIndividualAccountAttachmentLogPageusesparams["attachmentIds"]@ line 74typeenum is exactlydrivers-license-front|drivers-license-back|identity-front|identity-back; noselfie"identity-front"(no selfie)TestIndividualAccountAttachmentPostTypeEnumassertsassert.Contains(t, validTypes, attachment.Type)wherevalidTypesexcludes"selfie"@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:108-118createdis parsed to*time.Time(native datetime type)Created *time.Time)TestIndividualAccountAttachmentInfoGetassertsassert.NotNil(t, getAttachment.Created)@ sdk-infra/go/tests/sdk/individual_account_attachment_test.go:210typeinvalid,contentempty,contentTypemissing,accountRequestIdnot found, unknownid) has a test assertingInputErrorstype raised — code-agnostic; each attachment error test creates a fresh parent requestError.StarkErrorsTestIndividualAccountAttachmentPostInvalidType(line 288),TestIndividualAccountAttachmentPostInvalidContent(line 299),TestIndividualAccountAttachmentPostInvalidContentType(line 311),TestIndividualAccountAttachmentPostNotFoundParent(line 325),TestIndividualAccountAttachmentGetNotFound(line 339) @ sdk-infra/go/tests/sdk/individual_account_attachment_test.go — all asserterr.Errors != nilonly; fixtureExample.IndividualAccountAttachment()provisions a fresh parent per call (example_generator.go:562-589)AccountRequestAttachmentresource (route/account-request-attachment, SDK identifieraccountRequestAttachment) is removed in the same change set — no dual exposureaccountrequestattachmentpackage has ever existed (grep returned 0 results foraccountRequestAttachment|account-request-attachmentin src); this is ageneraterun — there is no legacy resource to remove. Test comment at individual_account_attachment_test.go:26-28 explicitly records this verification.Summary
Advisory notes (not blocking — route to Phase 5 / pattern-reviewer if not already flagged)
These are docstring/comment inaccuracies in the scaffold. They do not affect runtime behavior and are not Phase 7 blocking items, but should be addressed:
Stale status enum in IndividualAccountRequest scaffold docstring:
individual_account_request.go:15,30,105,147still reference"success" | "failed" | "canceled"(v1 values). The v3 contract enum isapproved | created | denied | processing | updated. The struct and test are correct; only the doc comment is stale.Stale type/status enum in IndividualAccountAttachment scaffold docstring:
individual_account_attachment.go:20,30include"selfie"in the type enum (contract explicitly excludes it) and list"canceled"as a status value (contract uses"deleted"). The Cancel docstring at lines 171–172,181 says "canceled" instead of "deleted". Implementation behavior (utils.Delete) and tests are correct.Stale log type enum in request/attachment log scaffold docstrings:
log/log.go:20-21,66,107(request log) andlog/log.go:20-21,66,107(attachment log) reference"success","failed","canceled"— v1 values. Tests use"created"(valid v3 value).Income field
json:",omitempty"onint:individual_account_request.go:40— Go'somitemptyomits integer fields with value0. The contract statesincome=0is accepted. A caller passingIncome: 0would have that field silently dropped from the JSON body. No test exercises this path (not an M-point violation, but worth noting for correctness).Metadata
contracts/individual-account-request.md(v3),contracts/individual-account-attachment.md(v3)runs/20260528-182857-account-approval/go/feature/account-approval89c7d3bac711035fc408ee04283fabd9edee8faa