| service | resourcegroupstaggingapi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| sdk_module | aws-sdk-go-v2/service/resourcegroupstaggingapi@v1.41.3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| last_audit_commit | 6d3b2159e | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| last_audit_date | 2026-10-10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| overall | A | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ops |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| families |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gaps | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| items_still_open | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| structural_gaps |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| deferred |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| leaks |
|
-
Real resourcegroupstaggingapi has no
ValidationExceptionerror shape. Its error model (aws-sdk-go-v2/service/resourcegroupstaggingapi/types/errors.go) is exactly:ConcurrentModificationException,ConstraintViolationException,InternalServiceException,InvalidParameterException,PaginationTokenExpiredException,ThrottledException. Any parameter-validation failure in this service isInvalidParameterException(400), notValidationException-- unlike many other AWS JSON services (DynamoDB, IAM, etc.) that do modelValidationException. -
PaginationTokenExpiredExceptionwas declared in the error model forGetResources/GetTagKeys/GetTagValuesbut never producible by any code path -- an unmatched/garbagePaginationTokensilently restarted pagination from page 1 instead. Real AWS pagination tokens are opaque and expire after 15 minutes; this in-memory backend has no encoded timestamp to check, so any token that fails to resolve against the current sorted result set (malformed, stale, or referencing a since-removed resource/key/value) is now treated as expired, the closest faithful emulation given the architecture.paginateResources/paginateStrings/findTokenStartnow returnErrPaginationTokenExpiredinstead of silently defaulting to index 0;GetTagKeys/GetTagValues/GetComplianceSummary'sStorageBackendinterface signatures changed to returnerrorto carry this (GetComplianceSummary's signature changed for its own, unrelated MaxResults-validation reason -- see below -- since that op's error list does not includePaginationTokenExpiredException). -
TagFilter.Valuescap was 256, matching nothing in the real model. Field-diffingaws-sdk-go'smodels/apis/resourcegroupstaggingapi/2017-01-26/api-2.jsonshowsTagValueList: {max: 20, min: 0}-- the real cap is 20, exactly matching the doc comment text ("each key can include up to 20 values") that the previous 256 constant silently ignored. FixedmaxTagFilterValuesto 20. -
GetResources'ResourceARNListhad no length cap at all. The realResourceARNListForGetshape declares{max: 100, min: 1}-- distinct fromTagResources/UntagResources'ResourceARNListForTagUntagshape, which caps at 20 (already correctly enforced viamaxARNsPerTagRequest). AddedmaxResourceARNListForGet = 100and a length check invalidateResourceARNListExclusivity. -
GetComplianceSummary'sMaxResultswas silently clamped to the default on out-of-range input instead of validating. UnlikeGetResources'ResourcesPerPage(whose model shape has no declared min/max -- silent clamping there is a defensible choice),MaxResultsGetComplianceSummaryexplicitly declares{min: 1, max: 1000}in the real model, the same kind of explicit rangeTagsPerPagealready enforces with an error. AddedvalidateComplianceSummaryMaxResults, matching that existing pattern;GetComplianceSummary'sStorageBackendsignature changed to(*GetComplianceSummaryOutput, error)to carry it. -
DescribeReportCreation's "NO REPORT" status: a previous audit had this backwards. The priorPARITY.mdasserted"NO REPORT"was "not a real AWS status value" and pinnednilStatusvia two tests with comments to that effect. Field-diffing the actualaws-sdk-go-v2doc comment onDescribeReportCreationOutput.Status(andaws-sdk-go'sdocs-2.json, the same source botocore/smithy generates that comment from) shows the opposite:"NO REPORT - No report was generated in the last 90 days"is explicitly documented as one of exactly four valid status values (RUNNING,SUCCEEDED,FAILED,NO REPORT). FixedDescribeReportCreationto return the literal"NO REPORT"string (notnil) both when no report has ever been started for a region, and when the most recent non-RUNNINGreport is older than the documented 90-day window (reportStaleAfter). Rewrote the two tests that had pinned the wrong behavior, and addedTestDescribeReportCreation_StaleReportBecomesNoReportfor the 90-day transition. -
Malformed request bodies use
SerializationException, matchingservices/organizations' convention for the same awsjson1.1 protocol -- this is a protocol-level failure (the body never parses far enough to know which operation-level error applies), not a modeled per-operation error, so it is intentionally distinct from theInvalidParameterExceptionused for well-formed-but-invalid parameters. -
StartReportCreationInput.S3BucketRegionwas a fabricated field with no counterpart in the real AWS API (aws-sdk-go-v2/service/resourcegroupstaggingapi'sStartReportCreationInputhas onlyS3Bucket). Removed along with its one-off test. -
GetResourcesResourceARNList mutual exclusion: real AWS rejects a request that combinesResourceARNListwithResourceTypeFilters,TagFilters, or any ofResourcesPerPage/TagsPerPage/PaginationToken(InvalidParameterException). Enforced viavalidateResourceARNListExclusivity. -
TagsPerPageis validated (100-500, matching the real API's documented range) and actually constrainsGetResourcespage splits by cumulative tag count (a resource with no tags counts as one tag) rather than by resource count alone, viacapByTagCount+resolveTagsPerPage, wired intopaginateResources. -
GetComplianceSummary/ListRequiredTagsreturning empty output is correct, not a stub-in-disguise -- CORRECTED THIS SWEEP. A prior note here claimed "gopherstack has no tag-policy engine anywhere (no Organizations policy-attachment model, no policy-document evaluator)"; that was inaccurate.services/organizations(seepolicies.go'spolicyTypeTag = "TAG_POLICY"andeffective_policy.go'sDescribeEffectivePolicy/mergeTagStyleChain) already models tag-policy documents, attachment to root/OU/account, and AWS's real root-to-target deep-merge inheritance rule forTAG_POLICY-style policies. Investigated wiring this intoGetComplianceSummarythis sweep and deliberately did not, for a more precise reason than "no engine exists": realGetComplianceSummaryis documented (AWS API reference) as callable only from an organization's management account, and its example response returnsSummaryListrows for three different member-accountTargetIdvalues underGroupBy=TARGET_ID-- it is fundamentally a cross-account aggregation operation. gopherstack has no multi-account resource-store simulation anywhere (every running instance models exactly one AWS account's resources), so there is no second account's tagged-resource set to aggregate against even with a working tag-policy evaluator. A single-account approximation would produce plausible-looking but semantically wrong numbers for what the real operation actually measures, so this was documented rather than built. An account with no tag policy attached genuinely reports zero noncompliant resources on real AWS too, so the current empty-but-honest output is not a regression.ListRequiredTags(areport_required_tag_for-driven feature, distinct fromGetComplianceSummary'stag_key/tag_valuebasic-compliance rules) was not separately investigated this sweep. Tracked (bd: gopherstack-i710). -
Cross-service tag wiring lives in
internal/app/cli.go(wireResourceGroupsTagging) -- EXPANDED THIS SWEEP from 6 to 11 of the ~90 services with nativeTagResourcesupport. Previously only dynamodb, sqs, sns, lambda, kms, secretsmanager were registered as providers/ARN taggers. Added ecs, athena, glue, ecr, kinesis, chosen because they were named explicitly in the tracking issue and their native tag stores were tractable to enumerate without inventing per-resource-kind constants:wireTaggingARNResources(the shared helperwireTaggingSQS/wireTaggingSNSalready used) was generalized to accept aresourceTypeOf(arn) stringclosure instead of one fixed resource-type string, and a newresourceTypeFromARN(arn, service)helper derives the AWS resource-type string (e.g."ecs:cluster") from an ARN's own resource segment for services whose flat ARN-keyed tag store spans more than one resource kind (ECS: clusters/services/task definitions/...; Athena: workgroups/data catalogs/capacity reservations/notebooks; Glue: databases/crawlers/jobs/data quality rulesets/connections/triggers/workflows). ECR and Kinesis have exactly one taggable resource kind each (repository, stream) so use a constant resource type instead, same as SQS/SNS. Each newly-wired service got a newTaggedResources()/TaggedStreams()accessor method (mirroring the pre-existingTaggedQueues/TaggedTopics/TaggedFunctions/TaggedKeys/TaggedSecrets/TaggedTablespattern) that excludes resources with zero tags, matching real AWS'sGetResourcesbehavior of only returning tagged resources. This backend still faithfully reportsFailedResourcesMapwithInvalidParameterException("no registered tagger handles ARN") for every other service's ARNs, which is the correct behavior for an unregistered tagger -- the gap is in what's registered, not in how this package handles an unregistered ARN. The remaining services were unwired as of this note; seeinternal/app/cli.go'swireResourceGroupsTaggingdoc comment for the current exact list (coverage has grown across several sweeps since -- see the gaps section above for the up-to-date count) and for why s3control was skipped (its taggable ARNs use the"s3"/"s3-object-lambda"service namespaces, not"s3control", so it doesn't fit the current single-namespace-per-service dispatch without further generalization). Tracked (bd: gopherstack-3xne). -
Wire shapes for
Tag,TagFilter,FailureInfo,ComplianceDetails,ResourceTagMapping,RequiredTag,Summary/ComplianceSummarywere all checked field-by-field againstaws-sdk-go-v2/service/resourcegroupstaggingapi/typesand the underlyingaws-sdk-goapi-2.json/docs-2.jsonshape models, and match (including the easy-to-misspellKeysWithNoncompliantValues, and the 2-valueFailureInfo.ErrorCodeenum --InternalServiceException/InvalidParameterExceptiononly).
Census: paginateResources/findTokenStart (GetResources) and paginateStrings
(GetTagKeys/GetTagValues), both in pagination.go, already use the "return a found
flag or error" safe-by-construction pattern this campaign is looking for
(ErrPaginationTokenExpired on a scan miss, never a silent restart at offset 0) — one of
the three patterns explicitly called out as already present in this repo. Both callers
(get_resources.go, tag_keys.go, tag_values.go) propagate the error rather than
swallowing it. Verdict: correct, no bug found.
Existing tests (TestGetResources_PaginationWalk, TestGetResources_UnmatchedTokenExpired
in get_resources_test.go) already exercise both the boundary walk and the stale-cursor
case thoroughly at the backend level — no gap. Added pagination_arithmetic_test.go with
a new newTestRGTAClient helper (this service had no typed-aws-sdk-go-v2-client test
helper at all before this pass) confirming the same two properties survive the real
serializer/deserializer round trip: a GetResources boundary walk (N=7, page=3, exact
order preserved) plus a stale-token call that errors instead of looping.
Gates: go build, go vet, go test -race -count=1, golangci-lint run — all clean
(./services/resourcegroupstaggingapi/...).
Read this service against bd gopherstack-uox6's class ("a parameter that is read,
applied, and wrong"). get_resources.go's GetResources filters were checked
against GetResourcesInput's own doc comment, which spells out its combining rules
explicitly with worked examples:
applyTagFilters/matchesTagFilter: AND acrossTagFiltersentries, OR across a single filter'sValues, emptyValuesmeans "any value for that key" -- matches the doc'sfilter1/filter2/filter3worked example exactly.applyResourceTypeFilter/matchesResourceTypeFilter: OR acrossResourceTypeFiltersentries; a service-only filter (no colon) matches any resource type with thatservice:prefix, an exact filter matches exactly -- matches "specifying a service of ec2 returns all... specifying ec2:instance returns only EC2 instances."applyARNListFilter: exact-match set membership, matchingResourceARNList's doc (no wildcard or prefix form documented).
GetComplianceSummary's RegionFilters/applyRegionFilter (OR-across-regions) and
ResourceTypeFilters (reused, OR) were checked too, but the whole computed,
filtered all slice is discarded before the response is built (_ = all; the
mock has no tag policy, so NonCompliantResources is always 0 by design) -- so
TagKeyFilters/applyTagKeyFilter's AND-vs-OR combining rule (the doc's own
wording, "resources that have tags with the specified tag keys," does not state
which) has no observable effect on any response regardless of which combining
rule it implements. Recorded as a gap rather than guessed at, since fixing it
would be unverifiable from any client-visible behaviour.
Pagination boundary checked too: capByTagCount's "does not exceed TagsPerPage"
cap uses total+count > tagsPerPage (keeps items while cumulative count <=
tagsPerPage) -- correctly inclusive of the exact TagsPerPage value.
No bugs found; no code changes in this service this pass.
Typed-client coverage sweep: DescribeReportCreation, GetComplianceSummary,
GetTagKeys, GetTagValues, ListRequiredTags, StartReportCreation,
TagResources, UntagResources driven through the real aws-sdk-go-v2 client
for the first time (realclient_tags_and_compliance_test.go, 3 subtests: tag
keys/values via a registered test provider, tag/untag resources via a
registered ARNTagger/ARNUntagger, compliance summary + required tags +
report creation). resourcegroupstaggingapi moved from 1/9 to 9/9
typed-covered per cmd/clientcoverage.
No real bugs found -- every op passed on the first correctly-shaped
request. ListRequiredTags/GetComplianceSummary legitimately return
empty results with no tag-policy provider registered (this file's own
documented, honest-gap behavior, not a stub).
Gates: go build ./..., go vet ./services/resourcegroupstaggingapi/...,
go test -race -count=1 ./services/resourcegroupstaggingapi/... and
./pkgs/persistence/..., golangci-lint run --new-from-rev=HEAD ./services/resourcegroupstaggingapi/... (0 issues). go run ./cmd/paritylint stays at 0 FAIL. No persisted-struct/snapshot changes.
Adjudicated all 9 items_still_open + 2 deferred entries against HEAD. Removed
6 as stale: two entries claiming ResourceTypeFilters used a stricter regex
and ResourceARN had no 1011-char max were both false against current code
(grep regexp returns zero hits in this package; validateResourceARNLength
already enforces the real 1011-char cap in both validateARNList -- used by
TagResources/UntagResources -- and GetResources directly). Also removed 4
superseded historical internal/app/cli.go-wiring-progress entries (55->61->69->91
services) that were fully subsumed by the final 91-service entry. Kept 3
items_still_open + 1 deferred, consolidated and tightened to one paragraph
each. No code fix needed (behavior fixes claimed by 2 of the removed entries
were already correct at HEAD).
Gates: gofmt -l clean; go build ./services/resourcegroupstaggingapi/...
and go vet ./services/resourcegroupstaggingapi/... clean; go test -race -count=1 ./services/resourcegroupstaggingapi/... and go test -count=1 ./pkgs/persistence/ pass; golangci-lint run ./services/resourcegroupstaggingapi/... 0 issues; git diff --stat go.mod go.sum empty. No code or persisted-field change.
The bridge lists the request region's resources and resolves TagResources/UntagResources by the ARN's region for ECS, Athena, Glue, ECR, Backup, CodeCommit, Cloud Map, Lightsail, Cognito IdP, SESv2 and CodeDeploy (regionalTagSpec in internal/app/cross_region.go). Auto Scaling, ELBv2 and CloudFormation expose no tagged-resource listing and are not bridged. Proof: TestInitializeServices_TaggingBridgeFollowsRegion.
GetResources rejects ResourcesPerPage outside 1-100 with InvalidParameterException (api_op_GetResources.go doc) instead of clamping. TagResources/UntagResources report a tagger's not-found or invalid-parameter failure as InvalidParameterException/400 in FailedResourcesMap rather than InternalServiceException/500. Proof: TestGetResources_ResourcesPerPageRange, TestTagResources_TaggerErrorClassification.