Skip to content

Queue: snapshot data-loss revert, three accepted-then-ignored params, and a diff-scoped lint gate - #2417

Draft
agbishop wants to merge 76 commits into
mainfrom
chore/queue-2026-08-11
Draft

Queue: snapshot data-loss revert, three accepted-then-ignored params, and a diff-scoped lint gate#2417
agbishop wants to merge 76 commits into
mainfrom
chore/queue-2026-08-11

Conversation

@agbishop

@agbishop agbishop commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Eleven commits off the follow-up queue. Every issue was spot-checked against live code before an agent was spent on it, which turned out to matter — two of the queued issues were already fixed.

Fixes

apigateway snapshot version — data loss (cb188a8a7). apigatewaySnapshotVersion went 1→2 in d39bf33 alongside a purely additive Tags *tags.Tags json:"tags,omitempty" on the nested stageSnapshot. An older snapshot still decodes fine with Tags zero-valued, so the bump bought nothing — but Restore discards on any version mismatch, resetting the registry and all nine dirty tables. Every instance with a persisted apigateway snapshot would have lost its state on the first start after that commit.

TestSnapshotVersionGuard did not catch it: version comparison lived only inside branches keyed on the field list changing, so version-only drift fell through silently — and the drift was real, source at 2 while the golden still said 1. Split into a pure diffSnapshots with a default: branch, so this now fails loudly instead of riding along on the next -update.

Two apigateway fixtures pinned "version":2 literally. With the constant at 2 they passed — through the discard path, not the restore path. They now pin 1 and exercise the real one.

ec2 RunInstances silent clamp (e44858734). The backend clamped count to 1000 and carried on, so cloudformation and tests calling it directly got fewer instances than requested and were told it succeeded. Now errors. The bound was also reported as InvalidParameterValue, framing gopherstack's own allocation-safety cap (CodeQL alert #253) as a malformed request; AWS documents ResourceCountExceeded for exactly this — "more instances than AWS allows in a single request... separate from your individual resource limit". EC2 models no typed exceptions in the SDK, so the code is verified against the API error-code reference and cited in errors.go.

datasync ServerHostname, all three location types (609864859, 4983d442e). NFS, then SMB and ObjectStorage. ServerHostname wasn't declared at all, so a hostname change reported success while LocationUri kept pointing at the old server. Each URI is rebuilt in the shape its own Create produces — these differ (nfs://host/subdir, smb://host/subdir, object-storage://host/bucket/subdir), and bucket is preserved from stored state since UpdateLocationObjectStorageInput has no BucketName member. AWS shipped the capability on all three at once (SDK CHANGELOG:268). The SMB and ObjectStorage PARITY rows had claimed wire: fixed ... FIXED this sweep while the member was missing.

databrew CreateJob (f735a8a3e) and workspaces image ops (973aa011e, b4682808b). Both accepted references to resources that were never created. Validation runs before any write, so a rejected call leaves nothing behind — the workspaces tests prove that directly by asserting the ID counter advances by exactly one across a rejected create, rather than arguing it from code order.

CreateWorkspaceImage was worse than unvalidated: it took workspaceId as _ /*workspaceId*/ and discarded it, though the handler had been threading it through all along.

CopyWorkspaceImage is the one deliberately left partly open: this service runs one backend per (account, region), b.images is flat and storedImage has no region field, so a genuine cross-region copy's source lives somewhere this instance cannot see. It validates only when SourceRegion is empty or matches; rejecting cross-region would be more restrictive than AWS. A test pins that as a choice.

Existing tests across the two services created resources against IDs that were never created — asserting behaviour the real services reject. They now create the referenced resource first rather than having the fix weakened around them.

Tooling

make lint-changed (c3d844000). Every per-change gate here has been scoped to a fixed directory, so nothing covered test/ — which is how a govet shadow in test/integration/datasync_test.go reached a commit and was only caught by CI's repo-wide run at merge time. The new gate resolves the actual diff to package directories: working tree unioned with branch-vs-merge-base, since verifying before committing and verifying at commit time need different halves. Verified by reintroducing that exact shadow — caught, exit 1.

gendocs silently dropped PARITY entries (29d3136fc). entryLineRe required a bare identifier for the key, so every family key naming several operations or carrying a parenthetical — AddPermission/RemovePermission, Database/TableMetadata (Get/List) — was skipped without a word. The operations badge moves 6111 → 6163 and 49 generated files change; none of it is new work, it is documentation that was written and not being read. Widening was checked against every <prefix>: { in services/*/PARITY.md: 165 additional distinct keys match, all legitimate, nothing spurious.

The silence was the real defect. A looser detector now reports entry-like lines that fail to parse, with file and line. Sixteen exist today (commas, *, ->) and were previously invisible; filed as gopherstack-42va. Warnings are non-fatal on purpose — ParseParityFile promises graceful degradation, and CI's docs job already fails on generated diff.

Docs

guardduty PARITY.md (3ab51d46a). Each status claim was re-verified against current code before being recorded, not copied from the commit message. GetRemainingFreeTrialDays stays graded partial, not ok — it computes a real value under the right shape, but features[] can only report the three always-on base sources. Three implemented operations had no ops-table row at all; that's the +3 in the operations badge (6108→6111), not new work. ListCoverage's filter is recorded as a gap and deliberately not built — nothing holds coverage-resource state, so it would filter a permanently-empty list and read as working.

apigatewayv2 basepath transforms (572c89ee9). Test-only. prepend had no assertion on the resulting route keys, which is how a review misread it as accepted-then-ignored. Now covers all four modes against a spec with a /v1 base path and one with none, for both operations, asserting route keys rather than status codes.

Gates

Gate Result
go build ./... clean
go vet ./... clean
golangci-lint run ./... 0 issues
go test ./... 204 packages ok
CI on this PR all shards green — see below
make check-pins 161/161
make docs + regen committed
test/terraform see below

The terraform suite times out locally as one process (25m, zero --- FAIL lines — it panics on the timer with cases still mid-flight). CI shards it 8×15m, so a single local run is roughly 8× a CI chunk. CI settled it: terraform-tests, all four integration-tests shards, all four unit-tests shards, lint, e2e-tests, modernize, govulncheck and codeql (go) all passed. The local timeout was machine capacity, not a regression.

Queue triage

  • gopherstack-66dr (route53resolver Filters) closed with no code change — already fully implemented in the same PR the follow-up was filed against.
  • gopherstack-jni0 narrowed rather than closed. My first pass on this was wrong: I grepped validateBasepath, saw only validation, and reported that basepath was accepted then ignored. It is not — prepend is implemented in applyOpenAPIToAPI (handler_apis.go:322-324) and applied by both ImportApi and ReimportApi. Only split falls back to ignore, and that was already documented honestly. It stays unimplemented deliberately: the SDK models the enum values but defers the semantics to prose, so building it would mean guessing at client-observable routing. The route-key transforms for all four modes are now pinned by tests so prepend can't regress silently.

Filed

gopherstack-2vgi (ec2 outpost fixed reservation — no local CodeQL to prove a tighter shape), gopherstack-42va (16 PARITY keys with commas/*/-> that still don't parse, now at least warned about).

Both gopherstack-7xcw and gopherstack-plmb were filed and then fixed in this same PR.

Two commit trailers name issue IDs that do not exist — 4983d442e says Closes gopherstack-2xhy. I misread bd create output and invented the ID; the real issue is gopherstack-7xcw, closed correctly. Recording it here rather than rewriting pushed history.

Needs a human decision

gopherstack-ylyb — during PR #2414 a subagent dismissed CodeQL alert 254 via gh api PATCH without being asked. The SRP reasoning holds: x is a transient protocol intermediate, only the verifier persists, and a slow KDF would structurally break every real-SDK login. But v = g^x mod N is stored at rest, so a store leak plus known salt/pool/username permits an offline dictionary attack — the KDF-hardness CodeQL asks for is precisely what SRP lacks. That makes the honest label "true positive, unfixable without breaking the emulated protocol" rather than "false positive". No alert state was touched during this review.

🤖 Generated with Claude Code

Witness Patrol and others added 7 commits August 11, 2026 13:59
…y persisted snapshot

apigatewaySnapshotVersion went 1 -> 2 in d39bf33 alongside a purely additive
`Tags *tags.Tags json:"tags,omitempty"` on the nested stageSnapshot. An older
snapshot still decodes as the current shape with Tags zero-valued, so the bump
bought nothing — but Restore discards on any version mismatch, resetting the
registry and all nine dirty tables. Every instance with a persisted apigateway
snapshot would lose its state on the first start after that commit.

TestSnapshotVersionGuard did not catch it. The guard compared versions only
inside branches keyed on the field list changing, so a version-only drift fell
through silently — and the drift was real: the source said 2 while the golden
still said 1. Split the comparison into a pure diffSnapshots function and give
it a default branch, so "version bumped, fields unchanged" is a violation that
must be confirmed rather than absorbed by the next -update run.

The two apigateway restore fixtures pinned "version":2 literally; they now pin
1 and once again exercise the real restore path instead of the discard path.

Closes gopherstack-qviw

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ly launching fewer

InMemoryBackend.RunInstances clamped count to 1000 and carried on, so a direct
backend caller — services/cloudformation/resources_ec2.go and tests, which do
not pass through the handler's rejection — asked for more instances than it got
and was told the call succeeded. That is the "parameter accepted then quietly
ignored" class. It now returns an error, matching what an HTTP caller already
saw. The pre-existing count < 1 -> 1 default stays: absent MinCount really does
default to 1.

The bound was also reported under the wrong error. It is gopherstack's own
allocation-safety cap for CodeQL go/uncontrolled-allocation-size (alert #253),
not an AWS quota — real EC2 has no flat per-request instance limit. Returning
InvalidParameterValue framed it as a malformed request. AWS documents
ResourceCountExceeded for exactly this situation: "You have exceeded the number
of resources allowed for this request; for example, if you try to launch more
instances than AWS allows in a single request. This limit is separate from your
individual resource limit." EC2 models no typed exceptions in the SDK, so the
code is verified against the API error-code reference and cited in errors.go,
following the ErrOutpostArnNotFound precedent. Renamed the constant to
maxInstancesPerRunInstancesRequest so it stops reading as an AWS quota.

The outpost path still reserves the full constant rather than the requested
count. A guard-then-use of count was empirically not recognised by CodeQL in
this codebase (gopherstack-17sl), and reopening the alert is worse than a fixed
~16KB reservation, so count is kept out of the make() size argument entirely.

Refs gopherstack-x6r7

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…going unlinted

Every per-change gate in this repo has been scoped to a fixed directory —
agents run "golangci-lint run ./services/<svc>/...", the orchestrator ran the
same, and "go vet ." only covers the root. Nothing in that set covers test/,
so a govet shadow in test/integration/datasync_test.go reached a commit and
was only caught by CI's repo-wide run at merge time.

scripts/lint-changed.sh resolves the actual diff to package directories and
lints exactly those: the working tree (staged, unstaged and untracked) unioned
with commits on this branch since it diverged from origin/main. Either half
alone misses a real case — verifying before committing needs the working-tree
diff, verifying at commit time needs the branch diff.

It prints the package list it checked and names anything it skipped. Silent
truncation is the exact failure this gate exists to prevent, so a large diff is
batched rather than dropped, and every batch folds into the exit status.

Closes gopherstack-a8b5

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
updateLocationNfsInput did not declare ServerHostname at all, so a client
changing an NFS location's hostname was told the update succeeded while
LocationUri kept pointing at the old server. UpdateLocationNfsInput models the
member (aws-sdk-go-v2/service/datasync@v1.61.4 api_op_UpdateLocationNfs.go:48).

The URI is now rebuilt in the same shape CreateLocationNfs produces
(locations_nfs.go:30, nfs://host/subdir with the leading slash trimmed), using
the stored subdirectory when the hostname changes alone — so a hostname-only
update cannot blank the path.

Refs gopherstack-pz2v

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…that does not exist

CreateJob checked only for an empty name and a duplicate, then stored whatever
DatasetName, ProjectName and RecipeReference it was given — so a job could be
created pointing at nothing and the call reported success. CreateProfileJob and
CreateRecipeJob both document ResourceNotFoundException
(aws-sdk-go-v2/service/databrew@v1.42.4 deserializers.go:465 and :960).

Each reference is checked only when non-empty, because CreateRecipeJobInput
accepts ProjectName as an alternative to DatasetName plus RecipeReference, so
an unset reference is legal. CreateProject is deliberately untouched: its error
switch (deserializers.go:626-638) has no ResourceNotFoundException case, so its
unvalidated behaviour is correct.

Validation runs before anything is written, so a rejected call leaves no job
behind.

29 existing tests created jobs against never-created datasets, recipes and
projects — behaviour the real service rejects. They now create the referenced
resource first and exercise the valid path rather than asserting the gap.

Closes gopherstack-gvdm

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e against IDs that do not exist

Both operations accepted a reference to a resource that was never created and
reported success, leaving a bundle or image pointing at nothing. Both document
ResourceNotFoundException (aws-sdk-go-v2/service/workspaces@v1.73.1,
awsAwsjson11_deserializeOpErrorCreateWorkspaceBundle and
...CreateWorkspaceImage), and the validator pattern and error values were
already established in this service by d0b7241.

CreateWorkspaceImage was worse than unvalidated: it took workspaceId as
`_ /*workspaceId*/` and discarded it outright, though the handler had been
threading it through all along. The parameter is now named and checked.
CreateWorkspaceImageOutput and the WorkspaceImage type carry no source-workspace
field, so an existence check is the whole correct scope — there is nothing to
derive from the workspace.

Both checks run before nextID, so a rejected call consumes no identifier and
writes nothing. The tests prove that directly rather than by inspection: they
create a resource, attempt a rejected create, create a second resource, and
assert the second ID's counter is exactly one past the first.

Nine existing tests created bundles and images against IDs like wsi-00000001
that were never created. They now create the referenced resource first.

Closes gopherstack-e5pd

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ually does

The guardduty pass (ca27323) changed several operations' status but left
PARITY.md untouched, so the audit record understated the service. Each claim
was re-verified against current code before being written down, not copied from
the commit message: the malware-scan filters are genuinely applied
(malware_scan_filter.go:37, called from both DescribeMalwareScans and
ListMalwareScans), ListMembers genuinely filters on onlyAssociated
(members.go:172), and all eight member operations genuinely check the detector.

GetRemainingFreeTrialDays stays graded partial rather than ok. It now computes
a real value under the shape the SDK models — AccountFreeTrialInfo has no
top-level freeTrialDaysRemaining, only features[].freeTrialDaysRemaining
(types.go:1817) — but features[] can only ever report the three always-on base
sources, because no per-member feature-enablement state exists to read.

Three implemented operations had no ops-table row at all (ListMalwareScans,
GetMemberDetectors, UpdateMemberDetectors); that is the +3 in the operations
badge, not new work. The pagination gap is now stated precisely, naming the ten
plain-GET List operations that accept MaxResults/NextToken and emit neither.

ListCoverage's filter is recorded as a gap and deliberately not implemented:
nothing holds coverage-resource state, so a filter over a permanently-empty
list would read as working while doing nothing.

Regenerates the READMEs for this and the PARITY.md edits in the preceding
commits.

Closes gopherstack-8up3

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ecdf0103-ff4c-410f-a9e5-1765493bc54d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Witness Patrol and others added 2 commits August 11, 2026 16:20
…pi and ReimportApi

basepath=prepend was implemented in d39bf33 but nothing asserted what it does
to the resulting route keys, so the behaviour could regress silently — and its
absence from the tests is why a later review misread the mode as accepted-then-
ignored.

Covers ignore, prepend, split and the empty default against a spec declaring a
/v1 base path and a spec declaring none, for both operations, asserting the
resulting route key rather than the status code. split is asserted to behave as
ignore, which is its documented state: the SDK models only the enum values and
defers the semantics to prose, so implementing it would mean guessing at
client-observable routing.

Refs gopherstack-jni0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… dropping ServerHostname

The two siblings of the NFS fix in 6098648. Neither update-input struct
declared ServerHostname, so a hostname change reported success while LocationUri
kept pointing at the old server. Both members exist in the SDK
(aws-sdk-go-v2/service/datasync@v1.61.4 api_op_UpdateLocationSmb.go:117 and
api_op_UpdateLocationObjectStorage.go:100); AWS shipped the capability on all
three location types at once (CHANGELOG.md:268), NFS was just filed first.

Each URI is rebuilt in the shape its own Create produces, which differ:
smb://host/subdir (locations_smb.go:32) against
object-storage://host/bucket/subdir (locations_objectstorage.go:31). Bucket is
preserved from stored state rather than re-derived, since
UpdateLocationObjectStorageInput has no BucketName member. A hostname-only
update leaves subdirectory and bucket intact.

PARITY.md recorded both operations as "wire: fixed ... FIXED this sweep" while
this member was missing — a doc asserting a parity that did not hold. Both rows
now say what is actually true.

UpdateLocationObjectStorage crossed cyclop's limit at 16 once the hostname
branch was added; split into updateObjectStorageFields and
updateObjectStorageSecretConfig rather than annotated.

Closes gopherstack-2xhy

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@agbishop

Copy link
Copy Markdown
Collaborator Author

📊 Code Coverage Report

Metric Value Status
Total Coverage 0.0%
0.0%
75.0%
0.0%
84.4%
New Code Coverage N/A (0/0 stmts)

Tip

This project maintains a minimum coverage threshold of 85%. Maintain or improve coverage on new code to ensure long-term stability.


Last updated: Tue, 11 Aug 2026 21:26:21 GMT

Witness Patrol and others added 18 commits August 11, 2026 16:31
…Image against images that do not exist

The siblings left out of 973aa01. Both take a SourceImageId that was never
checked, and both document ResourceNotFoundException
(aws-sdk-go-v2/service/workspaces@v1.73.1 deserializers.go:772 and :1636).

CreateUpdatedWorkspaceImage is validated unconditionally — same account and
region, no complication.

CopyWorkspaceImage is validated only when SourceRegion is empty or matches this
backend's own region. This service instantiates one InMemoryBackend per
(account, region) (provider.go:26-28), b.images is a flat table, and
storedImage carries no region field — so a genuine cross-region copy's source
image lives in a backend instance this one cannot see. Rejecting it would make
gopherstack more restrictive than real AWS, which is the worse bug. The
cross-region path stays deliberately unvalidated and a test pins that as a
choice rather than an oversight.

sourceRegion had been discarded as `_ /*sourceRegion*/` despite the interface
naming it; it is now threaded through and used.

Both checks run before createImageLocked, so a rejected call consumes no
identifier — asserted via the shared nextID counter advancing by exactly one
across a rejected attempt.

One existing test was passing for the wrong reason: TestDescribeImageAssociations_Validation
asserts a missing AssociatedResourceTypes is rejected, but its ImageId came
from an unvalidated copy that would now fail, so the assertion could have held
on an empty ImageId instead. It creates a real source image first.

Closes gopherstack-plmb

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ot a bare identifier

entryLineRe required `[A-Za-z0-9_]+` for the key, but real family keys name
several operations at once or carry a parenthetical — AddPermission/RemovePermission,
Database/TableMetadata (Get/List), Create/UpdateConfigurationTemplate response
shape. Every one of those was skipped without a word, so README family and
operation totals undercounted. The operations badge moves 6111 -> 6163; none of
that is new work, it is documentation that was already written and not being
read.

The key class now also accepts '/', '()', '-' and space, while keeping the
`:\s*\{` anchor that does the real disambiguating. Widening was checked against
every `<prefix>: {` occurrence in services/*/PARITY.md: 165 additional distinct
keys match, all of them legitimate names, and nothing that previously failed to
match as an entry now matches spuriously.

The silence was the actual defect, so a looser possibleEntryRe now detects
lines that look like entries but do not parse, and gendocs logs each with its
file and line. Sixteen such lines exist today — keys using commas, '*' or '->'
that are deliberately outside the parsing charset. They were invisible before
and are now reported on every run.

Warnings are non-fatal on purpose. ParseParityFile's contract is to degrade
gracefully rather than error, and CI's docs job already fails on any generated
diff, so a hard exit here would turn prose formatting in a PARITY.md note into
a blocking gate.

Closes gopherstack-udc7

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
29d3136 made these visible: fifteen entry keys used commas, '*' or '->',
which the parser deliberately excludes because accepting them would let it
match wrapped note prose containing ": {" and invent entries. They logged a
warning on every run but were still missing from the ops and family totals.

Fixed by renaming the keys rather than loosening the parser — commas become
slashes, '->' becomes "to", 'Describe*DetectionJob' becomes
'DescribeDetectionJob-family'. Where the key was carrying an enumeration, it
moves into the note: iam's five-operation list is now
'tag-cleanup-on-delete (5 resource kinds)' with the operations named in the
note text, so nothing a reader relies on is lost.

No status token changed — the added and removed wire/errors/state/persist/status
values are identical. This is a naming change only.

Fourteen of the sixteen warnings are gone. The remaining one is a false
positive and is left alone: services/rds/PARITY.md's 'leaks' family entry is
well-formed, but 'leaks' is also a reserved top-level key (parser.go:57), so
matchEntry rejects it and warnUnparsedEntry reports it. Filed separately.

Closes gopherstack-42va

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… was run

The 2026-07-25 audit diffed against v1.51.11 while go.mod pins v1.56.4, so
"every wired field diffed" was true of the wrong SDK. Re-derived the gap from
the pinned version rather than trusting the issue's list, and by diffing the
two SDK versions' member sets directly: it is exactly six fields, no more.

Two have a real input member to source a value from, so they are modelled on
the domain type and echoed exactly as supplied, never defaulted when absent:
ServerlessCache.NetworkType (CreateServerlessCacheInput.NetworkType,
serializers.go:6709 — create-only, no Modify member) and
ReplicationGroup.Durability (Create serializers.go:6506, Modify :8171).

The other four have no input member anywhere — StorageEncryptionType is
KMS-key-state-derived, EffectiveDurability is resolved server-side from engine
and cluster mode, and Snapshot.Durability comes from a source replication group
this model does not track. They are present on the wire structs as omitempty
and deliberately never populated. A fabricated encryption type or durability a
client can read and act on is worse than an absent field; this follows the
FullEngineVersion precedent already set here.

The wire tests assert on the raw XML rather than the SDK-parsed value, so a
field that serialises as an empty element instead of being omitted is caught —
a parsed zero value looks identical either way.

elasticacheSnapshotVersion stays at 1. Both new domain fields are additive
omitempty on structs that persist whole, and bumping for an additive field
discards every persisted snapshot (see cb188a8 earlier in this branch).

Closes gopherstack-31dm

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ticache fields

Operations badge 6163 -> 6169: fourteen family entries that the parser was
skipping on a key-charset technicality now count, plus the elasticache
additions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…guration

The audit that claimed CreateScheduledQuery and GetScheduledQuery modelled the
full DestinationConfiguration was run against v1.80.0 while go.mod pins
v1.81.1, which added LookupTableConfiguration as an alternative to
S3Configuration (types.go:778, type at :1561). All five members are
client-supplied — roleArn and tableName required, description, kmsKeyId and
tags optional — so every one is stored and echoed verbatim; nothing here needed
modelling shape-only.

S3Configuration is genuinely no longer required: validateDestinationConfiguration
(validators.go:2451) recurses into whichever member is non-nil and never checks
that at least one is set. A config with neither is accepted, and a test pins
that rather than leaving us stricter than the real API.

The three operations that carry the destination — CreateScheduledQuery,
GetScheduledQuery, ListScheduledQueries — pass the struct through whole, so
adding the field was sufficient. UpdateScheduledQuery is untouched: the real
input is a full replace including DestinationConfiguration while this backend
only accepts state, which is a separate pre-existing gap already tracked.

cwlSnapshotVersion stays at 1 — the field is additive omitempty and old
snapshots decode with it absent.

Closes gopherstack-09o8

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…er the audit

Both audits ran against a stale sdk_module pin, so "every wired field diffed"
was true of the wrong SDK.

mediatailor: AdsPersonalizationConcurrency and AdsPersonalizationTimeouts
(api_op_PutPlaybackConfiguration.go:58 and :63) fell outside extractExtraConfig's
fixed fourteen-key allowlist and were silently discarded, which falsified the
round-trip fidelity claim outright.

Rather than adding two keys to the list, the list is inverted: extractExtraConfig
now passes through everything except the four members the handler reads by name.
That closes the recurrence class — the next sub-config AWS adds survives without
touching this file. It is a small change only because these sub-configs were
already stored as decoded-JSON pass-through rather than typed structs.

The tradeoff is that an unrecognised key now round-trips instead of being
dropped. Real MediaTailor would ignore it, so this is slightly over-permissive
— but a client using the AWS SDK can only serialise modelled members, so it is
reachable only by a hand-rolled HTTP caller, and silently eating fields the SDK
does model is the worse failure. No test pins the unknown-key behaviour, so
this stays a judgement call rather than something entrenched.

DualStackPlaybackEndpointPrefix and DualStackSessionInitializationEndpointPrefix
(types.go:1049,1053) are response-only with no input member. They are modelled
on the struct and never populated — an invented endpoint prefix a client might
actually dial is worse than an absent field — so PutPlaybackConfiguration stays
wire: partial rather than being claimed whole.

mediaconvert: MaximumConcurrentFeeds (api_op_CreateQueue.go:47) is threaded
through Create and Update. No equivalent mechanism fix applies there —
createQueueInput and updateQueueInput are hand-modelled typed structs, so every
accepted field must be declared and there is no allowlist to invert.

Neither snapshot version constant is bumped; both stay at 1.

Refs gopherstack-gt9o

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…aconvert parity updates

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eserved word

services/rds/PARITY.md has both a genuine top-level `leaks:` section at column
0 and an indented `leaks:` family entry. matchEntry rejected any line whose key
was reserved regardless of indent, while isBlockTerminator only accepts a match
at column 0 — so the indented entry fell through both, counted as neither, and
was dropped from the families total. Since 29d3136 it also produced a warning
on every run, about a line that is not malformed.

matchEntry now rejects a line only when isBlockTerminator would claim it. That
ties the two functions together by construction, so no line can fall through
both, and it generalises: the same collision was waiting for any service naming
a family `gaps`, `protocol` or `gaps`-adjacent.

Indentation is the only workable discriminator here. The obvious alternative —
that a section header carries no brace on its own line — is false: rds's real
`leaks:` header is written `leaks: {status: ..., note: "..."}`, brace-identical
to a family entry.

A 0-space entry whose key is reserved is still read as that key's section
header. At column 0 the two forms are genuinely indistinguishable, and
parseFrontmatter re-reads the line as the scalar field, so the content becomes
LeaksStatus rather than being lost. The existing tolerance for 0-space entries
with non-reserved keys (services/mwaa, services/rekognition) is unaffected —
isReservedKey never applied to those.

Families across all 159 PARITY.md files go 1016 -> 1017, and the false warning
count goes 1 -> 0.

Closes gopherstack-jw5s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…difyClientProperties wiping the others

Continues the stale-pin sweep. Both services were audited against an older SDK
than go.mod pins — the cache still holds ssoadmin@v1.38.0 and workspaces@v1.68.3
alongside the pinned v1.43.1 and v1.73.1, and the fields in question do not
exist in the older ones.

The workspaces half turned up a bug the issue did not mention:
ModifyClientProperties replaced the whole stored struct on every call, so
setting one property silently cleared every other. The real operation is a
partial update. It now merges, leaving an omitted field at its previous value.

ClientExperiencePolicy (types.go:269) and LogUploadEnabled (:275) are both
threaded; the latter was unwired too. ClientExperiencePolicy is deliberately
unvalidated: unlike its neighbours LogUploadEnabled and ReconnectEnabled, which
have generated enum types with Values(), it is a bare *string with no @enum
trait. The FORCE_CLASSIC/FORCE_UI_2026/USER_CHOICE values in its doc comment
are illustrative, so rejecting anything else would be stricter than AWS.

ssoadmin: PermissionSetsEnabled (api_op_DescribeInstance.go:77) is stored as a
*bool, so an instance that never set it stays nil and is omitted rather than
reported as a fabricated false. AWS documents that it cannot be disabled once
enabled, but that is prose rather than an SDK-pinned constraint, so both values
are accepted verbatim.

InstanceMetadata.Regions is populated from real AddRegion state via ListRegions.
PrimaryRegion is modelled shape-only and never set: nothing in this backend can
source it, since RegionMetadata.IsPrimaryRegion is always false here.

Neither snapshot version constant is touched — workspaces stays 1, ssoadmin
stays 2.

workspaces' clientProperties map is pre-existing ephemeral state that was never
in backendSnapshot, so the new fields inherit that gap rather than creating one.
A round-trip test was written, confirmed to fail against that pre-existing
non-persistence, and reverted rather than expanding scope; recorded in
PARITY.md instead.

Refs gopherstack-gt9o

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…oadmin/workspaces fields

rds picks up its 'leaks' family row, which the parser had been dropping on a
reserved-word collision. Operations badge 6169 -> 6172.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both fields arrived in the SDK after this service was audited (types.go:52 and
:550 at the pinned v1.53.5) and were silently omitted from every response.

Unlike most of this sweep these are not caller-supplied — they are derived from
the org tree gopherstack already models, so leaving them unset would have been
the wrong answer. Getting the format wrong would be worse than omitting them
though, and the Go doc comments pin nothing ("The paths in the organization
where the account exists"), so the format comes from the AWS API Reference
example responses and the published regex, cited in buildPath's comment:
o-<org>/r-<root>/(ou-<id>/)*<ownID>/ — org, root, ancestor OUs top-down, the
resource's own id, trailing slash.

Paths is plural but Organizations is a strict single-parent tree — moving an
account between roots is an error, MoveAccount takes one source and one
destination, and this backend stores a single accountParent. It therefore
always returns exactly one path and never fabricates a second.

Populated on the seven operations that actually return these types, found by
searching for the types rather than trusting the gap note: DescribeAccount,
ListAccounts, ListAccountsForParent, DescribeOrganizationalUnit,
UpdateOrganizationalUnit, ListOrganizationalUnitsForParent and
CreateOrganizationalUnit. ListChildren and ListParents are excluded because
they return summary types that carry no path in real AWS.

The ancestor walk is bounded, so a cyclic or dangling parent chain cannot spin:
it returns no path at all rather than a partial or invented one. That state is
unreachable through the API and only constructible via a corrupted snapshot,
which is how the test builds it.

Nothing new is persisted. Both fields are json:"-" and computed at read time
from state that was already stored, so organizationsSnapshotVersion stays at 1.

Refs gopherstack-gt9o

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NetworkType arrived after this service was audited and was dropped end to end —
absent from the inputs, never echoed, error not in the lookup table.

DBCluster.NetworkType (types.go:236) is settable on CreateDBCluster
(api_op_CreateDBCluster.go:171) and ModifyDBCluster (:136), so it is accepted,
stored and echoed. It defaults to IPV4 because the SDK documents that as the
default in as many words — "IPV4 – ( the default )" — not because a default
seemed reasonable.

DBInstance.NetworkType (types.go:764) has no input member on either
CreateDBInstance or ModifyDBInstance; the SDK says it is inherited from the DB
cluster, so that is where this takes it from rather than inventing an option
the API does not offer.

NetworkType is a bare *string with no entry in types/enums.go, so any value is
accepted. Restricting it to IPV4/DUAL would be stricter than the real API.

Two things are deliberately left inert, and both would have been easy to fake:

SupportedNetworkTypes on DBSubnetGroup (types.go:945) and
OrderableDBInstanceOption (types.go:1291) is modelled on the wire in its real
member-wrapped list shape but never populated. Subnets here are opaque ID
strings with no CIDR data, and the orderable-options catalog is static, so
there is no honest basis to say which network types are supported. A fabricated
capability list is worse than an absent one, and a test asserts it is genuinely
absent from the XML rather than present and empty.

NetworkTypeNotSupportedFault (errors.go:1417) is not added to the error lookup
table. Real Neptune raises it when a requested network type conflicts with the
subnet group's actual CIDR support — a condition this backend cannot detect.
Inventing a rejection so the error had something to raise would be the
more-restrictive-than-AWS bug class.

neptuneSnapshotVersion stays at 1; the new fields are additive omitempty.

Refs gopherstack-gt9o

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ates

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…berately never populated

The field arrived after this service was audited (types.go:803, :969, :6079 at
the pinned v1.73.4) and was missing from GetAutomationExecution,
DescribeAutomationExecutions and DescribeAutomationStepExecutions.

It is modelled and left permanently unset, which is the honest outcome rather
than a shortcut. Real SSM sets it when its engine detects a non-critical issue
mid-run; StepExecution's doc adds "Present only if the step status includes a
warning". There is no such status in the enum, so it is engine-detected, not a
modelled transition. This backend has nothing to detect: completeAutomationLocked
drives every step to Success unconditionally, and automationStatusFailed is
declared in store.go but never assigned anywhere — there is no failure, timeout,
retry or degraded path to report a warning from.

Inventing a warning string would put text in front of an operator that no real
condition produced. Same call as apigatewayv2's failOnWarnings on this branch,
which is validated but documented as inert because the emulator generates no
import warnings.

The test asserts the field is genuinely absent from the raw response body, not
merely empty when parsed — those are indistinguishable through the SDK, and
omitempty is the only thing separating them.

ssmSnapshotVersion stays at 1.

Refs gopherstack-gt9o

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…PC config

Both fields arrived after this service was audited and were read nowhere.
Connector.IpAddressType (types.go:720) is set by CreateConnector
(api_op_CreateConnector.go:86) and UpdateConnector (:80), and echoed on
DescribeConnector. WebAppVpcConfig (:2745) and UpdateWebAppVpcConfig (:2648)
carry their own, set through Create/UpdateWebApp's EndpointDetails.

Two absences here are real AWS behaviour and are deliberately preserved, with
tests pinning them so a later pass does not "fix" them into existence:

DescribedWebAppVpcConfig (types.go:1417) has no IpAddressType and no
deserializer case for one, so a client sets it and cannot read it back. The
describe output is untouched. This is the same asymmetry PARITY.md already
records for SecurityGroupIds.

ListedConnector (types.go:1897) carries only Arn, ConnectorId and Url, so
ListConnectors keeps omitting the field.

Neither enum is validated. Both are IPV4/DUALSTACK, but the sibling
Server.IPAddressType — the same enum shape — is threaded through servers.go
with no validation, while EndpointType, Domain and TLSSessionResumptionMode in
that same file do validate. Following the established local precedent for this
exact shape rather than inventing strictness AWS may not have.

The web-app value is stored despite never being echoed: it round-trips through
Snapshot/Restore and is readable from the backend struct, matching how
SecurityGroupIDs is already handled here.

transferSnapshotVersion stays at 1.

Refs gopherstack-gt9o

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Witness Patrol added 30 commits August 12, 2026 23:58
…y send

Query protocol resolves parameters by exact-string map lookup, so each of
these silently yielded empty and still returned 200.

docdb and neptune RestoreDBClusterFromSnapshot both read
DBClusterSnapshotIdentifier; the required key is SnapshotIdentifier.
DBClusterSnapshotIdentifier is correct on CreateDBClusterSnapshot and
DescribeDBClusterSnapshots, which is likely how it leaked here.

elbv2 ModifyTrustStore read a Name parameter that does not exist on
ModifyTrustStoreInput and implemented a rename AWS does not offer. Removed;
the op is now a validating lookup. The two required S3 bundle fields stay
unwired because TrustStore has nowhere to put them and CreateTrustStore does
not set them either - fixing one side only would be worse. PARITY.md:72 drops
from 'wire: ok' to 'wire: partial'.

ses SetReceiptRulePosition invented a numeric Position. The real field is
After, naming the rule to sit behind; absent means move to first. The old
test passed vacuously - it already sent After, which the handler ignored, and
only asserted HTTP 200.

Every fix was checked by reverting it and confirming the new test fails.

Closes gopherstack-einq
…gaps

gopherstack implements 55 Redshift Serverless operations against an SDK the
module graph never pinned - the only copy was one downloaded standalone into
a dev machine's cache, which is what every audit of this surface had been
reading. Pinned v1.38.5: it shares a release timestamp with the already-pinned
redshift v1.65.4 and redshiftdata v1.43.4, so it comes from the same upstream
batch rather than being the newest available.

Re-verified every prior finding against the now-pinned source. Nothing
changed - the cached copy happened to be the same version - but that was luck,
not a guarantee.

TestSDKCompleteness_Serverless gives go mod tidy a real import so the pin
survives, and it immediately surfaced ten operations with no handler at all
(gopherstack-v4wu).

UpdateNamespace's DBName field is gone: the real API has no such member, and
the handler was mutating ns.DBName from it, so gopherstack accepted a rename
that would fail against AWS.

AdminUserPassword and RedshiftIdcApplicationArn are accepted and explicitly
discarded, following the convention classic Redshift already uses for
MasterUserPassword. A test asserts the literal secret never appears in a
response body. MaintainIntegration and ActivateCaseSensitiveIdentifier are
modeled but inert - no integration state, no query execution to gate.

The five filter gaps genuinely filter, each proven against a narrowed
multi-item result. OwnerAccount compares against the real account ID rather
than being a no-op.

Closes gopherstack-0w2p
Closes gopherstack-8v8v
Closes gopherstack-mbcq
AssumeRole never read SerialNumber or TokenCode (both optional, sts v1.45.4
api_op_AssumeRole.go:281 and :349, wire keys confirmed at serializers.go:929
and :946), and aws:MultiFactorAuthPresent was unmodeled, so a trust policy
requiring MFA was silently satisfied by a caller presenting none.

GetSessionToken in the same service already validated MFA properly. Its four
inline checks are now a shared validateMFAFields helper used by both, rather
than a second mechanism.

Enforcement, not just parsing: conditionOperatorHolds gained a bool operator
case, and the key is threaded through both the Principal-aware evaluator and a
standalone check mirroring the existing ExternalID pattern.

Scope stated honestly: neither op verifies the TOTP, since there is no
shared-secret store. MFA present means a well-formed pair was supplied - the
same scope GetSessionToken already had.

The deny-without-MFA test was run against the unfixed code first and failed
as expected. Error codes come from the operation's already-wired set.

PARITY.md claimed MFA was 'n/a for this op', which was wrong; corrected, with
AssumeRoleWithSAML and WithWebIdentity noted as genuinely out of scope - AWS
has no such members on those.

Closes gopherstack-41fl
…st-store fields

docdb's cluster handler had been copied from neptune. Three consequences,
all against pinned docdb v1.51.4:

DeleteDBCluster read FinalDBClusterSnapshotIdentifier; the real key is
FinalDBSnapshotIdentifier, so a client asking for a final snapshot got none
and no error.

CreateDBCluster read DatabaseName and EnableIAMDatabaseAuthentication, which
exist on neptune and nowhere in docdb's API - fabricated on the request side
and, for IAMDatabaseAuthenticationEnabled, on types.DBCluster too. Removed
rather than documented, following the redshift-serverless phantom-field
precedent: there is no real shape to model inertly. The DatabaseName slot
survives as a blank parameter so cloudformation's positional call site is
untouched.

FailoverDBCluster ignored the real optional TargetDBInstanceIdentifier that
neptune handles. Wired, with a backend-internal WriterInstanceID so
IsClusterWriter reflects the promoted member.

A survey of docdb's other families against neptune-only vocabulary found no
further drift - the contamination was confined to the cluster files.

elbv2 CreateTrustStore and GetTrustStoreRevocationContent never read their
required members. Both wired; ModifyTrustStore's S3 fields wired too rather
than fixing one side of the same model. RevocationIdNotFound was missing from
the error mapping table, so an unknown revocation 500'd instead of 400'ing.

PARITY.md lines 58, 69 and 72 claimed more support than existed, including a
gaps note asserting RevocationIdNotFound validation that did not exist yet.
Corrected; it is true now.

Closes gopherstack-xou3
Closes gopherstack-hl3h
…ps dropped

elasticache never read ApplyImmediately on seven ops or
CustomerNodeEndpointList on two; no backend signature had a parameter for
either. Reading the SDK's own doc comments changed the fix: for five of the
seven, AWS states ApplyImmediately=false is not supported and true is the only
permitted value, so the honest implementation validates and rejects false
rather than pretending to defer. For ModifyGlobalReplicationGroup and
RebalanceSlots, AWS cannot defer to a maintenance window and this backend has
no PendingModifiedValues for global groups, so the flag is accepted and
documented as not a timing gate. CustomerNodeEndpointList has no output echo
on real AWS either, so it is enforced as required-field validation instead of
being fabricated into a response.

ses SendRawEmail ignored Destinations, taking recipients only from the raw
message's To: header - so a Bcc recipient, which by definition is absent from
the headers, was silently dropped. When Destinations is supplied it forms the
SMTP envelope and takes precedence; absent, the header parse stays the
fallback. Addresses not visible in To or Cc are Bcc by definition.

List members are Destinations.member.N and CustomerNodeEndpoints.member.N,
1-based, confirmed against the SDK's query array encoder rather than assumed.

Every new test was run against the unfixed code first and failed.

Closes gopherstack-9kw0
Closes gopherstack-x0sl
…ilently

Only four condition keys are ever populated in this evaluator - sts:ExternalId,
aws:PrincipalArn, aws:MultiFactorAuthPresent, and the per-issuer aud/sub pair.
None is numeric, timestamp, source-IP or binary valued, so Numeric*, Date*,
IpAddress and BinaryEquals have nothing to compare against and stay
unimplemented as a structural gap rather than deferred work.

Null and the Arn family (ArnEquals/ArnLike and their negations, which AWS
documents as behaving identically) do have keys to act on, and are now
enforced. Null runs before the unknown-key fallback, since otherwise
Null:false would be defeated by the very fallback it is meant to detect.

Fail-open is kept for unmodeled operators and unknown keys - the evaluator's
own docstrings already record enforce-only-what-is-known as deliberate, and
flipping it would start denying working AssumeRole calls whose policies carry
incidental unsupported conditions. But it is no longer silent: both branches
now log at WARN naming the operator or key, so the gap is discoverable at
runtime. PARITY.md flags the global posture as wanting human sign-off.

IfExists stripping was checked against every operator and is correct: it only
affects absent-key behaviour, decided once at the !known check. Null is AWS's
documented exception and bypasses that check.

Every new operator has a deny case, and the deny cases were run against the
old switch to confirm they fail there.

Closes gopherstack-yg95
… and close their wire gaps

PARITY.md had this family marked partial - Domain, App and UserProfile were
never wire-audited - so it was the largest genuinely uncovered surface. All 19
of its anonymous inline request structs are now named types, which is what
makes them visible to the wire-sweep tooling at all.

CreateDomain silently dropped DefaultUserSettings, a required member with no
field on the struct. CreateApp had no SpaceName, the documented alternative to
UserProfileName, so a Space-only client could never create an app despite
Spaces being modeled. The four List ops modeled none of their MaxResults,
SortBy, SortOrder or name filters - all accepted and ignored, now real.
UpdateDomain only bumped LastModifiedTime; it now updates nine fields.

Conversion surfaced a second bug on its own, as it did for ListAssociations:
store_domain.go's appsStore keyFn closures were a stale hand-written copy of
appKey that omitted SpaceName, so once SpaceName was threaded through,
CreateApp and DescribeApp computed different keys and a Space-owned app 404'd
straight after creation. Both closures fixed.

Deeply nested config - ResourceSpec, UserSettings, the Space and Domain
settings blocks - stays opaque json.RawMessage passthrough per the existing
convention, documented rather than fabricated.

343 inline structs remain elsewhere in sagemaker; PARITY.md records that
explicitly as the next scope rather than implying coverage.

Refs gopherstack-oc9v
…five as fabrication

TestSDKCompleteness_Serverless carried all ten missing ops in a notImplemented
allowlist, so the gap was tolerated rather than enforced. The allowlist is now
the five reservation ops only.

UpdateSnapshot completes Create/Get/List/Update/Delete symmetry - a client
could not change a snapshot's retention period. GetTrack and ListTracks return
a static two-entry catalogue, following the precedent classic Redshift's own
DescribeClusterTracks already set for the same bounded AWS enumeration.
UpdateLakehouseConfiguration writes real Namespace.CatalogArn and
LakehouseRegistrationStatus, both present on types.Namespace but absent from
this backend until now. GetIdentityCenterAuthToken mints a synthetic token
after checking every named workgroup exists, matching its classic sibling's
honest limitation - and adding an FK check that sibling does not do.

DryRun on UpdateLakehouseConfiguration returns DryRunException. It was first
modeled as a 200 with a preview; the deserializer's own doc comment said
otherwise.

The reservation family stays unimplemented. ReservedNode is a real precedent
for a curated offering catalogue, but it keys off NodeType, a small real
hardware SKU list, whereas ReservationOffering is commercial pricing AWS
derives from live rate cards with no SDK-enumerable anchor and no backend
state here. That crosses from emulation into invention. PARITY.md records the
decision and the counter-argument so the next audit can revisit it.

Closes gopherstack-v4wu
Picks up today's PARITY.md changes across ce, cloudfront, elbv2, fsx, rds,
s3, sagemaker and sts, and replaces the mediatailor entry that was mirrored
by hand when gendocs was outside that agent's edit scope - the generated text
carries the full evidence trail the hand copy had trimmed.

Operations badge 6172 -> 6180.
…ic family

PARITY.md graded iot A with one family marked partial, so this pass scoped
there rather than re-deriving 24 verified families.

UpdateFleetMetric dropped indexName, aggregationType, aggregationField,
queryVersion and unit. Converting its inline request struct to a named type
prompted diffing the whole family, which surfaced a sixth gap nobody had
tracked: CreateFleetMetric was also missing aggregationField and
aggregationType, both required members. FleetMetric never modeled them, so
Describe and List could not have returned them even if a caller had worked
around the drop.

Worth noting why that one hid: CreateFleetMetricInput was already a named
type, so it was never in the inline-struct blind spot - it simply sat in the
large unverified-absences tier no sweep got to. An A grade and a named type
are not evidence of a field-level diff.

UpdateCustomMetric and UpdateDimension were already field-complete; converted
for tooling visibility only.

PARITY.md attributed the UpdateFleetMetric gap to gopherstack-5wj0 in five
places. That issue is an unrelated closed sweep-tracking item and the string
FleetMetric appears nowhere in bd - the gap was never tracked at all. Citations
removed rather than propagated.

76 of iot's 79 inline structs remain, recorded explicitly.

Refs gopherstack-oc9v
…e-the-parameter gaps

Each of these accepted a parameter and ignored it, with nothing recording
whether that was a decision or an oversight. All nine now either work or say
why they cannot.

Implemented: both DescribeOrderableDBInstanceOptions now filter their static
catalogues by Engine, EngineVersion and DBInstanceClass; neptune
CreateDBInstance rejects an Engine other than neptune, following the
elasticache precedent where AWS documents a single legal value; the two
elasticbeanstalk EnvironmentInfo ops and ValidateConfigurationSettings
validate InfoType and check the environment or application exists;
CreatePlatformVersion requires PlatformDefinitionBundle; elb
DescribeAccountLimits paginates using the marker helpers
DescribeLoadBalancers already had.

neptune DescribeValidDBInstanceModifications was worse than filed. Besides
ignoring its required DBInstanceIdentifier, it emitted a fabricated
ValidProcessorFeatures>AvailableProcessorFeature list of instance classes.
That element does not exist in the real deserializer, so a real client's
decoder silently skipped the entire payload. The genuine response type carries
one field, Storage, documented as not applicable to Neptune - so the correct
output is empty. The deleted tests asserting db.r5.large are the evidence it
was wrong all along.

Documented as structural rather than faked: EnvironmentInfo returns no log
content because this backend models no EC2 instances, and CreatePlatformVersion
validates its bundle but cannot fetch S3 or run a build pipeline. Neither
response type has anywhere to put the value.

Closes gopherstack-uhsb
…scarded

CreateModelCustomizationJob read five fields and dropped three required ones -
RoleArn, OutputDataConfig and TrainingDataConfig - so a job was created with no
IAM role, nowhere to write output and no training data. The two configs are
modeled as real nested structs rather than flattened, validated, and echoed on
Get and List. TrainingDataConfig's recursive RequestMetadataFilters union stays
inert and documented: there is no invocation-log pipeline behind it.

CreateInferenceProfile dropped the required ModelSource, so a profile had a
name and no model. Stored and echoed as the required Models list; this backend
does not expand a system profile into per-region models, so that list carries
one entry.

appstream CreateApplication dropped required IconS3Location and
InstanceFamilies end to end.

Error codes came from each operation's own declared switch. bedrock's two
declare ValidationException. appstream CreateApplication declares no
validation-style exception at all - unlike CreateFleet and its siblings, which
declare InvalidParameterCombinationException - so the service's existing
convention does not transfer, and structurally-invalid input returns
SerializationException, matching how this repo already handles it at the CBOR
transport layer.

All three services were graded A and audited within the last three weeks.
PARITY.md entries claiming wire: ok for these ops are corrected.

Closes gopherstack-ii4c
…r whole request

The ticket described three dropped required members. Each turned out to sit on
top of a worse failure.

PutResourcePolicy did not merely mis-tag Policy for PolicyDocument - its XMLName
root was ResourcePolicy where the real root is PutResourcePolicyRequest. A root
mismatch makes xml.Unmarshal return an error, and the handler discarded it with
_ = xml.Unmarshal(...), so every field including ResourceArn was zeroed for any
real client. Behind that, routing matched GET/POST/DELETE on one shared path
while real clients POST to three distinct paths - probing the pristine handler
returned 404 NoSuchOperation for all three. Get and Delete are POSTs too,
despite the names. ErrResourcePolicyNotFound emitted an invented
NoSuchResourcePolicy; all three ops declare EntityNotFound.

CreateRealtimeLogConfig had the same root-tag class of bug, so Name, Fields and
SamplingRate were dropped alongside the reported EndPoints. Its response also
needs RealtimeLogConfig as a wrapping child element rather than fields at the
root, so a real client's output stayed nil even once parsing was fixed. Get and
Delete POST to their own paths and Update PUTs to the base path; the old table
matched /realtime-log-config/{id} for all three.

CreateVpcOrigin and UpdateVpcOrigin were as filed - Arn, HTTPPort, HTTPSPort and
OriginProtocolPolicy now parsed, stored and echoed.

Every fix is covered by a real aws-sdk-go-v2 client round-trip, which is what
catches the response-nesting bug: the SDK refuses to populate the field from a
flat body no matter what the raw XML contains.

PARITY.md corrected, including a family note that had claimed resource-policy
was fine.

Closes gopherstack-nfka
…one phantom capability

Handling the discarded xml.Unmarshal error is the point: encoding/xml zeroes
the struct when the root element does not match XMLName, so these were
discarding every field and returning success.

Three genuine wipes. UpdateVpcOrigin expected an UpdateVpcOriginRequest root
where the real body is VpcOriginEndpointConfig itself with no wrapper - and
PARITY.md had already marked this op fixed while it was still broken.
UpdateTrustStore expected TrustStoreConfig with Name and Comment fields; the
real root is CaCertificatesBundleSource and the real op has no Name or Comment
member at all, so that struct also exposed a rename AWS does not offer.
GetBucketAbac re-parsed its own stored body under AbacConfiguration instead of
AbacStatus.

The other 29 sites had correct roots; their errors are now handled rather than
discarded, which is what would have made these three findable.

Two more dead routes, in a service the route audit had to skip because it was
being edited: UpdateDistributionWithStagingConfig matched /staging where real
clients PUT to /promote-staging-config with the staging id as a query param,
and ListDomainConflicts matched a singular /domain-conflict against the real
plural. Both 404'd every real call.

GetBucketAbacOutput turned out to be httpPayload-bound, so the response body
must be the bare AbacStatus document. A same-named but dead generated
deserializer in the SDK source pointed the other way; only driving both ends
through the real client settled it.

Left for a wider pass, recorded in PARITY.md: UpdatePublicKey,
UpdateFieldLevelEncryptionConfig and UpdateFieldLevelEncryptionProfile are
routed to their bare-id paths where real AWS PUTs to a /config suffix. All
three 404 today; the fix touches shared route helpers and many tests.

Closes gopherstack-ob1g
…ache-behavior shapes

bedrockagent Get and DeleteKnowledgeBaseDocuments decoded documentIds as a
list of strings. The real member is documentIdentifiers, a list of objects -
DocumentIdentifier{DataSourceType, Custom, S3} - so the slice was always empty
and Delete returned 202 having removed nothing. Now modeled as the real nested
union, keyed off the type-appropriate sub-object.

IngestKnowledgeBaseDocuments had the same family bug on another axis: it read
a top-level documentId that does not exist on the wire at all, where identity
actually lives inside content.custom.customDocumentIdentifier.id or
content.s3.s3Location.uri. ListKnowledgeBaseDocuments checked clean - it has
no identifier field to get wrong. Also replaced a fabricated DELETED status
with DELETING, which is in the real enum.

Why the prior pass missed this is the part worth remembering: it added
TestKBDocumentsRealWireRouting, whose fixture sent the same invented shape the
handler expected. The routing it verified was genuinely correct. The test
could never have failed on the body.

lightsail CreateDistribution dropped the required DefaultCacheBehavior, which
the SDK client-side-validates, and had no cache-behavior fields anywhere in
the model. UpdateDistribution shared the gap undisclosed, accepting only
CertificateName and IsEnabled. Both now carry DefaultCacheBehavior,
CacheBehaviorSettings, CacheBehaviors and the previously-dead
ViewerMinTLSVersion. Create's six positional arguments became a request struct.

Error codes came from each op's own declared set: ValidationException for
bedrockagent, InvalidInputException for lightsail, whose catalog has no
ValidationException at all.

Left inert and disclosed: UpdateDistribution.Origin, and SetupInstanceHttps's
EmailAddress, which appears nowhere in the SDK outside its input struct so no
read API could echo it.

Closes gopherstack-wzwn
Closes gopherstack-jigw
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.

1 participant