Chore/parity upgrade - #2414
Conversation
|
Important Review skippedToo many files! This PR contains 2742 files, which is 2642 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. Usage-priced reviews support at most 300 files. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (2742)
You can disable this status message by setting the |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
📊 Code Coverage Report
Tip This project maintains a minimum coverage threshold of 85%. Maintain or improve coverage on new code to ensure long-term stability. Last updated: Sun, 09 Aug 2026 02:21:45 GMT |
| // ec2.Instance at all -- matches real RunInstances failing atomically. | ||
| var instanceIDs []string | ||
| if outpostArn != "" { | ||
| instanceIDs = make([]string, count) |
| // like real Cognito, which must derive and store an SRP verifier at password-set time | ||
| // since it never stores the plaintext password itself. | ||
| func srpComputeX(poolName, username, password string, salt *big.Int) *big.Int { | ||
| inner := sha256.Sum256([]byte(poolName + username + ":" + password)) |
…ed shapes ListWirelessDevices accepted six filters and ignored all of them, so a narrowed query returned every device. They arrive as query parameters, not body fields (iotwireless@v1.59.4 serializers.go:6439). Filters now intersect: the SDK does not define a combining rule, and AND matches how every other narrowing List filter here behaves. An absent or empty value means "not requested", matching the SDK only sending the parameter when the pointer is set; an unmatched value returns an empty list rather than an error. DeviceProfileId checks both the LoRaWAN and Sidewalk fields, since AWS applies it to whichever technology the device uses. LoRaWAN, Sidewalk, Update and TraceContent were opaque map[string]any and are now real types. LoRaWAN is not one shape: the create and get form (types.go:723), the narrower update form (types.go:1211) and the list-entry form carrying only DevEui (types.go:1034) are distinct, as are the gateway and gateway-task variants, and each call site now uses the right one. Sidewalk splits the same way, with the get response a superset of create. Go identifiers were renamed for revive, but every json tag keeps the SDK's exact wire key -- AbpV1_0_x, DevEui, DeviceProfileId. Splitting the shared device converter caught a latent regression: narrowing it for the list entry would have quietly given GetWirelessDevice the list's truncated LoRaWAN and Sidewalk too. UpdateWirelessDevice and UpdateWirelessGateway now merge field by field against each Update type's real field set, replacing a blanket key merge over untyped maps. TraceContent's fields are not optional in the SDK, so a client cannot express leave-this-alone and an update replaces it wholesale. ServiceProfile, DeviceProfile, FuotaTask and MulticastGroup keep their untyped LoRaWAN and Sidewalk fields; those are filed separately. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rsions UpdateAgentActionGroup, DeleteAgentActionGroup, UpdateAgentCollaborator, DisassociateAgentCollaborator, UpdateAgentKnowledgeBase and DisassociateAgentKnowledgeBase never got the DRAFT-only agentVersion guard their Create and Associate counterparts already carry, so a caller could mutate or delete a numbered version's snapshot row directly. That was latent until b72533e made those rows real by snapshotting DRAFT's sub-resources into each numbered version. Once the snapshots exist, an unguarded update edits history. Reads are untouched: GetAgentActionGroup and the List ops still accept a numbered version, which is the point of having snapshots. The five remaining IngestionJobStatistics counters stay at zero. The backend discards each document's content and metadata at ingest and keeps no prior-job document set, so there is nothing to diff -- any non-zero value would be invented. PARITY.md now says that rather than calling it a to-do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…overrides PutScalingPolicy accepted a PredictiveScalingConfiguration, returned 200, and threw it away, so a caller had every reason to believe predictive scaling was configured when nothing had been stored. It is now parsed and echoed by DescribePolicies: top-level scalars plus all three predefined-metric variants (autoscaling@v1.70.4 types.go:2558, serializer serializers.go:5967). The Customized*MetricSpecification variants are deferred -- each nests the CloudWatch MetricDataQuery math sub-language shared with GetMetricData. MixedInstancesPolicy overrides now carry InstanceRequirements, 24 of its 25 fields (types.go:1263). BaselinePerformanceFactors is deferred; it nests a CPU-family reference list with no analogue elsewhere here. Query flattening was taken from aws/protocol/query's object and array encoders rather than inferred: nested objects join with a dot, non-flat lists always take .member.N. That work exposed a real bug. parseLaunchTemplateOverrides decided the member list had ended by checking only InstanceType, WeightedCapacity and LaunchTemplateSpecification, so an override carrying only InstanceRequirements -- the entire point of attribute-based selection, and what Terraform emits -- looked like the end of the list and silently dropped itself and every override after it. ABANDON on a launching hook now terminates and replaces the instance rather than leaving the group short, reusing the disposition finishTermination already applies, so the replacement is gated by the same hook. AWS documents this as "terminate and replace"; the existing test asserted the group was left empty, which was wrong, and now asserts a distinct replacement instance. Multiple hooks on one transition still arm only the first. AWS documents an ordered chain but exposes no ordering field, and threading it through all four arm sites plus the restore path is left for its own change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six resolvers re-derived their starting value from backend state instead of checking whether an earlier op in the same request had already staged a write, so a PATCH carrying several operations silently kept only one of them. PARITY.md named three; the other three were the same bug. All six now read through the stagedValue helper the earlier sweep introduced. UpdateDomainName had no case in applyResourcePatchOp at all, so every multi-segment path fell through to a guard that rejects anything containing a slash -- accepted, and silently doing nothing. Nested paths under endpointConfiguration and mutualTlsAuthentication now apply; modelling the latter meant adding mTLS, which was absent entirely. certificateArn and regionalCertificateArn are pointers now, so an explicit remove is distinguishable from an absent field. Only the update input changed: the DomainName response and CreateDomainNameInput keep plain strings, so nothing dropped out of a response. The wider pointer-ification this issue asked for turns out to be mostly unnecessary. Checking each resource's documented op support, nearly every other top-level scalar -- across ApiKey, Account, Stage, UsagePlan, Model, RequestValidator, Resource and VpcLink -- is replace-only, so there is no remove to distinguish. The UsagePlan throttle path shape was verified against the same reference and already matches. Two missing-field gaps are recorded rather than fixed, being a different class: DomainName lacks certificateName, policy, routingMode and several others, and UsagePlan has no ProductCode at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…bugs Tags on UsageLimit, SnapshotCopyGrant, HsmClientCertificate and HsmConfiguration, IdcApplication.ApplicationType, ReservedNode's recurring charges and ScheduledAction's next invocations. Tags reuse the service's existing shared helpers rather than a per-resource mechanism, and the list wrapper is Tags>Tag in every case (deserializers.go:44978). Two real wire bugs surfaced while verifying: CreateHsmConfiguration read HsmIPAddress, but the wire field is HsmIpAddress (serializers.go:11722), so a real client's value was dropped. The existing test passed only because it used the same wrong casing. CreateClusterSubnetGroup accepted a VpcId parameter that does not exist -- the real input carries only ClusterSubnetGroupName, Description, SubnetIds and Tags. Removed. The response field is real, but AWS derives it from the subnets' VPC and there is no EC2 cross-reference here to derive it from. RecurringCharges come from the offering's own UsagePrice, so All Upfront yields none and No Upfront yields one hourly charge. NextInvocations are computed by evaluating the stored schedule; the parser is new here rather than shared, since eventbridge's lives in another service package. Its tests caught a bug both copies share: a combined range and step such as 0-30/10 was routed to the range branch, which then failed to parse 30/10 and matched nothing at all, silently. Fixed here by resolving the step's base first; eventbridge still has it and is filed separately. EndpointAccess.VpcEndpoint and IdcApplication.ServiceIntegrations stay empty and are documented as such: the first needs per-interface availability zones and addresses this backend has nowhere to derive, and inventing an endpoint id would fabricate state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ire time matchCronToken tested for "-" before "/", so a combined range and step such as 0-30/10 -- valid AWS cron for "every 10th minute from 0 through 30" -- took the range branch, failed to parse "30/10", and matched nothing at all. No error, just a rule that never fires. NextAfter separately returned the end of its two-year scan window when nothing matched, so an expression that can never fire reported a concrete future time. Both are ported from services/redshift/schedule.go, which fixed the same inherited bugs in cdad5fb, including the missing field-count guards on the range and step matchers. Returning zero needed a caller change. fireDueRule compared the result with Before(tick), and a zero time predates every tick, so a rule that previously never fired would have fired on every tick instead -- the opposite failure. It now treats zero as "no next occurrence". The two schedule implementations are now the same matcher with different wrappers. Extracting them is worth doing, but not here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Registering more than one hook on the same transition armed only one; the rest never fired, and a caller who configured them got no signal they were inert. AWS runs them as an ordered chain -- CONTINUE lets the remaining hooks complete, ABANDON stops them -- but neither PutLifecycleHookInput nor LifecycleHookSpecification carries an order field, and DescribeLifecycleHooks returns an unordered list, so the order is ours to choose. Registration order it is, recorded in a Sequence assigned once per hook and preserved across updates. It is internal: the XML response is now built field by field rather than by type conversion, so nothing of the sort can leak onto the wire by accident. Two data-model additions, both deliberate. LifecycleHook.Sequence carries the order. Instance.LifecycleHookName records which hook currently gates a waiting instance, without which a restore cannot tell whether a group was mid-chain -- rearmPendingWaits now resumes at that hook and only falls back to the first one for snapshots written before this change or a hook since deleted. Both ride inside the existing group JSON, so the snapshot version is unchanged. The sequence counter is recomputed on restore rather than stored. ABANDON still never consults the chain: it goes straight to the terminal effect, including b7d3a84's terminate-and-replace, and the replacement starts the chain again from the first hook. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ignored UpdateAutomatedReasoningPolicyTestCase never received the request body at all -- the route chain did not pass it -- so it echoed the ids back with a 200 and changed nothing. RegisterMarketplaceModelEndpoint likewise never read its body and returned no content. Both now parse what they are given, store it, and return what the SDK expects: the ids for the first, the full endpoint object for the second. Five list ops accepted filters and ignored them. Two of the names in the issue were wrong, and using them would have produced filters that never match: TypeEquals binds to the query parameter "type" and ModelSourceEquals to "modelSourceIdentifier" (bedrock@v1.66.4 serializers.go:6752, :6822). ListCustomModels and ListModelCustomizationJobs turned out to have no filters at all rather than one missing, so both got their full documented set. ModelStatus and ApplicationType had to be modelled first; without them their filters would have had nothing to match against. baseModelArnEquals and foundationModelArnEquals are left out deliberately: CreateCustomModel is a bring-your-own-model import and never records a base model, so accepting those filters would match against data that does not exist. Sorting is only ever by creation time -- both sort-by enums have a single value -- so only the order needed handling. The build-workflow scoping of the ARP sub-resources is untouched. Annotations, scenarios and test results are build-scoped in AWS and policy-scoped here, and correcting it means re-keying storage and rewriting the routes; PARITY.md already records it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…state MLTransform and UserDefinedFunction called tagResource at creation but had no Tags field to store into, so the call silently failed and creation-time tags were lost outright rather than merely unreachable. Both Update ops then replaced the stored record wholesale with the caller's input, wiping any tags that had survived -- neither UpdateMLTransformRequest nor UpdateUserDefinedFunctionInput carries tags on the real wire, because AWS changes them only through TagResource and UntagResource. Tags now exist on both, internal-only like Blueprint and DevEndpoint already were, and Update carries the existing ones forward. The ARN dispatchers in tags.go recognise all four kinds. There is no shared tag-by-ARN dispatcher in pkgs to reuse; ECS solves this with a flat ARN-keyed side map, which does not fit Glue's per-resource inline tags. Workflow.Graph is built from the triggers that actually reference the workflow, with their real actions and predicate conditions as nodes and edges, gated on IncludeGraph as the SDK is. LastRun is the most recent real run, absent until one has happened. Left absent: WorkflowRunStatistics and per-run node execution details, which would need a link from a job or crawler run back to the workflow run that triggered it, and nothing here records one. ml-transform EvaluationMetrics stays unmodelled for the same reason -- no evaluation is ever run. Of the exceptions, only ResourceNumberLimitExceeded on CreateDevEndpoint has a real trigger, against AWS's published limit of 25. ConcurrentModificationException is unreachable while every op holds the backend lock for its duration, OperationTimeout cannot happen in a synchronous in-memory backend, and IdempotentParameterMismatch has no ClientToken on any of the eight inputs that document it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…g them ListAnnotationStores, ListVariantStores, ListAnnotationStoreVersions and ListShares accepted filters and returned the full unfiltered list, so a narrowed query silently gave wrong results. The issue named ListShareVersions, which does not exist in the SDK -- the real operation is ListAnnotationStoreVersions, and its store name is a URI path parameter rather than a body field. The filters themselves all arrive in the JSON body, not the query string; only maxResults and nextToken are query parameters (omics@v1.49.5 serializers.go:5497, 7543, 5608, 7270). Threaded through the same way jxc5 did for RunFilter: a plain filter struct alongside an explicit ids list, matched by a shared helper next to the existing importJobMatchesFilter. Share filters are any-of lists over resource ARN, status and type, with the type derived from the ARN. Reference and read-set import jobs now carry their optional Files sub-object. The imported ones report a content length of zero, which is honest -- this backend stores an empty body for them. The multipart upload completion reports the bytes actually uploaded, which it already tracked. StartRunBatch needed nothing: 041c16c already gave it the real batchRunSettings shape and made it create genuine constituent runs, despite that commit's subject naming only cognitoidp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…real ExecuteStackRefactor flipped status to EXECUTE_COMPLETE and moved nothing, which it could not have done anyway: CreateStackRefactor never parsed ResourceMappings, passing nil to the backend. Both are fixed, and a refactor now validates each mapping, moves the resource between the two stacks' resource maps and records a stack event. ListStackRefactorActions derives its MOVE actions from the mappings rather than inventing them. Failures return errors instead of reporting success. BatchDescribeTypeConfigurations was worse than missing two output fields. TypeConfigurationIdentifiers is a list of structs, each field flattened separately (serializers.go:7114 and :7082), but the handler read TypeConfigurationIdentifiers.member.N with no field suffix -- a key that never appears on the wire -- so it always parsed zero identifiers. Errors and UnprocessedTypeConfigurations were empty because nothing had been parsed to populate them from. OU-targeted stack instances are resolved against the real Organizations backend, which does have a queryable hierarchy, so this did not need inventing an org tree. CreateStackInstances and friends accept DeploymentTargets.OrganizationalUnitIds, require SERVICE_MANAGED with organizations access activated, and record the OU on each instance so ListStackSetAutoDeploymentTargets can group by it instead of falling back to a per-account placeholder. Wired in cli.go after Organizations initialises. AccountFilterType and AccountsUrl are rejected as unsupported rather than accepted and quietly ignored. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
InputAttachment.InputSettings and AudioDescription's codec, normalization, watermark, remix and dash-role fields were accepted in the request JSON and silently discarded -- no struct field existed to hold them, and audioDescriptionOutput being a type alias of AudioDescription made the gap structurally invisible. Both directions now parse and emit. InputSettings turned out shallower than the issue suggested: every sub-shape is flat scalars or a small tagged union, so it is modelled in full -- audio selectors with their four variants, caption selectors with their eight source formats, video selector, network and multicast input settings (medialive@v1.101.4 types.go:4189, 4759). AudioCodecSettings is 7 variants, not the ~20 the issue claimed, and all are flat, so it is complete too. The four remaining unions are left untouched rather than half-modelled: a union whose fields are only partly parsed is worse than an absent one, because a caller cannot tell what survived. VideoCodecSettings alone carries 45 fields for H264 and 43 for H265. None is accepted as a passthrough blob; they are cleanly absent. Output.OutputSettings is the best next pickup, all eleven variants being small, but it pairs with OutputGroupSettings and modelling one half of that pair would be misleading. The round-trip test caught one of its own: an empty union marker written as an empty map vanished under omitempty, which treats it as the zero value. It is a pointer to an empty struct now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An audit of the eight deferred families against sagemaker@v1.263.2 found the same failure everywhere: fields accepted on the wire and then discarded. DescribePipelineExecution never returned ParallelismConfiguration despite the backend already storing it. StartPipelineExecution ignored PipelineVersionId and SelectiveExecutionConfig. CreateExperiment and CreateTrial dropped DisplayName. CreateTrialComponent kept only name and tags, discarding start and end time, status, parameters and both artifact maps. CreateFeatureGroup dropped RoleArn and Description. CreateCluster dropped ClusterRole and VpcConfig. DescribeLabelingJob stored tags and never returned them. TrialComponent's status was serialised as a bare string; the real shape is an object of PrimaryStatus and Message (types.go:23735). A test asserting the string form was itself wrong and is corrected. InferenceRecommendationsJob had no InputConfig field at all, though it is required on both create and describe; it is carried opaquely, matching how this service already handles blobs it does not interpret. CreateAutoMLJob's InputDataConfig is now typed through AutoMLChannel and its S3 data source. Lineage and hub audited clean. Left for follow-up, deliberately not rushed: feature store's three config blocks, six nested cluster types, and pipeline definitions held in S3, which needs a real cross-service fetch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…as V1 CreateAutoMLJobV2 and DescribeAutoMLJobV2 were routed to V1's handler, so a V2 request was parsed as if it were V1 and its required AutoMLJobInputDataConfig was dropped on the floor. 32d6369 recorded that field as not existing in the SDK; it does, on CreateAutoMLJobV2Input:91, as []AutoMLJobChannel -- a different element type from V1's InputDataConfig, which carries TargetAttributeName and SampleWeightAttributeName that V2's does not. The two versions diverge too far to share a handler: beyond the renamed required input, V2 requires an AutoMLProblemTypeConfig union V1 has no equivalent of and adds compute, data-split and security config, while V1 has AutoMLJobConfig, ProblemType and GenerateCandidateDefinitionsOnly that V2 drops. Separate handlers, one store -- job names are unique across both. That split exposed a second leak: V1's Describe marshalled the shared struct directly, so describing a V2-created job through the V1 op would have emitted V2-only fields. Both Describes now build explicit response maps. AutoMLProblemTypeConfig is carried opaquely rather than half-modelled; it is a five-member union with large nested configs, and its discriminator is derived from the serializer's wire key rather than guessed. The flat types around it are modelled properly. Feature groups gain their online, offline and throughput store configs. DescribePipeline accepts PipelineVersionId, erroring on an unknown version rather than quietly returning the current one, and derives LastRunTime from real executions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
DAX, Detective, GuardDuty, Transfer, CognitoIDP, AppConfig, CodeCommit,
ServiceDiscovery and MemoryDB resources tagged through their own APIs were
invisible to GetResources and their ARNs always failed TagResources with
InvalidParameterException. Forty-five of roughly ninety services are wired
now.
Deriving the resource type from the ARN needed care in three places, and
guessing would have produced filters that silently match nothing. DAX builds
its cluster ARNs under cache/, not cluster/. Cognito's namespace is
cognito-idp. CodeCommit repositories carry a bare name with no type segment
at all, so they take a constant like SQS and SNS do.
GuardDuty, Transfer and AppConfig nest sub-resources under their parent --
detector/{id}/filter/{id} and the like -- which the flat derivation would
have collapsed onto the parent type, so they share a new nested helper
alongside the existing wafv2 special case.
Every service added has a subtest that tags through its own API and reads the
resource back from the tagging backend filtered by the derived type; without
that it does not count as wired.
s3control stays blocked: its taggable ARNs live under the s3 and
s3-object-lambda namespaces, which the one-namespace-per-service dispatch
cannot express.
The issue and PARITY.md both said eleven services were wired. Thirty-six
already were, from sweeps that never updated the docs; both now match the
code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
extractOutputGroups and extractEncoderOutputs read only names and the description references, so any outputGroupSettings or outputSettings in a CreateChannel body was accepted and thrown away. Both unions now round-trip in full: eleven variants each, covering archive, HLS, MS Smooth, MediaPackage, Multiplex, RTMP, SRT, UDP, CMAF ingest, frame capture and MediaConnect router (medialive@v1.101.4 types.go:6827 and :6764). They were taken together deliberately. An output group's settings and its outputs' settings describe the same delivery mechanism, so modelling one without the other would misrepresent what a channel round-trips. Closing them out meant modelling the containers they reference too -- M2tsSettings alone is around 48 fields and is shared by three container types -- along with the HLS settings and CDN variants, key provider, DVB tables and the MediaPackage v2 pair. Caption destinations and the video codec union are deliberately untouched rather than started and abandoned. They remain cleanly absent. Two variants carry no fields at all, and an empty marker written as an empty map disappears under omitempty; both use a pointer to an empty struct, with assertions that they survive the round trip. ConnectedRouterInputs is skipped -- the SDK documents it as deprecated and unused. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e fields Auditing the thirteen families that had only ever been checked for stubs turned up two shapes that were wrong on the wire, not merely incomplete. ListIAMPolicyAssignmentsForUser wrapped its items under IAMPolicyAssignments. The real output field is ActiveAssignments, carrying a different and narrower type -- ActiveIAMPolicyAssignment, just a name and a policy ARN (api_op_ListIAMPolicyAssignmentsForUser.go:60). A real client deserialised nothing at all from this op. RefreshSchedule's StartAfterDateTime was a string; the wire carries epoch-seconds as a JSON number in both directions (serializers.go FormatEpochSeconds). Writes silently became empty and reads would have failed a real client's parser. Five fields were accepted and discarded: VersionDescription on template and theme create and update, the four Include flags on StartAssetBundleExportJob, and OAuth client tags, which went into a generic passthrough bag instead of the tag helper its sibling families use -- so they never reached tag state and leaked back out as a field the real type does not have. Three response fields were simply missing: RefreshSchedule's top-level Arn, AwsAccountId on a described assignment, and UserName on a self-upgrade request. IdentityPropagationConfig, Automation, DashboardSnapshotJob and Flow audited clean. Two Topic findings recorded in PARITY.md were already fixed and the notes were stale; corrected. VPCConnection.NetworkInterfaces stays absent. There is no ENI provisioning here to derive an interface id, availability zone or status from, and inventing them would be fabrication. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…il details The recommendation type was a value the API does not define, so a real client would never have recognised what it got back. Two required fields were missing from that response entirely, and a third optional one, all of which the backend already held. Generating a recommendation also accepted any finding id at all, including ones that do not exist; it resolves the finding now and refuses unknown ones with the error the read already models. Starting a policy generation read only the principal and discarded the trail configuration beside it -- the role, the trails, the time window. That is stored now and echoed back on the read, in the shape the API returns it. The generation status also used a value the real enum does not have. Nothing assigns it today, since generation completes at once here, but it would have been wrong the moment anything did. Still absent: the recommended steps and the generated policy statements themselves. Both need analysis over activity this backend does not record, and inventing either would be worse than leaving them empty. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… use The conflict error names this case in its own documentation, and a backend holding one account holds enough to detect it -- comparing the requested address against the current one is a comparison, not a simulation. Both operations that model the error now raise it. The other three items stand as recorded, each for a different reason. Targeting another account is a missing backend model rather than a dropped field: the identifier is read and validated exactly where the API requires it, there is simply no second account to route to. The enabling and disabling states are present and match, and no response carries anything a caller could catch disagreeing, so completing at once contradicts nothing. Denied and throttled responses need a request-authorisation model that exists nowhere here. A sweep of every enum and response shape in this service against the API found nothing else adrift. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…id list filters A certificate requested with HTTP validation was issued immediately and handed back a DNS record, because that path fell through to the branch for private certificates which need no validation at all. It now stays pending and returns the redirect pair the API defines for exactly this case, which is mutually exclusive with the DNS record it was wrongly given. Listing certificates accepted any value at all for its status, key, usage and sort filters. An invalid one matched nothing and returned success, so a typo looked like an empty account. Those are validated now against the real enums, with the error that operation alone defines for bad arguments. Two items needed no change and were confirmed rather than assumed. The export gating already matches the operation's own error set in both directions. The managing service is accepted, stored, echoed and filterable, which is all the API itself does with it. Also fixed a shared copy that left the new redirect pointer aliased between a certificate and its copy, and the same narrower bug already present in the renewal summary beside it. Left alone deliberately: several request-path validators return an error that operation's own error set excludes, but the validators are shared with two other operations whose sets do include it, so it needs per-caller codes rather than a rename. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tion honestly Athena's delete-catalog flag was accepted and never read -- the request struct had no field for it, so a client's value was discarded by the decoder. It reaches the backend now, and is refused for the catalog types the API says it does not apply to. For the type it does apply to it remains inert, honestly: there is no stack, connector or connection here to preserve. Deleting one of those also echoed the catalog's stale creation status where a deletion status belongs. App Mesh reported every resource as active after deleting it -- a stronger false claim than a state that merely never advances, and the terminal value exists on all seven status enums. All seven deletes set it now. Both services also accepted any string at all for their state filters, so a typo returned an empty list and a success. Athena's three list operations and App Mesh's shallow specs validate against the real enums now, including a session state that was missing from the source entirely. App Mesh's four deep specs stay opaque. They nest four or five levels through several unions apiece, and half-validating them would refuse valid input while still admitting invalid. Two more tests filtered on a state that does not exist in the API and asserted success. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…sts, and stop guarding what AWS allows Detective returned an ingest-history field the real type does not declare. A client parsing it would drop the value and read an empty history on every call. Replaced with the documented nested shape, keyed off a timestamp recorded only when a package actually changes state. CodeDeploy accepted ContinueDeployment against a deployment in any state and never read the wait type off the wire at all. Both are validated now. That operation errors in every case today, which is the honest outcome: nothing here reaches the state it requires, and its previous success was a no-op. Deployment groups also stored EC2 tag filters they never evaluated -- the EC2 accessor already existed, so they resolve against real instances now, excluding ones already shutting down. CodeConnections went the other way and refused duplicate connection and host names. Neither operation models an already-exists error, while two siblings in the same service do, so the check was inventing a restriction. Removed, along with the indexes that existed only to serve it. All three services also accepted arbitrary values for enums the API constrains, returning empty results where AWS returns an error. The tag-filter wiring is covered from the composition root, so deleting its call site fails the build rather than silently resolving nothing. StopDeployment has the same missing precondition, left alone: deployments complete synchronously here, so enforcing it would strand the operation permanently. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ted updates MQ accepted tags for any ARN at all, including one belonging to no broker or configuration. Those tags could never be read back, since every read path resolves through a real resource -- a write that vanishes with no way to diagnose it. All three tag operations model a not-found error; they return it now. A snapshot test had asserted success against a fabricated ARN, which was the bug rather than a guarantee, so it is gone. That change surfaced a second door: the Resource Groups Tagging API reached the same backend through a closure that discarded the error and returned success unconditionally. Same nonexistent ARN, two answers depending on which API the client used. It propagates now, and the wiring is covered from the composition root so restoring the closure fails the build. The other five tagging closures of that shape were checked; the rest wrap operations that genuinely cannot fail. MWAA applied an update's fields to the stored environment before validating its sizing, so a rejected request left the DAG path, execution role and version already changed while the caller was told the update failed. Validation now runs to completion before anything is written. Also: configurations still referenced by a broker could be deleted, that operation being the only delete in the service that models a conflict; mw1.micro accepted webserver counts the real class rejects and defaulted to the wrong one; and both services took any string for an enum. Cross-region replication and Airflow request routing stay unmodelled. Both would need behaviour this cannot observe, and a partial answer reads as a real one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nerate stale docs Five register and permission operations fell through empty required fields into a lookup, so a request omitting one was told the resource did not exist rather than that the field was missing. Setting a permission with an empty user ARN reported no error at all. The password on RDS registration was decoded and then discarded, never required and never echoed; AWS requires it and always returns it filtered, which it does now. Instances created by the service itself could be assigned to a layer, which the API forbids. The distinction was already recorded on each instance and simply never consulted. Permission levels were accepted as any string against a closed set of five. Engine and the missing-on-RDS flag stay absent: the first is not a member of the request at all, and the second needs drift detection against real RDS state. Most optional creation parameters remain deferred -- the four named ones are modelled, the rest are a much larger surface. The service README rows for mq, mwaa and opsworks were stale against their own PARITY sources. Two concurrent passes each reverted the other's regenerated rows, so both landed unregenerated and the docs check would have failed. Regenerated here. Two tests omitted the now-required password and passed because nothing enforced it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… field AWS does not The idempotency token was decoded and thrown away, so a retried execution created a second statement. Retries are exactly what that token exists to make safe, and a client resending after a timeout got duplicate work with no way to tell. Repeat calls now replay the original result, following the scheduler's existing cache. Execution also demanded a database on every request. The SDK validates that field on the list and describe operations and not on either execute operation, so this rejected requests the real service accepts. Two tests asserted the rejection and were themselves the bug. CancelStatement was re-examined rather than assumed: it validates before mutating and already rejects an unknown statement. It never observably succeeds only because execution completes synchronously, which matches the documented requirement that a query be running to be cancelled. Left alone. The session keep-alive and role-level filters stay dropped. Both need a session or per-identity model that does not exist, and filtering on an identity nothing tracks would silently return the wrong rows. The concurrency and connection exceptions are unreachable for the same reason. One of them was missing from the audit entirely and is recorded now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tag atomically A profile could be created with no roles at all. The field is required both in the client validator and the service model, and a profile without it can never grant anything, so every such profile was dead on arrival. The prior note called this permissive behaviour a deliberate choice made to avoid disturbing existing tests -- but those tests were themselves asserting it, so the excuse was circular. Fourteen call sites corrected. The check is for presence, not contents: an explicitly empty list is still accepted, matching the validator. Tagging merged an incoming batch into the store's own backing slice before checking the tag limit, so a rejected over-limit request could still have overwritten the value of a tag that was already there. The caller saw an error and the change stood. The audit claimed this operation was atomic; now it is. Attribute mappings accepted any string for a field constrained to three values, a nil rule list the validator requires, and rules with an empty specifier. Subject lookup and the access-denied error stay as they are. Both were re-tested rather than assumed: unknown subjects already return the right error and pagination is already validated, so the empty list reflects absent session data rather than a missing check. Authorization would need a policy engine, and a partial one would answer wrongly rather than not at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ady held Seven Start* handlers parsed the job tag and video reference and then threw them away into a blank identifier. Every corresponding Get* response omits them, though the backend had the values the whole time. Threaded through, along with the inference-unit counts -- one of which was already stored and simply never serialised -- and the source version a copy was made from. Creating a project version did not require its output location, which the real validator does. Training and testing data could also be supplied one without the other, which the documentation forbids. The nested manifest shapes stay opaque, for a reason worth separating from their depth: they only resurface in training results, and training never completes here. The evaluation metrics stay absent for a stronger reason -- an F1 score cannot be derived from anything this holds, and a plausible one is worse than none. Reading a segment job's types needed care: each read advances the poll counter that drives the in-progress to succeeded transition, so fetching them separately would have made that one operation complete at twice the rate of its siblings. The audit claimed the feature configuration was a union of variants. It is one struct with one member. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every wire claim in a service's audit is verified against the version its front matter records, so a wrong version silently undermines the file that cites it. Twenty-one were checked by hand over one session: nineteen wrong. The harm is not the number itself -- on one service a claim stopped holding once re-checked against the real pin. The checker reads each recorded module name rather than deriving it from the directory, so the dozen services whose module differs from their folder cost nothing. One service is audited from the module cache and is absent from go.mod deliberately; its file says so, and that phrasing is what exempts it. Reports 105 mismatches today, so it is not yet wired into CI -- that comes with the corrections. Run it with make check-pins. Six files record a version the tool cannot parse, four of them omitting it entirely, and those warn rather than fail. That is the weaker half of this: the four largest services in the repo are currently exempt from the check by accident of formatting. x/mod moves from indirect to direct. The first attempt parsed go.mod with a regex and silently missed ten single-line requires. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… drift hid All 105 recorded pins disagreed with go.mod. Every wire claim in an audit is verified against the version its front matter names, so a wrong version does not merely mislabel the file -- it means nobody can tell which claims were checked against the real SDK. Most of the drift was harmless: 74 of 105 diffs were client middleware plumbing with no wire-shape change at all. One looked alarming, with two thousand changed lines and a move to the SDK's new code generation, and proved byte-identical field for field. The rest is why this was worth doing. Five audits asserted completeness that had quietly expired: a serverless cache described as fully wired against thirteen fields that now has nineteen, a destination configuration that gained an alternative shape and lost a required one, a queue input, a playback configuration whose round-trip claim was actively false, and an instance description missing two new fields. Those claims are corrected or downgraded here; the fields themselves stay unmodelled and are filed. One is a live bug rather than a stale claim: transcribe validates against a hand-written language list that predates twelve codes the service now accepts, so a client using any of them is rejected outright. Filed, not fixed here -- this pass changes documentation and comments only. The service that prompted this sweep was itself the proof. Its pin had been reported corrected earlier today and was not, and its own audit claimed a fifteen-member enum that has sixteen. Another recorded in its notes that only part of one pass had been checked against the real pin. Ninety-odd stale citations inside comments follow the same corrections. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eep left stale The six services the checker could not parse are now recorded properly, and an unparseable pin fails rather than warns. Four of the six were the largest services in the repo, so the check had been claiming coverage it did not have. Two of those six were themselves stale once a version could be read at all. IAM's had drifted far enough that policy simulation changed shape -- results now aggregate across resources instead of one entry per resource -- though that file already disclosed simulation as unverified, so no live claim broke. One recorded no version in any form and was unverifiable as written. The regenerated READMEs are the larger part of this diff, and they are my mistake. Splitting the pin sweep in two told each half to revert the other's regenerated rows; both obeyed, so sixty landed unregenerated and the docs check would have failed. Same failure as the earlier pair, at thirty times the scale, and it went in after I had already seen it once. The check runs as its own CI step before docs generation rather than inside that target, so regenerating READMEs does not start failing for an unrelated reason. Verified it rejects both a wrong version and an unreadable one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The allowlist was a hand-copied literal holding 42 of the 117 values the service accepts, so 75 valid codes were rejected outright -- six times the twelve the issue recorded, and the undercount is itself the argument: nobody can eyeball an enum this size, which is how it drifted unnoticed behind a stale SDK pin. It now reads the enum's own Values method, so a future bump cannot reintroduce the gap. The regression test iterates that same enum rather than a list of its own, and fails if the two ever diverge again. Every code the old list held was genuinely valid, so nothing was accepted that AWS refuses -- the drift ran one way only. The service's eight other hand-maintained allowlists were checked against their enums and all match exactly. Only this one had moved, which fits: it is the one AWS keeps adding to. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…very secret on an owner filter Rotation could be enabled on a secret with no Lambda ever configured. The error type documents that exact condition in words -- enabling rotation without a function ARN already set and without passing one -- and it is among the operation's four modelled errors. The recorded reason for leaving it was that dozens of tests depended on the lenient behaviour, but those tests were asserting the gap, so the justification rested on the thing it justified. Twenty-one corrected, and one that exercised a scenario the real service cannot reach now asserts the rejection instead. Nothing chained off rotation succeeding, so unlike the deployment operation left permissive earlier today, enforcing this strands nothing. The owning-service filter matched unconditionally, so a client narrowing to a managed owner got every secret back rather than none. Three more tests had fixed that behaviour in place. Two rejected requests wrote before they validated. Rotation mutated ahead of its own check, and an update applied the description and key before a value change that could still fail -- the caller saw an error and the edits stood. The managed-secret type and external rotation parameters were decoded into nothing at all. They are stored and echoed now. The owning service itself stays unset, correctly: no request field sets it, only AWS does. The external rotation role is deliberately not accepted as a strategy on its own. Nothing documents it as one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the filters that were parsed and ignored Send statistics counted real deliveries while reporting zero bounces and zero complaints unconditionally. A client reading a nil bounce rate could not tell an account with no bounces from one that never measured any -- the call stated a fact it had not established. AWS documents mailbox simulator addresses as the deterministic way to produce both, and nothing here recognised them; now it does, and the counters follow from real sends. Rejects still reports zero. There is no client-triggerable path to one and no content scanning to hang it on, so the number stays honest rather than invented. Listing identities ignored its type filter entirely, returning every identity whatever was asked for. Notification types and event-destination types were accepted unvalidated, the latter required by the model and limited to eight values -- several tests passed capitalised spellings no real client sends, and those were corrected rather than the validation loosened. The cross-account ARNs are accepted and dropped, which is now recorded as such. The model gives them no format to check and nothing here evaluates identity policies, so rejecting a malformed one could not be justified. Mail-from verification cannot fail here: the domain is marked verified the moment it is set, with no DNS check to fail it, matching how the rest of this service treats verification. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t, and stop reporting deleted units as policy targets Service control policies and resource control policies have different maximum sizes, and both were enforced at the smaller one. A service control policy of eight thousand characters, which AWS accepts, was rejected here. The existing test asserted the wrong boundary, so the limit had a test holding it in place. Deleting an organizational unit cleared its own index but left it listed as a target on every policy attached to it, so those policies kept reporting a target that no longer exists -- nameless, with an empty ARN, and typed as an account. Removing an account already cleaned both directions; this now does too. Tag keys and values were checked for count, duplication and reserved prefix but never for length, in either direction, though the model gives exact bounds for both. Resource policies had no size cap at all, and that one is a hard shape constraint rather than an adjustable quota. Enabling or disabling a policy type accepted any string at all, unlike creating one. The quota-increase path stays unmodelled, which is honest -- it is account state nothing here can observe. The chat and security policy sizes were checked against AWS's published limits rather than left unverified, and both already matched. One enum is left unvalidated deliberately: effective policy types are a larger set than policy types, and guessing at the difference would reject valid input. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ts, and reject instances that do not exist The recorded reason for leaving service attributes unbounded was that no numbers are documented. They are: the model carries a maximum of thirty attributes, a key length and a value length, none of which the Go SDK comments repeat. All three are enforced now, the count checked after the merge and before anything is written. Asking for the health of an instance that does not exist returned success with the identifier silently dropped, rather than the not-found error the operation documents. A client polling for an instance it never registered was told everything was fine. Three enums on service creation and update were accepted as any string -- routing policy, record type and health check type -- all closed sets in the model that the SDK's plain string fields cannot check. Two items stay unimplemented and the evidence for both is now recorded rather than asserted. The unknown health status exists in the enum, so the gap was never a missing value: nothing here drives the transition out of it. And there is no second account to share a namespace with, since the account identifier is a single constant repo-wide. The duplicate-request error is modelled on ten operations, four more than recorded. There is still no synchronous path to it: re-registering an instance is an upsert in the real service, and a duplicate service name already raises its own distinct error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…and validate batches before applying any of them Cluster responses carried a tags field the real shape does not declare, so a client parsing one silently read nothing where it expected tags. The backend keeps its own tag record, which is where the data actually lives and what the tag operations already read; only the invented wire field is gone. A test had locked the fabrication in place and now checks the real path. Updating a parameter group validated and wrote each entry in the same pass, so a batch with a bad entry near the end had already committed the good ones before it failed. Updating a cluster likewise wrote its description, window and security groups before checking the parameter group exists. Both now validate everything before writing anything. Six required-field checks reported a malformed ARN, an error the model declares only for the three tagging operations. The operations that raise them all declare an invalid-parameter error instead. Three required fields were accepted as absent and treated as no-ops. One of them could not even be detected, because the handler allocated an empty slice before the backend could tell absent from empty. Subnets gained the per-subnet network types the model gives them, distinct from the group-level field already present. Both recorded items stay unimplemented and both are honest: the two faults are account and infrastructure state no request shape can trigger, and the binary data plane is a separate wire format of some seven thousand lines. Node types stay free-text. The SDK gives no enum to check them against, and inventing a list would reject instance sizes AWS accepts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
I told the agents to stop running the docs generator, on the grounds that two of them reverting each other's regenerated rows is what broke this gate twice, and said I would regenerate at commit time instead. Then I did not, across six commits. The generator is the only thing that reconciles a service's audit with its README, so the check would have failed on the next push. The rule was right and the follow-through was missing. Regenerating once before each commit is a step in my sequence now, not an intention. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s a topic attribute Any syntactically valid JSON was accepted as a data protection policy, including an empty object, and no length was enforced. AWS documents three required top-level keys and a maximum length; both are checked now. The policy grammar itself stays unimplemented, which is the honest boundary -- the identifiers and statement forms are a language, not a schema. The policy was also settable through the generic topic attribute setter and came back from the attribute getter. Neither operation lists it among their attributes; it belongs solely to its own dedicated pair. Removed from both. Two fixtures were asserting the looser behaviour: one policy omitted a required key, and one seeded the attribute through the path that no longer accepts it. Three of this issue's four items were already fixed, by a pass that landed two days after the issue was filed. Verified against the code rather than the audit prose, since a false claim in one of those files is what prompted this campaign's verification rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s, and stop accepting directories that were never registered Application associations returned a status field under a name the real type does not declare, holding values its enum does not contain. A client reading it found nothing where it expected the state, and the state it wanted was never sent. The field and its values are the documented ones now. That the association completes immediately is fine and stays -- there is no pending window to model in a synchronous backend. Only the invented name and values were wrong. Seven directory operations shared one cause: a settings row was fabricated for any directory identifier at all, registered or not, so every one of them succeeded against a directory that does not exist. Bundle updates likewise accepted an image identifier that was never created, leaving the bundle pointing at nothing. Pool running mode could be changed in any state, though the API allows it only while stopped. Reboot and rebuild ignored their documented state preconditions entirely. Application identifiers are deliberately still unvalidated: nothing here seeds the catalogue and the real API has no operation to create one, so requiring existence would strand the operation permanently. Same reasoning that kept a deployment operation permissive earlier today, applied the other way round. No quota errors were invented. Every one is account state with nothing here to check against. Two more operations have the same unvalidated-identifier gap and are recorded rather than fixed, to keep this contained. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ur quick-create immutability Routing rules stored their actions and conditions as free-form maps where the API defines six small structs, none nested more than three deep. Typed, with the required sub-fields checked, the documented priority bounds enforced, and the referenced API and stage required to exist -- previously any string was accepted, leaving a rule pointing at nothing. Routes and stages created by quick-create are managed by the service and cannot be edited, which was not enforced at all. Deleting them stays permitted: those operations model no error that would fit a refusal. The import operations never read their query parameters. Prepending the imported base path to route paths works now; splitting it into a stage does not, and neither does failing on warnings, because the model does not say what either produces and this file already carries a warning against inventing that content. Three more operations wrote before they validated -- a route key applied ahead of an invalid authorization type, an API's name ahead of an invalid address type, and a domain's tags ahead of an invalid routing mode. The portal family was recorded as a large unmodelled surface. It is twenty six operations and all of them are implemented; that note was wrong and is corrected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rule across calls Attribute names were never checked against the API's set, so a misspelling was stored and echoed back as though it had taken effect. A queue asked for a shorter visibility timeout under a slightly wrong name kept the default and reported success. The rule that per-message-group throughput requires message-group deduplication was enforced only when both attributes arrived in the same request. Setting them in either order across two calls produced a combination the real service rejects. It now checks the merged state. Per-queue throughput limiting is still not implemented, deliberately. Neither the SDK nor the model publishes the per-operation budgets, and a throttle that fires where the real service would not turns working client code into an intermittent failure -- the hardest kind to attribute. The encryption attributes stay stored and echoed with no encryption behind them, which is the honest boundary. Their mutual exclusion is left unenforced too: the wording is advisory rather than a stated rule, the managed option is on by default here, and guessing between rejecting, clearing and last-write-wins would invent behaviour rather than model it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ng projects that do not exist Four of the five untyped shapes are one to three levels deep with no unions, so they are typed now. The profile configuration is not: four levels across two independent lists of structs, where a partial model would drop fields a client cannot distinguish from ones never implemented. It stays a map. Typing is what exposed the actual bugs. Three enums were unchecked, two output shapes had required members nobody validated, and the documented rule forbidding overwrite alongside database options was unenforced. Updating a job also applied its role and outputs before checking any of that, so a rejected update left the other fields changed. Both project session operations never touched the backend at all, so a session started against a project that does not exist returned success. Both document a not-found error and return it now, and the session identifier that was always discarded is returned. The interactive session itself -- view frames, applying and previewing recipe steps -- stays unmodelled. Creating a job still does not check that its dataset, project and recipe exist, though the operation documents the error. Around twenty-five tests create jobs against names never created, so that is filed rather than swept in here. Creating a project was checked too and is correctly unvalidated: its error list has no not-found at all. A bucket owner field was missing from the shared location shape. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…es that do not exist A predictor could be created against a dataset group that was never created, and a dataset group against datasets that do not exist. The create succeeded, so everything downstream behaved as though the dependency were simply empty -- the failure a client cannot diagnose, because nothing ever reports an error. All four operations model the not-found error, each checked separately rather than inferred from a sibling: the update's error list is genuinely shorter than the creates'. The two predictor fields were fenced out of an earlier pass on purpose, and that note said so rather than hiding it. The dataset list was not mentioned at all. Rejection is on the first missing reference. Nothing documents collecting them all, and the service's existing list check behaves the same way. An empty list stays legal in both operations -- the shape sets no minimum, and for the update an empty list is how you clear the datasets. That was confirmed with a test that passed before the change as well as after, so the new check cannot have tightened it. Three tests referenced datasets that were never created. They build real ones now. Nothing in the suite exercised the predictor configs at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ed, and reject locations built on agents that do not exist Five location types accepted customer-managed and custom secret settings and discarded them, along with the SMB Kerberos principal and DNS addresses -- accepted even though the Kerberos authentication type itself already was. All are stored and echoed now, except the keytab and configuration file, which stay write-only because the real response omits them too. None of those five checked that the agents they reference exist, so a location could be created against an agent that was never created. The managed secret configuration stays absent and that is correct: the API declares it read-only and populates it itself, so accepting one would invent a secret this has no way to hold. The generated location URIs for object storage and Azure Blob do not match the pattern the model publishes, which permits only a fixed set of schemes. That is now proven rather than suspected -- but nothing indicates what the real schemes are, and the earlier fix for a sibling type only worked because a confirmed neighbour existed to reason from. Recorded, not guessed. The SMB authentication type accepted any string against a two-value enum. Task error codes and interface identifiers stay unreported: the only failure state ever recorded is a bare status with no message behind it, and there are no interfaces to name. The NFS location has the same unchecked agent reference and a flat field the real request nests. Both are recorded rather than fixed; correcting the shape is a restructure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The NFS location was the one type left out when the other five gained agent existence checks, so it still accepted an agent that was never created. Both its operations model the error independently -- checked separately rather than inferred from each other or from the five already done. Two tests used invented agent identifiers and now create real ones, one of them in the integration suite. The second half of the issue this closes was wrong, and it was my error. I recorded that the NFS request carries a flat agent list where the real API nests it under the on-premises configuration. The wire shape has nested it correctly since July; what is flat is the internal function parameter, which is deliberate and matches every other location type. I repeated the claim without checking it. The audit note asserting the same thing is corrected. Also recorded, not fixed: the NFS update drops a server hostname the real API accepts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…the two tag stores Every error from every operation in this service arrived at the client as an unknown error. The response carried a message and nothing else -- no error type header, no type in the body -- so the SDK had nothing to identify it by. A caller could not distinguish a missing channel from a malformed request, and no error-handling branch above the transport could ever match. Found while checking an unrelated fix through a real client. Tags had two stores that disagreed. Four resource types wrote both on create but read only the struct, so tagging afterwards was visible to the tag listing and invisible to describe; functions never wrote the ARN-keyed store at all, so their tags were invisible there from the moment they were set. Reads now come from the ARN-keyed store the other types already treat as authoritative, and deletes clear it. The three source location configurations are shallow -- at most three levels and no unions -- so they are typed rather than left opaque. That exposed an access type accepted as any string. Creating a program did not check that its source location or its named source exist, though both sibling operations already did. Function types were likewise unvalidated against a three-value enum, and several tests used invented values. Ad break scheduling stays absent: it needs manifest scanning that exists nowhere here, and inventing timings would be worse than the gap. Tag operations still do not check that the ARN they name exists. That needs ARN parsing across resource types and is recorded rather than half-done. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…can tell them apart Three services returned every error as a message with no type anywhere -- no header, nothing in the body -- so the SDK had nothing to match and every failure arrived as a generic unknown error. A caller could not distinguish a missing channel from a malformed request. MediaLive had the identical responder to the one fixed in MediaTailor. Each emitted type was checked against that service's own modelled error list rather than assumed from a sibling. The wider audit this came from matters more than the three fixes. Of 48 services with no error-type header, only six are actually broken. Nineteen already carry a type in the body under a name the header search missed. Eighteen are query, EC2 or REST-XML, where the header is irrelevant and adding one would invent a wire shape. Five type every error a client can actually trigger and leave only an unreachable internal fallback bare. The three genuinely broken services left alone are left for stated reasons, not budget alone: one routes eight call sites through a shared conflict helper where the real model exposes that error on only some of the operations, one uses a field name the deserializer does not read across four files, and one has no central error path at all. Whether the XML services shape their error bodies correctly is a separate question and was not audited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
No description provided.