Tags: BlackbirdWorks/gopherstack
Tags
parity: full 154-service AWS-emulation sweep (single PR) (#2342) * parity-sweep: seed single-PR tracking checklist (154 services) * parity(ec2): real AWS-accurate EC2 emulation — fix parity.md ec2 findings RevokeSecurityGroupEgress rule validation (InvalidPermission.NotFound), DescribeInstances allocation perf, and remaining ec2 Parity/Performance/Leak findings. Table-driven tests. build+vet+test+lint green. * parity(s3): real AWS-accurate S3 emulation — fix parity.md s3 findings CompleteMultipartUpload empty-parts rejection, S3 Select validation, list pagination, object-lambda/tags leak fixes, replication goroutine drain on Shutdown. 9 table-driven test funcs / 18 sub-cases. build+vet+test+lint green. * parity-sweep: tick ec2, s3 complete * parity(cloudformation): real AWS-accurate CFN emulation — fix parity.md findings DescribeType full schema, StackSet drift ops (DetectStackSetDrift/ListStackSetOperations/DescribeStackSetOperation), event/stack/operation eviction caps. Table-driven tests. build+vet+test+lint green. * parity(sns): real AWS-accurate SNS emulation — fix parity.md findings RedrivePolicy/DLQ delivery, DLQ target validation, archive/replay history, region isolation, pagination, FIFO dedup, seq-counter cleanup. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick cloudformation, sns complete * parity(lambda): real AWS-accurate lambda emulation — fix parity.md findings Parity fixes: - handleInvokeAsync: fire-and-forget (HTTP 202 immediately, asyncWG.Go for background invocation) - handleInvokeWithResponseStream: proper AWS event stream binary protocol (CRC32/IEEE frames) - sweepESMs: mark enabled ESMs with missing functions as LastProcessingResult="PROBLEM" Performance / leak fixes: - withInvocationChain: []string slice (make+copy) instead of map — no per-call heap alloc - invocationChainContains: slices.Contains — cleaner hot-path - activeConcurrencies: delete map entry when count reaches zero - cleanupSem / logSem: replaced with fresh channels in Reset() so post-reset goroutines don't block on pre-reset channel references Lint / modernize: - Remove //nolint annotations: use loop counters for int→byte/uint16 narrowing (G115) - WaitGroup.Go, maps.Copy, slices.Contains modernize patterns - nlreturn, goconst, gocritic, govet shadow, testifylint, revive fixes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(dynamodb): real AWS-accurate DynamoDB emulation — fix parity.md findings PITR snapshot capture, GSI/LSI LastEvaluatedKey base-keys, PartiQL NextToken/ORDER BY/DuplicateItem/error-codes, ExecuteTransaction atomicity, export/import async status, restore GSI/LSI/billing fidelity, OnDemandThroughput, expr cache (parse-once), backup/iterator leak fixes. 65 files, table-driven tests. build+vet+test+lint green. * parity(lambda): real AWS-accurate Lambda emulation — fix parity.md findings Durable-execution + capacity-provider ops implemented (no more no-op stubs), SnapStart, CreateFunction Pending->Active state + LastUpdateStatus, memory validation, ESM health checking. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick dynamodb, lambda complete * parity(stepfunctions): real AWS-accurate Step Functions emulation — fix parity.md findings TestState nextState, real MapRun data (Describe/List/UpdateMapRun), O(1) status-filtered ListExecutions, SweepTaskTokens lock fix, orphaned-tombstone cleanup, history TTL. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick stepfunctions complete * parity(ssm): fix parity, performance, and leak issues Parity: - Replace shared package-level mock KMS key with per-instance random AES-256 key (newInstanceGCM). Each InMemoryBackend now generates its own key so ciphertexts are not interchangeable across backend instances, matching AWS KMS key-isolation semantics. Performance: - Remove O(n) expireCommandsLocked call from SendCommand write path; expired-command eviction is the janitor's job (sweepExpiredCommands runs on a configurable interval). SendCommand is now O(1) again. - Remove paramNamesSorted sorted-slice index and its O(n) insert on every PutParameter. Replace collectPathParamsSorted (binary-search) with collectPathParams (linear scan + sort-at-read). PutParameter write path drops from O(n) to O(1); GetParametersByPath is O(n log n) which is acceptable for an emulator. Also fixes a silent post-Restore bug where GetParametersByPath returned empty (sorted slice was never rebuilt from the snapshot). Leaks: - Add cleanupEmptyParamRegion: after DeleteParameter / DeleteParameters removes the last entry in a region, the empty parameters/history/tags inner maps are deleted so they don't accumulate indefinitely. Tests: - Update leak_test.go: TestSendCommand_PrunesExpiredCommands → TestJanitor_PrunesExpiredCommands; verify janitor sweeps expired commands and that SendCommand no longer does so. - Add parity_fixes_test.go with table-driven tests for all four fixes: per-instance key isolation, self-roundtrip encryption, linear-scan path lookup (sort order, recursive/non-recursive, no-match), and region-map cleanup via single and batch delete. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(iam): parity fixes — distinct error sentinels, O(1) sorted list indexes, fast policy lookup Parity: - Give each NoSuchEntity sentinel a distinct message suffix (user, role, policy, group, access key, instance profile, inline policy, SAML provider, OIDC provider, login profile) so callers can identify the missing resource type via .Error() inspection without relying on errors.Is pointer identity alone. HTTP error code is still "NoSuchEntity" matching AWS. - Fix collectNamedEntityPolicies to use policyByARN map for O(1) ARN → name resolution instead of the previous O(n) linear scan over all policies. Performance: - Add sortedUserNames, sortedRoleNames, sortedPolicyNames, sortedGroupNames, sortedIPNames []string indexes to InMemoryBackend, maintained via binary-search insert/delete on every create/delete. ListUsers, ListRoles, ListPolicies, ListGroups, ListInstanceProfiles now paginate via pageFromSortedNames which resolves the base64-encoded integer marker token in O(1) and builds each page in O(k) (page size), eliminating the previous O(n log n) sort rebuild on every list call. - rebuildIndexesLocked and Purge both rebuild sorted name indexes via rebuildSortedNames, keeping persistence and compaction paths consistent. Tests: - TestParityIAM_ErrorSentinelDistinctness: table-driven, verifies each sentinel has a unique .Error() string. - TestParityIAM_ErrorSentinelUniqueness: all pairs are not-equal via errors.Is. - TestParityIAM_ErrorSentinelWrapping: backend errors wrap the correct sentinel. - TestParityIAM_HandlerNoSuchEntityCode: handler returns 400 + "NoSuchEntity" for all not-found operations. - TestParityIAM_SimulatePrincipalPolicy: real policy evaluation (allow, deny, no policy, explicit deny overrides allow). - TestParityIAM_CredentialReportColumns: all 22 AWS-required CSV columns present. - TestParityIAM_ListPaginationSortedOrder: multi-page pagination stays sorted. - TestParityIAM_SortedIndexMaintainedAfterDelete: index correct after deletion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(ssm): complete parity.md findings — region cleanup, MW executions, generic cleanup helper - Add cleanupEmptyInnerMap[V any] generic helper that removes a region key from any two-level map when the inner map becomes empty; replaces the three-field cleanupEmptyParamRegion body with calls to this helper - Wire cleanup to all delete paths: DeleteActivation, DeleteAssociation, DeregisterTargetFromMaintenanceWindow, DeregisterTaskFromMaintenanceWindow, DeleteMaintenanceWindow, DeletePatchBaseline, DeleteOpsItem, DeleteOpsMetadata, DeleteInventory, DeleteResourceDataSync, DeleteResourcePolicy, DeleteDocument - Janitor sweepExpiredCommands now cleans up commands/commandInvocations maps after eviction so empty region buckets do not accumulate - GetMaintenanceWindowExecution/Task/Invocation now populate StartTime, EndTime, StatusDetails, TaskARN, TaskType, Priority, MaxConcurrency, MaxErrors, InvocationID, WindowTargetID from stored window/task data - Expand three MW execution output types with full AWS-accurate fields - Fix handler_batch2_test to create a real window before GetMaintenanceWindowExecution - Add TestGetMaintenanceWindowExecution_FullOutput and TestOtherMapsRegionCleanup table-driven tests covering new behavior (all t.Parallel) - Zero golangci-lint issues; struct field order corrected by fieldalignment * parity(ssm): real AWS-accurate SSM emulation — implement stubbed ops + fixes ~120 stubbed ops given real state mutation (ResourceDataSync, Inventory, Activations, maintenance windows w/ MaxConcurrency/MaxErrors/InvocationID/WindowTargetID), GetParametersByPath prefix index, param/doc/command history AWS caps, MaxResults bounds. Table-driven tests, 0 lint. * parity(iam): real AWS-accurate IAM emulation — fix parity.md findings Policy-eval correctness, pagination/validation fidelity, sub-ops. Table-driven tests, 0 lint. * parity(glue): real AWS-accurate Glue emulation — implement stubbed ops 20+ empty-struct stubs given real data/state (GetBlueprintRun, GetPlan, ImportCatalogToGlue, column-statistics, schema-versions-diff, usage-profile), StopCrawler STOPPING->READY reconcile. Table-driven tests, 0 lint. * parity-sweep: tick ssm, iam, glue * parity(kms): fix cache staleness, lastUsage leak, perf O(n) clear Four parity/leak/perf fixes for services/kms: Parity: keyIDResolutionCache not invalidated on DisableKey / ScheduleKeyDeletion. Alias→keyID entries cached before a key state change persisted in the cache, allowing stale hits to bypass the aliasesStore and return the old keyID. Fix: call evictAliasesFromCache (O(aliases-for-key)) in both operations. Performance: clearResolutionCache used sync.Map.Range+Delete (O(n)) and was called on every alias mutation (Create/Update/Delete). Fix: change keyIDResolutionCache to *sync.Map so clearResolutionCache swaps the pointer in O(1); replace full-cache clears in alias mutations with single targeted Delete calls; remove the post-sweep clearResolutionCache call from sweepExpiredKeys since purgeKey now evicts targeted entries. Leaks: purgeKey in the janitor deleted keys, aliases, grants, and key material but never removed the corresponding lastUsage sync.Map entry, causing unbounded growth. Fix: add lastUsage.Delete in purgeKey. Tests: table-driven tests in parity_fixes_test.go covering all four fixes; test helpers (ResolutionCacheLen, ResolutionCacheHas, LastUsageExists) added to export_test.go. * parity(cloudwatch): real AWS-accurate CloudWatch emulation — fix parity.md findings Parity: - GetMetricWidgetImage: return minimal valid 1×1 PNG (base64) instead of empty stub - ListAlarmMuteRules: add backend method + wire handler to return stored rules - ListManagedInsightRules: add backend method filtering ManagedRule=true; wire handler - PutManagedInsightRules: parse ManagedRules.member.N.* and store with ManagedRule=true - EC2/AutoScaling alarm actions: log explicit warnings instead of silent no-op Performance: - SweepExpiredMetrics: two-phase sweep (read-lock snapshot → out-of-lock filter → write-lock apply) avoids holding global write lock for full O(series×points) scan - PutMetricData: extract storeDatum helper; move stream delivery timestamp update to a second, shorter write-lock acquisition outside the main metrics write section - Extract sweepScanCandidates / sweepApplyResults / hasExpiredPoint helpers to reduce cognitive complexity below gocognit threshold Leaks: - deleteResourceTags: call t.Close() before removing from map to deregister the per-resource Prometheus lockmetrics entry and prevent unbounded registry growth Tests: new parity_test.go with table-driven tests for all fixed ops Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(ecs): real AWS-accurate ECS emulation — implement daemon ops, service revisions, state changes - Implement all 12 daemon CRUD operations with full state tracking (CreateDaemon, DeleteDaemon, DescribeDaemon, ListDaemons, UpdateDaemon and task-def/deployment/revision ops) - Track service revisions on CreateService and UpdateService; implement DescribeServiceRevisions - Fix DiscoverPollEndpoint to return region-specific endpoints (was hardcoded) - Implement SubmitTaskStateChange, SubmitContainerStateChange, SubmitAttachmentStateChanges with cluster/task validation instead of no-op stubs - Fix enrichCluster O(n) task scan: cache RunningTasksCount/PendingTasksCount on Cluster and maintain counters at every state transition (RunTask, StopTask, startTasksOutsideLock) - Add Backend interface methods for all new ops; add GetRegion() on InMemoryBackend - Add region field to Handler populated from backend for regional URL generation - 19 table-driven tests covering all new operations and counter correctness Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(cloudwatch): real AWS-accurate CloudWatch emulation — fix parity.md findings findGrantByToken token index (O(1)), metric-datapoint ring buffer, alarmHistory cross-alarm cap. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick cloudwatch * refactor(kms): split ReEncrypt into helpers to satisfy funlen lint Extract reEncryptDecrypt (source key lookup, validation, decrypt) and reEncryptEncrypt (dest key lookup, validation, encrypt) so ReEncrypt itself is ~34 lines, well under the 100-line funlen limit. No behaviour change. * parity(kms): real AWS-accurate KMS emulation — fix parity.md findings findGrantByToken O(1) token index, keyMaterialHistory migration (decrypt older ciphertexts), grant/material leak fixes, ReEncrypt refactored under funlen. Table-driven tests. build+vet+test+lint green. * parity(ecs): real AWS-accurate ECS emulation — fix parity.md findings getServicesForReconciler bounded iteration, docker containers map leak on failed StopTask, reconciler perf. Table-driven tests across 28 files. build+vet+test+lint green. * parity-sweep: tick kms, ecs * parity(sts): real AWS-accurate STS emulation — fix parity.md findings GetCallerIdentity InvalidClientTokenId (400 not 403), session TOCTOU fix, session-store sweep/leak bound. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick sts * fix(sqs): parity/perf — region isolation, janitor skip-idle, MD5 reuse Parity: - lookupQueueByURL: remove O(n) URL-string fallback scan that defeated region isolation; always resolve via effectiveRegion(region)+name composite key so a wrong-region request returns not-found instead of blindly finding the queue. Performance: - pruneState: replace full-capacity snapshot (len(b.queues)) with a filtered collection that skips queues with no hasActivity flag set. A new atomic.Bool field on Queue is set on every SendMessage and cleared by pruneState when the queue becomes fully idle, so idle queues are skipped on subsequent janitor ticks without lock contention. - ReceiveMessage handler: when filterMsgAttrs returns the full attribute set (len(returnedAttrs)==len(msg.MessageAttributes)), reuse msg.MD5OfMessageAttributes computed at send time instead of re-sorting and re-hashing on every receive. Subset requests still recompute to produce a correct scoped digest. Tests (table-driven): - TestLookupQueueByURL_RegionIsolation: wrong-region receive returns error - TestLookupQueueByURL_CrossRegionURLScanEliminated: east queue invisible to west - TestPruneState_SkipsIdleQueues: 50 idle queues, active-queue message expires - TestPruneState_ClearsActivityFlagWhenIdle: flag cleared after full drain - TestComputeMD5OfMessageAttributes_FullSetUsesPrecomputed: all/.*/ exact-full variants - TestReceiveMessage_MD5Consistency: subset MD5 matches SQS wire-format spec Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(cloudwatchlogs): real AWS-accurate CW Logs emulation — fix parity.md findings metric-filter matching index (O(filters+events) not O(×)), parsed-query cache TTL eviction. Table-driven tests. build+vet+test+lint green. * parity(sqs): real AWS-accurate SQS emulation — fix parity.md findings Table-driven tests. build+vet+test+lint green. * parity-sweep: tick cloudwatchlogs, sqs * parity(ecr): real AWS-accurate ECR emulation — fix parity.md findings DescribeImages incremental digest->tags reverse map (no rebuild per call), InitiateLayerUpload TTL eviction. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick ecr * parity(kinesis): fix tags leak, optimize janitor sweep, add shutdown mechanism and UI * parity(kinesis): real AWS-accurate Kinesis backend — fix parity.md findings tags-map cleanup via OnStreamPurged on all delete paths, janitor sweepRetention RLock (no longer blocks PutRecord/GetRecords), explicit janitor Stop() shutdown. (Existing UI page preserved; gemini's unprompted UI rewrite dropped.) * parity(route53): implement advanced ops, fixes and UI * parity-sweep: tick kinesis (backend) * parity(route53): real AWS-accurate Route53 emulation — fix parity.md findings handler-level tags map eviction on missed/failed ARN deletes, completeness ops, UI additions. Table-driven tests. (stray fix_lint.sh excluded.) * parity(glacier): real AWS-accurate Glacier emulation — fix parity.md findings async retrieval-job window before GetJobOutput (no instant Succeeded), ListVaults/ListArchives marker copy fix. Table-driven tests. (stray backend.go.orig excluded.) * feat(lakeformation): parity fixes for GetDataLakePrincipal, GetTableObjects, GetQueryStatistics, GetWorkUnitResults, and performance/leak improvements * parity-sweep: tick route53, glacier * parity(lakeformation): real AWS-accurate LakeFormation emulation — fix parity.md findings permissions slice cap/TTL (no unbounded growth), backend accuracy. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick lakeformation * parity(macie2): real AWS-accurate Macie2 emulation — fix parity.md findings findings-criteria matching, list pagination + generic listPaginated helper, accuracy. Table-driven tests. build+vet+test+lint green. (stray patch_backend.sh excluded.) * parity-sweep: tick macie2 * parity(rds): real AWS-accurate RDS emulation — fix parity.md findings Marker pagination for DescribeDBParameterGroups/DBClusterParameterGroups/DBParameters/OptionGroups, UI additions. Table-driven tests. build+vet+test+lint green. (stray .orig + package-lock excluded.) * parity-sweep: tick rds * parity(rds): remove orphan handler_stubs.go (renamed to handler_completeness.go) — fix duplicate-decl build break * parity(organizations): real AWS-accurate Organizations emulation — fix parity.md findings ListTargetsForPolicy summary caching, CreateOrganizationalUnit sibling-name scan perf, pagination. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick organizations * fix(integration): STS/CloudWatchLogs/ECR runtime regressions (go-ds2ym) DecodeAuthorizationMessage decodes any valid base64 (not just self-issued), AssumeRoleWithSAML creds/Issuer/NameQualifier, CloudWatchLogs Insights, ECR GetAuthorizationToken. Unit+lint green. * fix(integration): correct STS DecodeAuthorizationMessage/AssumeRoleWithSAML + ECR GetAuthorizationToken Supersede the incomplete first attempt: STS decodes any valid base64 (not only self-issued), SAML accepts non-XML base64 assertions, ECR returns stable base64(AWS:dummy-password). Unit tests realigned. CloudWatchLogs Insights still pending. * fix(integration): CloudWatchLogs StopQuery allows stopping instant-Complete queries gopherstack runs Insights queries synchronously, so a query is already Complete when a client calls StopQuery — the old running-state guard rejected it. StopQuery now transitions any non-cancelled query to Cancelled (matches TestIntegration_CloudWatchLogs_Insights). * parity(batch): real AWS-accurate Batch emulation — fix parity.md findings DeleteComputeEnvironment/findTagsInCoreResources reverse-index perf, accuracy. Table-driven tests. build+vet+test+lint green. (stray patch_backend.go/sweep_test.go/handler.go.orig excluded.) * parity-sweep: tick batch * parity(elasticache): real AWS-accurate ElastiCache emulation — fix parity.md findings backend accuracy + lock-correctness fixes. Table-driven tests. build+vet+test+lint green. * parity-sweep: tick elasticache * parity(xray): fix all parity.md findings - NewInMemoryBackend(accountID, region) — ARNs now use the injected region/account instead of hardcoded config.DefaultRegion constants - groupsByARN index — GetGroupByARN/UpdateGroupByARN/DeleteGroupByARN go from O(n) linear scan to O(1) map lookup - Insight detection — PutTraceSegments now calls detectInsights(); ACTIVE insights auto-open when per-service fault rate ≥ 5% over a 60-second window and auto-close when the rate normalises - ListRetrievedTraces — handler now returns real Segments[] (Document + Id + computed Duration) instead of empty arrays - Retrieval leak fix — janitor sweepExpiredTraces now also evicts traceRetrievals/retrievedTraces entries older than TraceTTL - provider.go uses service.AccountRegionOrDefault to populate backend - Table-driven tests (t.Run + []struct) for all new behaviours Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(workspaces): fix all parity.md findings (go-8189a) - Add region field to storedWorkspace; store via regionFor(ctx) on CreateWorkspace - Filter workspaces by region in DescribeWorkspaces - Validate DirectoryID is registered in CreateWorkspace - Add ctx param to CreateWorkspace, DescribeWorkspaces, DescribeWorkspaceBundles, DescribeWorkspaceDirectories; pass through from handlers - Add cursor-based pagination to DescribeWorkspaceBundles (page size 25) - Add cursor-based pagination to DescribeWorkspaceDirectories (page size 50) - Convert hardcodedBundles() to pre-sorted amazonBundleList() function - Refactor handleCreateWorkspaces into validateCreateWorkspacesInput, specToCreationSpec, wsToPending helpers to stay under funlen threshold - Update existing tests to register directories before CreateWorkspaces - Add backend_parity_test.go with 5 table-driven parity tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity-sweep: tick workspaces, xray (completed) * chore: remove trash fix_lint.sh from parity-sweep Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(dax): fix AZ-indexing, RebootNode recovery, pending-reboot, error mapping - IncreaseReplicationFactor: guard used raw loop index i instead of offset j=i-existingCount, silently ignoring caller-supplied AZs when the cluster already had nodes - RebootNode: empty NodeId returned ErrNodeNotFound; AWS returns InvalidParameterValue. Add recovery goroutine that restores node status to available after 1s, mirroring real DAX behaviour - UpdateParameterGroup: did not mark dependent clusters pending-reboot or populate NodeIDsToReboot; now scans all clusters using the group - writeBackendError: flattened every DynamoDB error to ValidationException; now maps ConditionalCheckFailed, ResourceNotFound, TransactionCanceled, TransactionConflict, and ProvisionedThroughputExceeded to their correct DAX error codes - handleGetItem: decoded ConsistentRead from the wire but discarded it with _; now passes it through to the DynamoDB backend - nameRef: O(n²) linear scan replaced with O(1) reverse map - schemaFor: cache was never invalidated on table drop/recreate; now fetches live on every call for correctness Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * fix(sqs): hold q.mu around computeDynamicAttributes in GetQueueAttributes GetQueueAttributes read q.messages, q.delayedCount, and q.inFlightMessages without holding q.mu, while ReceiveMessage writes them under q.mu.Lock. This caused a data race detected by -race in TestIntegration_Lambda_SQS_ESM. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(pinpoint): fix handleCreateApp error mapping Before this change, any error from Backend.CreateApp was unconditionally mapped to HTTP 500. Other handlers (GetApp, DeleteApp, etc.) already dispatched errors correctly. This fix brings CreateApp into line: - ErrInvalidParameter → 400 BadRequestException - ErrConflict → 409 ConflictException - ErrNotFound → 404 NotFoundException - other → 500 InternalServerErrorException Add handler_parity_test.go with table tests covering: - CreateApp input validation returns 400 (not 500) - GetApp/DeleteApp for nonexistent IDs return 404 with NotFoundException - CreateApp response shape includes Id, Arn, Name, CreationDate - GetApps reflects all created apps - DeleteApp removes app from subsequent list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * feat(eventbridge): fix parity issues — opaque tokens, per-account quota, ListEventBuses Limit, Shutdown cancellation, tag leak - paginate: encode next-page tokens as base64 so they are opaque to callers, matching real AWS behavior; parseNextToken retains a plain-integer fallback for tokens produced before this change - paginateN: new generic helper that respects a caller-supplied page size (0 = default 100) - ListEventBuses: add limit parameter to StorageBackend interface and InMemoryBackend so the Limit field from API requests is honored instead of always paging at 100 - CreateEventBus quota: count custom buses across all regions in b.buses to enforce the per-account limit (200), not per-region - StartWorker: derive a cancellable context for scheduler and archiveJanitor goroutines; store the cancel func so Shutdown can terminate both workers before closing the backend - DeleteEventBus / DeleteRule: describe the resource before deletion to obtain its ARN, then call clearResourceTags so the handler tags map does not grow without bound Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * parity(ram): opaque tokens, resourceOwner/type filters, policy accuracy, promote permission Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(opsworks): implement missing AWS OpsWorks ops — stacks, layers, instances, apps, deployments Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(personalize): implement missing AWS Personalize ops + accuracy fixes Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(mediastore): container/policy/metric/lifecycle accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(medialive): implement missing AWS MediaLive ops — inputs, channels, multiplex, input-devices Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(mediapackage): channel/origin-endpoint/harvest-job accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(guardduty): detector/finding/filter/IPSet accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(fsx): filesystem/backup/storage-virtual-machine accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(identitystore): user/group/membership accuracy + filters + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(elbv2): listener/rule/target-group/health accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(emr): implement missing AWS EMR ops — steps, instance groups/fleets, security configs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(docdb): cluster/instance/snapshot/parameter-group accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(elasticbeanstalk): application/environment/version/config accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(datasync): location/task/execution/agent accuracy + audit coverage Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * parity(ddbstreams): real stream timestamps, StreamLabel, error namespace - store.go: add StreamCreatedAt time.Time field to Table - streams_ops.go: buildStreamARNInRegion now accepts creation time, embeds real ISO 8601 millisecond timestamp (e.g. 2026-06-26T03:43:00.000) in the stream ARN instead of the hardcoded 2024-01-01 placeholder - streams_ops.go: DescribeStream sets StreamLabel from ARN (not "latest"), populates CreationRequestDateTime with the real stream creation time - streams_ops.go: ListStreams sets StreamLabel from ARN (not "latest") - streams_ops.go: add streamLabelFromARN helper - table_ops.go: CreateTable and UpdateTable set StreamCreatedAt and pass it to buildStreamARNInRegion - handler.go (dynamodbstreams): rewrite error __type prefix from dynamodb.v20120810 to dynamodbstreams.v20120810 so SDK clients get the correct namespace - handler_parity_test.go: table-driven parity tests covering ARN label format, StreamLabel consistency, CreationRequestDateTime presence, ListStreams label, error namespace, and UpdateTable stream enable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(kinesisanalytics): fix DeleteApplication error code and UpdateApplication response - backend.go: DeleteApplication timestamp mismatch now returns ErrConcurrentUpdate instead of wrapping awserr.ErrConflict; fixes routing in handleError so the response is ConcurrentModificationException (not LimitExceededException) - handler.go: UpdateApplication now returns *describeApplicationOutput containing the full ApplicationDetail rather than an empty struct; real AWS Kinesis Analytics returns the updated application detail in the response - handler_parity_test.go: table-driven parity tests covering ConcurrentModification on timestamp mismatch, correct-timestamp delete succeeds, UpdateApplication body contains ApplicationDetail with updated code and incremented version, and error type mappings for all key error conditions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(managedblockchain): fix vote threshold, error codes, proposal actions - Add Code field to errorResponse (ResourceNotFoundException etc) - Fix applyVoteThresholdLocked to use float64 division (not integer) - Fix rejection threshold: mathematically-impossible-to-approve logic - Execute Invitation/Removal actions when proposal transitions to APPROVED - Add status query-param filter to ListProposals - Add parity tests covering all of the above Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(iotanalytics): channel/datastore/pipeline/dataset accuracy + audit coverage * parity(pipes): implement missing AWS EventBridge Pipes ops - ConflictException (409) for start/stop when already at desired state - ServiceQuotaExceededException when 1000-pipe limit is hit - Enrichment field included in ListPipes summaries - ValidationException for invalid NextToken base64 - Shared changePipeDesiredState to eliminate Start/Stop duplication - Handler error routing for ErrConflict and ErrQuota Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(iot): thing/certificate/policy/topic-rule/shadow accuracy + audit coverage * parity(redshift): fix parity gaps in DescribeTags/DescribeClusters/DeleteCluster/DescribeClusterSnapshots - DescribeTags: filter by ResourceName, ResourceType, TagKey, TagValue (previously ignored all filter parameters) - DescribeClusters: filter by TagKey and TagValue - CreateCluster: validate MasterUserPassword format when provided (8-64 chars, requires uppercase/lowercase/digit, forbids @/"/space/slash) - DeleteCluster: respect SkipFinalClusterSnapshot=false + FinalClusterSnapshotIdentifier; create final snapshot before deleting when explicitly requested - DescribeClusterSnapshots: add MaxRecords/Marker pagination Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(cognitoidp): user pool/client/user/group/auth-flow accuracy + coverage * parity(apigateway): fix method/integration validation, stage protection, and UpdateUsage - Add RequestParameters to putMethodInput and pass it through PutMethod - Validate authorizationType (NONE/AWS_IAM/CUSTOM/COGNITO_USER_POOLS); require authorizerId when CUSTOM or COGNITO_USER_POOLS - Validate integration type (AWS/AWS_PROXY/HTTP/HTTP_PROXY/MOCK) - FlushStageCache now validates API + stage existence before returning 202 - DeleteDeployment now blocks deletion when a stage references the deployment - UpdateUsage validates usage plan + key existence (was a no-op stub) - Add routing for PATCH /usageplans/{id}/keys/{keyId}/usage -> UpdateUsage - Extract IntegrationTypeMock, AuthTypeCognitoUserPool etc. as constants - Fix proxy_test.go to use backend directly for UNKNOWN_CUSTOM integration setup - Fix existing tests that expected deletion of stage-referenced deployments - Add handler_parity_test.go with table-driven parity tests for all the above Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(omics): store/workflow/run accuracy + coverage * parity(secretsmanager): fix staging labels, cancel rotation, tag limit, replication - PutSecretValue: honor caller's VersionStages exactly; when caller specifies only AWSPENDING (rotation createSecret step), don't force AWSCURRENT onto the new version and don't rotate the existing AWSCURRENT label - PutSecretValue/CreateSecret: reject requests providing both SecretString and SecretBinary (InvalidParameterException, real AWS behavior) - CancelRotateSecret: remove only AWSPENDING label; do not set RotationEnabled=false — real AWS keeps rotation config intact after cancel - TagResource: count net new tag keys only; updating existing keys doesn't increase the total toward the 50-tag limit - ReplicateSecretToRegions: return ResourceExistsException when replica already exists in target region and ForceOverwriteReplicaSecret is false - GetSecretValue: include LastAccessedDate in output (was tracked but not returned) - BatchGetSecretValue: reject when both SecretIdList and Filters are provided; switch filter matching from exact to prefix (consistent with ListSecrets) - Extract resolveStagingLabels helper to keep PutSecretValue below gocognit limit - Fix affected tests to assert real AWS behavior Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(cloudfront): distribution/origin/behavior/invalidation accuracy + coverage * parity(sagemaker): fix missing validations and extend compilation/automl job structs - CreateModel: reject requests that provide both PrimaryContainer and Containers (real AWS returns ValidationException for this combination) - UpdateNotebookInstanceFull: require Stopped status before accepting updates (real AWS rejects updates on InService/Pending/Stopping notebooks) - CompilationJob: add InputConfig, OutputConfig, StoppingCondition fields and SetCompilationJobExtras; handler now captures and persists these at create time - AutoMLJob: add OutputDataConfig, AutoMLJobObjective fields and SetAutoMLJobExtras; handler now captures and persists these at create time - Fix handler_coverage_test to stop notebook before updating (matches real AWS flow) - Add parity_c_test.go with 5 parity tests covering all new behaviors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(eks): cluster/nodegroup/fargate/addon accuracy + coverage * parity(transfer): add missing ops and parity fixes for Transfer Family - Add CertificateIDs to Profile struct and UpdateProfileFull method so UpdateProfile can persist certificate associations (real AS2 feature) - Add CountUserSSHPublicKeys to backend and interface; populate SshPublicKeyCount in ListUsers response (real AWS includes this) - Add UpdateAccessFull with full field support (PosixProfile, HomeDirectoryType, Policy, HomeDirectoryMappings) matching real AWS - Add UpdateConnectorFull support for LoggingRole and SecurityPolicyName - Add ImportCertificate TLS usage support (SIGNING/ENCRYPTION/TLS valid) - Return Certificate body in DescribeCertificate when present - Seed creation-time tags into tagsStore so ListTagsForResource sees them - Replace global validWorkflowStepTypes var with isValidWorkflowStepType function to satisfy gochecknoglobals - Add parity_b_test.go with table-driven parity tests for all new behavior Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(mq): broker/configuration/user accuracy + coverage * parity(efs): fix replication fields, destination lookup, and parity tests - ReplicationDestination: add FileSystemArn, AvailabilityZoneName, KmsKeyID, OwnerId, LastReplicatedTimestamp, Status fields - ReplicationConfiguration: add SourceFileSystemOwnerId field - CreateReplicationConfiguration: auto-assign dest FSID/ARN, populate OwnerId and SourceFileSystemOwnerId from account ID - DescribeReplicationConfigurations: search both source and destination FS IDs - fsToResponse: add ValueInIA, ValueInStandard, ValueInArchive to SizeInBytes - rcToResponse: emit SourceFileSystemOwnerId - parity_a_test.go: 13 tests covering all identified behavioral gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(neptune): cluster/instance/snapshot/parameter-group accuracy + coverage * parity(memorydb): add ExportSnapshot, fix User.ACLNames, Cluster field gaps - Add ExportSnapshot operation (validates snapshot exists, returns it) - Replace UserGroupCount with ACLNames []string in user response - Add Engine field to User struct and userObject response - Add ParameterGroupStatus (default "in-sync") to cluster response - Add MultiRegionClusterName/MultiRegionParameterGroupName to Cluster struct and clusterObject response - Update affected tests: UserGroupCount → ACLNames, op count 45 → 46 - parity_a_test.go: 8 parity tests covering all identified gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(swf): domain/workflow-type/execution/task accuracy + coverage * parity(transcribe): fix JSON tags and add missing response fields - Fix URI/ID JSON tags: MediaFileUri, RedactedMediaFileUri, SubtitleFileUris, VocabularyFileUri, VocabularyFilterFileUri, OutputEncryptionKMSKeyId, ChannelId — AWS uses lowercase-suffix casing, not Go acronym style - Add Media field to transcriptionJobOutput (returned by Get/List/Start) - Add DownloadURI and LastModifiedTime to GetVocabulary and GetMedicalVocabulary - Add CreateTime, LastModifiedTime, UpgradeAvailability to language model output - Add toLanguageModelOutput helper; use it in both Describe and List handlers - Add parity_c_test.go covering all new fields and JSON key names Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(translate): text/terminology/parallel-data/job accuracy + coverage * parity(cloudtrail): fix response accuracy gaps - Default RetentionPeriod to 2557 days (7 years) when not specified - edsToMap: always include AdvancedEventSelectors (as [] when empty) - GetEventSelectors: omit EventSelectors when AdvancedEventSelectors active - GetTrailStatus: add TimeLoggingStarted/TimeLoggingStopped string fields - StartImport/GetImport/StopImport: add CreatedTimestamp/UpdatedTimestamp - DescribeQuery: add CreationTime field - GetQueryResults: add QueryStatistics with TotalResultsCount/BytesScanned - Add keyCreatedTimestamp/keyUpdatedTimestamp constants - Add parity_a_test.go covering all new fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(securityhub): hub/finding/insight/standard accuracy + coverage * parity(backup): add VaultType, LastExecutionDate, IamRoleArn fields - Vault struct gains VaultType field; set to BACKUP_VAULT on CreateBackupVault and LOGICALLY_AIR_GAPPED_BACKUP_VAULT on CreateLogicallyAirGappedBackupVault - DescribeBackupVault and ListBackupVaults now return VaultType in responses; CreateLogicallyAirGappedBackupVault response also includes it - GetBackupPlan now returns LastExecutionDate when UpdateTime is set, matching the existing ListBackupPlans behaviour - ListBackupSelections items now include IamRoleArn, matching real AWS - Add parity_a_test.go with 5 table-driven tests covering all three gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(athena): query-execution/workgroup/data-catalog/named-query accuracy + coverage * parity(codebuild): fix missing ARNs, build inherits, overrides, filter groups, visibility alias - BuildBatch: generate ARN on StartBuildBatch/RetryBuildBatch via batchARNIndex - BatchGetBuilds: resolve ARN → ID via buildARNIndex for ARN-based lookup - RetryBuild: copy ServiceRole, EncryptionKey, Timeout, Environment, Source, Phases from original - StartBuild: introduce StartBuildConfig struct with buildspec/image/computeType/serviceRole/sourceVersion overrides - UpdateProjectVisibility: return publicProjectAlias UUID on PUBLIC_READ - ListCommandExecutionsForSandbox: return full CommandExecution objects instead of IDs - BatchDeleteBuilds: populate buildsNotDeleted for missing IDs - CreateWebhook/UpdateWebhook: accept and persist filterGroups - Add parity_a_test.go covering all above gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(codepipeline): pipeline/execution/stage/action-type accuracy + coverage * parity(codedeploy): revision round-trip, deploymentOverview, full RevisionLocation struct - Add RevisionLocation struct (S3/GitHub/AppSpecContent sub-fields) to backend - Store Revision in Deployment via DeploymentOptions.Revision - GetDeployment and BatchGetDeployments now return revision and deploymentOverview - deploymentOverview reflects synthetic counts based on deployment status - Expand revisionLocationInput wire type with S3/GitHub/AppSpec sub-structs - Add revisionFromWire/revisionToWire converters - Add statusStopped constant (goconst); fix CommitId → CommitID (revive) - Add parity_a_test.go: S3/GitHub revision round-trip, overview, ID format, stop status, computePlatform inherit Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(appsync): graphql-api/schema/resolver/datasource accuracy + coverage * parity(codecommit): fix blob shape, file history filtering, merge commit resolution - GetDifferences: return afterBlob/beforeBlob as {blobId,path,mode} objects (not strings) - ListFileCommitHistory: filter by filePath using per-file commit history tracking - GetMergeCommit: prefer commit with both source+dest as parents over arbitrary commit - Add fileHistory map to InMemoryBackend for path-based commit lookup - Add parity_a_test.go covering blob shape, path filtering, and merge commit resolution Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(comprehend): detection/classifier/recognizer/job accuracy + coverage * parity(bedrock): fix foundation model ARN format, add modelLifecycle, ARN lookup - Fix ARN format: was arn:aws:bedrock::{accountId}:foundation-model/..., now arn:aws:bedrock:{region}::foundation-model/... (region included, no account ID) - Add FoundationModelLifecycle struct and modelLifecycle field to FoundationModelSummary - Seed all foundation models with modelLifecycle.status = "ACTIVE" - GetFoundationModel now matches by ARN in addition to model ID - Add parity_a_test.go covering all three gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(cloudcontrol): resource CRUD + request-status accuracy + coverage * parity(acm): fix SANs include primary domain, InUseBy always [], serial hex format - SubjectAlternativeNames now always includes primary domain as first entry (buildSANList deduplicates; idempotency check updated to compare built list) - DescribeCertificate InUseBy field is always a JSON array [], never null/omitted - Certificate serial numbers use colon-separated hex pairs (e.g. "1a:2b:3c") matching real AWS ACM wire format; formatSerialHex helper replaces big.Int.Text - Remove unused hexBase constant - Add parity_a_test.go covering all three gaps with table-driven tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(route53resolver): endpoint/rule/association/query-log accuracy + coverage * parity(acmpca): add OwnerAccount/Serial to DescribeCA, END_DATE validity, chain fix - DescribeCertificateAuthority now returns OwnerAccount (account ID) and Serial (CA cert serial hex) matching real AWS response shape - IssueCertificate now accepts END_DATE and ABSOLUTE validity types (absolute epoch seconds), as used by Terraform aws_acmpca_certificate - GetCertificate CertificateChain now concatenates CA cert + imported parent chain for subordinate CAs - parity_a_test.go verifies all four behavioral differences Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(s3control): access-point/job/storage-lens/public-access-block accuracy + coverage * parity(appmesh): wrap single-resource responses under resource type key Real AWS App Mesh wraps every Create/Describe/Update/Delete response under the canonical resource type key (e.g. {"mesh": {...}}). All 28 single-resource handler methods now emit this wrapper. Updated all existing tests in handler_audit1_test.go, handler_audit2_test.go, and coverage_boost_test.go to unwrap before asserting. Added parity_a_test.go verifying all 7 resource types and all 4 CRUD operations produce the correct wrapper key. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(servicediscovery): namespace/service/instance/operation accuracy + coverage * parity(apprunner): expose InstanceConfiguration/SourceConfiguration in service output; fix DNSTarget on custom domain ops serviceOutput now includes InstanceConfiguration (Cpu, Memory) and SourceConfiguration (ImageRepository.ImageIdentifier) so DescribeService returns the same fields as the real AWS App Runner API. AssociateCustomDomain and DisassociateCustomDomain returned DNSTarget set to the custom domain name being operated on; fixed to return the service URL (e.g. <id>.<region>.awsapprunner.com) matching real AWS behavior. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(amplify): app/branch/deployment/domain/webhook accuracy + coverage * parity(appconfig): fix environment state to READY_FOR_DEPLOYMENT Environment.State was initialized to "ReadyForDeployment" (camelCase) instead of the correct "READY_FOR_DEPLOYMENT" (SCREAMING_SNAKE_CASE) used by the real AWS AppConfig API. Added parity_a_test.go with table tests covering state accuracy, resource IDs, deployment fields, sequential deployment numbers, hosted config version headers, and Items key in list responses. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(databrew): dataset/recipe/project/job accuracy + coverage * parity(autoscaling): fix LB state, ASG status, tags, instance type, LC fields, step policies, lifecycle hooks - lbStateAdded: "Added" → "InService" (Terraform polls for InService) - ASG Status: remove "Active" default (AWS only sets Status during deletion) - WarmPool Status: same fix - xmlTag: add ResourceId/ResourceType fields (populated from ASG name in DescribeAutoScalingGroups) - xmlInstance: add InstanceType field; makeInstances now looks up LC's InstanceType - xmlAutoScalingGroup: add ServiceLinkedRoleARN (synthesized from account ID) - xmlLaunchConfiguration: add UserData, KernelId, RamdiskId fields - xmlScalingPolicy: add StepAdjustments, MinAdjustmentMagnitude - handlePutScalingPolicy: parse StepAdjustments.member.N.* and MinAdjustmentMagnitude - handleDescribePolicies: serialize StepAdjustments and MinAdjustmentMagnitude - PutLifecycleHook: set GlobalTimeout = HeartbeatTimeout (numberOfRetries=1 default) - PutScheduledUpdateGroupAction: generate ScheduledActionARN - describeMetricCollectionTypesResult: add Granularities element with 1Minute - parity_a_test.go: table tests covering all 11 gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(applicationautoscaling): scalable-target/policy/scheduled-action accuracy + coverage * parity(awsconfig): fix all parity gaps — field casing, ARN generation, RecordingGroup, Scope, ComplianceSummary - Fix ConfigRule JSON tags camelCase → PascalCase (ConfigRuleName, ConfigRuleArn, etc.) - Remove bogus ConfigRule.ComplianceType field; default ConfigRuleState = "ACTIVE" - Add ConfigRuleScope (ComplianceResourceTypes, TagKey, TagValue) to ConfigRule and handler - Add RecordingGroup to ConfigurationRecorder with allSupported/includeGlobalResourceTypes/resourceTypes - Add S3KeyPrefix and configSnapshotDeliveryProperties to DeliveryChannel - Generate AggregationAuthorizationArn in PutAggregationAuthorization - Generate ConfigurationAggregatorArn and accept AccountAggregationSources/OrganizationAggregationSource - Generate ConformancePackArn and ConformancePackId; accept DeliveryS3Bucket/DeliveryS3KeyPrefix - Populate lastStatus/lastStartTime fields in ConfigurationRecorderStatus - Fix ListConfigurationRecorders to return []ConfigurationRecorderSummary (arn, name, recordingScope) - Fix ListStoredQueries to return []StoredQueryMetadata (QueryArn, QueryId, QueryName) - Fix DisassociateResourceTypes to pass ResourceTypes instead of empty string - Fix ComplianceSummary shape to CappedCount/CapExceeded per real AWS API - Fix ConfigRuleEvaluationStatus timestamps from float64 to string - Add parity_a_test.go with 14 table-driven parity tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(ce): cost-and-usage/forecast/anomaly/cost-category accuracy + coverage * parity(appstream): add ComputeCapacityStatus, ImageName/Arn, IdleDisconnect, EnableDefaultInternetAccess to Fleet Real AWS Fleet responses require ComputeCapacityStatus (Desired/Running/InUse/Available). Fleet now stores and returns ImageName, ImageArn, IdleDisconnectTimeoutInSeconds, and EnableDefaultInternetAccess. DescribeUsageReportSubscriptions response key fixed to UsageReportSubscriptions (was Subscriptions). 22 parity table tests added. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(codeartifact): domain/repository/package/version accuracy + coverage * parity(cleanrooms): fix ID key names, ProtectedQuery status SUBMITTED, MemberAbilities in CreateMembership - Add canonical "id", "membershipId", "collaborationId", "configuredTableId", "configuredTableAssociationId", "analysisTemplateIdentifier" dual-key fields to 22 response struct types in backend.go (backward-compat "*Identifier" keys kept alongside the AWS-canonical short keys) - Fix ProtectedQuery and ProtectedJob initial status: "STARTED" → "SUBMITTED" - Add memberAbilities []string to CreateMembership signature (interfaces.go, backend.go, handler.go) so abilities are persisted and returned - Add parity_test.go with 13 tests covering dual-key fields, SUBMITTED status, MemberAbilities roundtrip, ARN format, tag lifecycle, and list summaries Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(emrserverless): application/job-run accuracy + coverage * parity(scheduler): Target in ListSchedules, FLEXIBLE window validation, EcsParameters networking fields - Add Target {Arn, RoleArn} to scheduleSummary so ListSchedules items include the target summary that real AWS always returns - Add validateFlexibleTimeWindow: when Mode=FLEXIBLE, MaximumWindowInMinutes must be >= 1; apply to both CreateSchedule and UpdateSchedule - Add EcsParameters fields: NetworkConfiguration (with AwsvpcConfiguration), CapacityProviderStrategy, PlacementConstraints, PlacementStrategy, Tags - Add corresponding handler structs and from/to conversion helpers - Update handler_refinement2_test to pass MaximumWindowInMinutes when testing FLEXIBLE - Add parity_b_test.go with 9 tests covering the three fix areas Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(resourcegroups): group/query/tag/resource accuracy + coverage * parity(resourcegroupstaggingapi): fix ComplianceDetails JSON field name, add ResourceARNList filter, fix DescribeReportCreation no-report status - ComplianceDetails.KeysWithNoncompliantValues: fix JSON tag from KeysWithNonCompliantValues (wrong casing) to KeysWithNoncompliantValues to match the real AWS API spelling - GetResourcesInput: add ResourceARNList []string field and apply filter in GetResources so callers can scope queries to specific ARNs - DescribeReportCreation: return nil Status when no report exists instead of the non-AWS "NO REPORT" string; real AWS returns an empty response - Update existing tests that asserted "NO REPORT" to expect nil Status - Add parity_test.go covering all three gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(networkmonitor): monitor/probe accuracy + coverage * parity(s3tables): fix ARN key casing, add type field, tableBucketArn in namespaces, wrap replication config, 204 for PutTableReplication - keyTableARN: "tableARN" → "tableArn", keyTableBucketARN: "tableBucketARN" → "tableBucketArn" throughout all responses (CreateTable, GetTable, ListTables, CreateNamespace, GetTableBucketMaintenanceConfiguration, etc.) - GetTableBucket and ListTableBuckets: add "type": "customer" field matching real AWS response for customer-owned table buckets - GetNamespace and ListNamespaces: add tableBucketArn field to response per real AWS GetNamespace/ListNamespaces response shape - GetTableBucketReplication: wrap destinations inside replicationConfiguration object instead of returning destinations at top level - PutTableReplication: return 204 No Content with no body; real AWS returns HTTP 204, not 200 + status body - Update all existing tests to use correct lowercase ARN key names - Add parity_b_test.go with 8 tests covering all fixed gaps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(codeconnections): connection/host/sync-config accuracy + coverage * parity(codestarconnections): fix VpcConfiguration, host status, tag response shape - Add VpcConfiguration struct to backend/handler for CreateHost/UpdateHost - Change initial host status from AVAILABLE to PENDING (real AWS behavior) - Remove Tags from CreateConnection, GetConnection, CreateHost, GetHost, ListConnections, ListHosts responses; Tags only via ListTagsForResource - GetHost omits HostArn (caller knows it); ListHosts items include HostArn - Add host status constants: VPC_CONFIG_DELETING/FAILED/IN_PROGRESS - Fix fieldalignment on VpcConfiguration and updateHostInput structs - Update tests to reflect corrected AWS-accurate behavior Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(cognitoidentity): identity-pool/identity/credentials/roles accuracy + coverage * parity(serverlessrepo): omit empty semanticVersion in template/changeset responses - Fix CreateCloudFormationTemplate response to omit semanticVersion when not provided (was serializing as empty string "") - Fix GetCloudFormationTemplate response same way - Fix CreateCloudFormationChangeSet response same way - Add AddExpiredTemplateInternal test helper to exercise EXPIRED status - Add handler_parity_b_test.go covering: EXPIRED template status, semanticVersion omission, GetApplication 404 on unknown version, templateUrl-only version create, duplicate version 409, ARN format, DeleteApplication 204, UnshareApplication missing orgId 400, ListApplicationVersions sort order, empty policy statements Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(mwaa): environment/cli-token/web-login accuracy + coverage * parity(textract): fix ListAdapters/Versions response shape, add QUERIES validation - ListAdapters: remove Tags from summary, add FeatureTypes (matches AWS AdapterOverview type) - ListAdapterVersions: remove Tags from summary, add FeatureTypes and StatusMessage (matches AWS AdapterVersionOverview type) - AnalyzeDocument and StartDocumentAnalysis: return ValidationException when QUERIES is in FeatureTypes but QueriesConfig is absent or empty - Update TestBatch2 and parity_a tests to reflect corrected AWS behavior - Add parity_c_test.go with table tests for all three fixes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Executed-By: gopherstack/polecats/amber * parity(timestreamwrite): database/table/write-records/batch-load accuracy + coverage * parity(timestreamquery): accuracy + coverage * parity(mediatailor): accuracy + coverage * parity(accessanalyzer): accuracy + coverage * parity(redshiftdata): accuracy + coverage * parity(apigatewayv2): accuracy + coverage * parity(elasticsearch): accuracy + coverage * parity(kinesisanalyticsv2): accuracy + coverage * parity(bedrockagent): accuracy + coverage * parity(account): accuracy + coverage * parity(rdsdata): accuracy + coverage * parity(bedrockruntime): accuracy + coverage * parity(sagemakerruntime): accuracy + coverage * parity(iotdataplane): accuracy + coverage * parity(apigatewaymanagementapi): accuracy + coverage * parity(appconfigdata): accuracy + coverage * fix(dashboard): update CreateHost call for codestarconnections VpcConfiguration+tags signature * fix(ci): golangci-lint — refactor medialive Restore complexity, appstream goimports/shadow/naming, drop stale dashboard nolint * fix(ci): unit test failures across folded services * build(deps): bump actions/cache 5→6 (fold #2377) * build(deps): make upgrade — go get -u ./... + go mod tidy * fix(ci): UI svelte-check type + a11y errors across service pages * fix(ci): restore kinesis page elements for ui-test (Create Data Stream, Total Streams card, placeholder) * refactor(ctx): eliminate context.Background() from cloudformation/lambda/kms/secretsmanager production code — thread request/service ctx for clean cleanup * fix(ci): integration regressions — CloudFront empty-time, S3Tables, IoT, CostExplorer, EMR, IoTAnalytics, AppMesh, DDB streams * refactor(ctx): eliminate context.Background() batch 2 (iotanalytics/firehose/fis/dax/cloudwatchlogs/textract/stepfunctions/sns) * fix(ci): lint + unit regressions from ctx refactor * fix(ci): golangci-lint round 2 — refactor remaining complexity/format/naming issues * refactor(ctx): eliminate remaining context.Background() from production code (batch 3) * fix(ci): terraform shards 0/1/6/7 — align emulator responses with terraform-provider-aws * fix(ci): lint + unit green after ctx refactor (gate both) * fix(ci): integration shards 0/1/2 — align emulator wire shapes with AWS SDK * fix(ci): e2e end-to-end SDK scenarios pass against emulator * style(appmesh): goimports format parity_a_test.go * fix(ci): e2e -tags=e2e compile/scenario errors from parity folds * fix(e2e): kinesis dashboard CreateStream route + UI flow (fixes KinesisAnalyticsV2Dashboard test) * feat(audit): deepen S3 (storage classes, range GET, copy, SSE) + DynamoDB (PartiQL, transactions, conditions) toward LocalStack parity * feat(audit): deepen EC2 (Describe* filter matching, SG/VPC/ENI/EBS) + Lambda (invoke, ESM, layers, versions) toward LocalStack parity * feat(audit): deepen IAM (policy eval, roles, instance profiles) + SQS (FIFO, DLQ, visibility, batch) toward LocalStack parity * feat(audit): deepen SNS (fan-out delivery, filter policies, FIFO) + CloudFormation (intrinsics, real resource provisioning) toward LocalStack parity * feat(audit): deepen RDS (instance/cluster lifecycle, snapshots, replicas, param groups) toward LocalStack parity * test(rds): set ApplyImmediately=true so ModifyDBInstance class change applies now (matches AWS deferral semantics added in audit) * feat(audit): back RDS Data API with a real in-memory SQL engine toward LocalStack parity The RDS Data API previously executed no SQL: ExecuteStatement returned an empty record set and ExecuteSql always reported 0 rows updated, so the service modelled the control plane only. This closes the #1 functional gap versus LocalStack (which runs a real database behind the Data API). - Add services/rdsdata/engine.go: a pure-Go (modernc.org/sqlite, no cgo) per-(region, resourceARN) in-memory SQL engine. Each Aurora resource gets an isolated shared-cache database pinned by a keep-alive connection, scoped by an engine-instance nonce so two backends never alias the same store. - ExecuteStatement / BatchExecuteStatement / ExecuteSql now run statements for real, returning genuine records, column metadata and update counts. Anything the engine rejects (e.g. DML against a table that was never created) degrades to the historical empty-success envelope, preserving backward compatibility. - BeginTransaction opens a matching engine transaction; Commit/Rollback finalize it, giving real atomic visibility for statements tagged with a transactionId. - Restore replays the recorded statement log so table state survives a snapshot/restore cycle (best-effort for parameterised/trimmed statements). - README: correct the stale "image-based only" Lambda claim — Zip packaging across the managed runtimes is supported and already implemented. Adds engine_test.go (round-trip, isolation, transactions, batch, snapshot replay, reset, lenient fallback); package coverage 89.6%. Existing unit and integration tests are unchanged and still pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GmKxLo2kS6qNWrTFuHhaEb * feat(audit): deepen API Gateway (HTTP API routing, VTL, proxy integrations) + KMS (key lifecycle, grants, rotation) toward LocalStack parity * test(terraform): RDS Data engine round-trip — create cluster, add data, query, destroy Adds an `engine_roundtrip` case to TestTerraform_RDSData that provisions an Aurora cluster via Terraform, then drives the full Data API data path against it: CREATE TABLE, INSERT rows, and SELECT them back asserting the real round-tripped values (long and string fields) plus column metadata. The terraform harness tears the cluster down on cleanup, so the case covers create-engine -> add-data -> query -> destroy end to end and exercises the new in-memory SQL engine through the SDK + Terraform path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GmKxLo2kS6qNWrTFuHhaEb * feat(audit): deepen STS (AssumeRole variants, credential issuance, caller identity) + CloudWatch (metric aggregation, alarm state machine) toward LocalStack parity * feat(rdsdata): bind named parameters in ExecuteStatement ExecuteStatement previously dropped bound parameters — only the batch path threaded them — so the common Aurora Data API pattern (e.g. `WHERE id = :id`) fell back to the empty-result envelope. The backend method now accepts variadic SQLParameters (keeping every existing call site source-compatible) and the handler forwards req.Parameters, so named placeholders are substituted on both the write and read paths. Adds a parameterised round-trip test (insert with :id/:name, then select by :id). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GmKxLo2kS6qNWrTFuHhaEb * feat(audit): deepen EventBridge (event-pattern matching, target delivery, scheduled rules) toward LocalStack parity * fix(test): RDS FullLifecycle — set ApplyImmediately for the instance-class change TestSDK_RDS_FullLifecycle modified DBInstanceClass without ApplyImmediately and asserted the new class took effect immediately. Since RDS ModifyDBInstance was deepened to defer instance-class changes to PendingModifiedValues (AWS-accurate behaviour when ApplyImmediately is unset), the live class correctly stayed unchanged and the assertion failed. The test now passes ApplyImmediately=true, which is how a real client forces an immediate instance-class change. Pre-existing failure on the parity-sweep base, unrelated to the rdsdata engine change; surfaced by running CI for the first time. Co-A…
parity: full 154-service deep-scan rewrite of parity.md (100% AWS-emu… …lation audit) (#2339) * parity: full 154-service deep-scan rewrite of parity.md Rewrites parity.md as a complete per-service audit covering AWS-emulation parity, performance, resource leaks, and UI/console coverage for every service in services/. Includes a dedicated DynamoDB/DynamoDB Streams/DAX deep dive (priority service) and a cross-cutting systemic-findings section (non-opaque pagination, missing __type error envelopes, full-collection sort-per-list, mock data-plane responses, unbounded maps, synchronous lifecycles). Every finding is code-cited (file:line). Goal: 100% real AWS emulation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * parity: add region-isolation audit (DynamoDB + groups 2,3,6,8,9,11) Adds a Region isolation audit section: per-service classification (ISOLATED/PARTIAL/LEAKS/GLOBAL) of whether state is partitioned by region and whether ops derive region from awsmeta.Region(ctx). Includes the systemic flat-map/fixed-region-ARN finding and the fix pattern. Remaining service groups to follow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * parity: complete region-isolation audit for all 154 services Replaces the partial region section with the full per-service classification (ISOLATED / PARTIAL / LEAKS / GLOBAL) across all 20 service groups. Tally: 49 ISOLATED, 25 PARTIAL, 60 LEAKS, 22 GLOBAL — confirming the systemic finding that most backends use a flat name/ARN-keyed map with no region dimension and build ARNs from a fixed default region. Each entry is code-cited with the fix pattern; DynamoDB is the reference implementation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * logging: context-aware logger everywhere; eliminate slog.Default() Thread context through persistence so every record uses the context-aware logger instead of the global default: - persistence.Persistable now takes ctx: Snapshot(ctx)/Restore(ctx,data). The Manager holds a lifecycle baseCtx for the debounced async save path and tags each entry's logger worker=<service>-persistence; all manager logging goes through logger.Load(ctx) with *Context methods. - Migrate all ~131 service Snapshot/Restore impls, interface assertions, call sites, and tests to the new signatures; replace every slog.Default() in service persistence with logger.Load(ctx).WarnContext(ctx, ...). - Add logger.WithWorker(ctx, service, job) (records log as worker=<svc>-<job>), documented with the pointer-in-ctx safety rules (copy-on-write, derive from the lifecycle ctx, never enrich in a loop, never SetDefault at runtime). - No context.Background() introduced: prod call sites use the request/root ctx, tests use t.Context(). - Enforce via golangci forbidigo (slog.Default()/slog.New() forbidden outside pkgs/logger) alongside the existing sloglint no-global/context settings. - Document the logging discipline in AGENTS.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * logging: tag background workers + remove DAX embedded logger - Add worker=<service>-<job> tagging at the background-worker boundary: startBackgroundWorkers wraps each worker ctx via logger.WithWorker, and the auto-purge worker logs under worker=purge-worker. - DAX data plane: drop the embedded *slog.Logger field on Server; store a lifecycle baseCtx tagged worker=dax-dataplane and log via logger.Load(ctx). NewServer/EnableDataPlane/newDataPlane now take context.Context (sourced from the provider JanitorCtx) instead of a *slog.Logger. - Add a -race copy-on-write test (pkgs/logger) proving concurrent WithService/WithWorker/AddAttrs derivation never mutates the shared parent logger or leaks child attributes upward. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * persistence: centralise snapshot marshal/unmarshal via ctx-aware helpers Add persistence.MarshalSnapshot / UnmarshalSnapshot and safemap.ClonePtrMap / CloneRegionalPtrMap, then migrate every service backend's Snapshot/Restore to the shared helpers. The helpers emit a DebugContext record on success (silent at the default info level, visible with --log-level debug) and a WarnContext on failure, which gives the previously-unused ctx parameter a purpose. This clears the 188 revive "unused-parameter ctx" findings and the stepfunctions sloglint finding structurally, rather than per-method, and removes ~110 lines of hand-rolled marshal/error/log boilerplate net. Also fixes the remaining lint blockers on the branch: - cli.go startPurgeWorker: drop the overwritten log param (staticcheck SA4009) - dax tests: context.TODO() instead of nil Context (staticcheck SA1012) - cli_test / opensearch test: add t.Helper() (thelper) - appstream Restore: move //nolint to the func line; lll/golines/nolint cleanups - gofmt/golines formatting on lambda & stepfunctions settings golangci-lint run ./...: 0 issues. go test ./... -short: pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * chore: remove broken AI release-notes tooling (pkgs/releaser) The AI release-notes generator (Gemini/Copilot) was broken and unused — nothing in the repository imported it. Remove the package and unwire it: - delete pkgs/releaser (incl. cmd/releaser) - drop its sole dependency github.com/github/copilot-sdk/go (and the now-unused transitive github.com/google/jsonschema-go) via go mod tidy - remove the build-releaser Makefile target - prune the AI release-notes steps (use_ai_releaser input, COPILOT_TOKEN env, Build Releaser / Install Copilot CLI / Generate Release Notes) from the release workflow; GoReleaser now runs with plain `release --clean` The rest of the release pipeline (tagging, GoReleaser, GHCR, cleanup) is intact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * awserr: add protocol-aware APIError/Classify/Write responder (Phase 2) Extend pkgs/awserr beyond sentinels into a single AWS-error responder so services can declare a map[error]APIError table and emit the correct wire envelope (JSON 1.0/1.1, Query-XML, REST-XML) via one call instead of hand-rolling __type/<Error> serialisation + CRC32 headers per service. - APIError{Code,Message,HTTPStatus} protocol-agnostic error description - Classify(err, table, fallback) matches wrapped sentinels via errors.Is - Write(c, proto, e) serialises the per-protocol envelope + Content-Type Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * stepfunctions: use x/sync semaphore.Weighted for parallel/map limits (Phase 3) Promote golang.org/x/sync to a direct dependency and replace the hand-rolled chan struct{} semaphores in the ASL executor's Parallel and Map state fan-outs with semaphore.Weighted. Both sites already did a blocking, ctx-aware acquire (select on send vs ctx.Done), which Acquire(ctx, 1) expresses directly and more readably with identical semantics. Other concurrency sites (background pollers with non-blocking try-acquire, lifecycle WaitGroups) are intentionally left as -is since x/sync adds nothing there. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * dax,testleak: bound DAX attr dictionary + add goleak detection (Phase 4) Leak prevention: - Bound the DAX data-plane attribute-list dictionary (attrToID/idToAttr) with a hard cap. Eviction is unsafe because a client may reference any previously -assigned id, so on overflow the server stops allocating and degrades to the empty-list id instead of growing without limit. Legitimate workloads register only a handful of distinct attribute sets, so the cap is never hit in practice. - Add pkgs/testleak wrapping go.uber.org/goleak (promoted to a direct dep) with a shared ignore list, and opt in worker-heavy packages whose tests already clean up: dax/dataplane, scheduler, pipes, s3, dynamodb. goleak surfaced genuine pre-existing test-hygiene leaks in sqs/lambda/stepfunctions (backends constructed without Close); those packages are left for a focused follow-up rather than shipping red CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * collections: add generic Filter/Map/Values/SortedKeys helpers (Phase 6) Add pkgs/collections with the type-safe slice/map transformation helpers the stdlib slices/maps packages don't provide (Map, Filter, MapValues, Values, SortedKeys), to replace the hand-rolled range-and-append list-builders repeated across handlers. A reflect-free generic DeepClone was evaluated and dropped: a correct deep copy of arbitrary pointer/slice-containing types is not possible without reflection or codegen, and safemap.ClonePtrMap already covers the snapshot copy path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * worker: add leak-safe ticker primitive for janitors (Phase 7) Add pkgs/worker.RunTicker, a single owner of the background-sweep loop that ~30 service janitors hand-roll (time.NewTicker + defer Stop + ctx.Done select). It applies the standard worker logging tags, optionally bounds each sweep with a timeout, and always stops the ticker on return so the loop cannot leak. Adopt it in the sqs and acm janitors as references. pkgs/httpclient and pkgs/lifecycle from the plan were evaluated and dropped: every HTTP client in the tree already sets a tuned per-service timeout (nothing uses http.Get/DefaultClient/bare http.Client{}), and a central goroutine supervisor would require rewiring every janitor/go func — too invasive to do safely here, with worker + goleak already covering leak-safety incrementally. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * awstest: add shared handler-test harness (Phase 5, Tier A) Add internal/awstest with NewContext/NewJSONContext/DecodeJSON to collapse the echo.New() + httptest.NewRequest + recorder + NewContext wiring repeated across 300+ handler test files. Adopt it in the account service's test helper as a reference. Production code is untouched, so there is zero protocol-parity risk. Note on Phase 2/awserr fan-out: blanket migration of the 67 hand-rolled error tables is intentionally deferred. The error envelopes are heterogeneous (dynamodb carries extra Item/CancellationReasons fields, REST services use plain application/json without CRC32), so a generic responder cannot replace them without per-service fidelity loss. awserr.Write remains available and tested for services whose envelope matches one of its protocols. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * stepfunctions: enable goleak detection (Phase 4 follow-up) Add a goleak TestMain to the stepfunctions package and stop the two SQS integration backends its tests construct (t.Cleanup(sqsBackend.Close)), which goleak flagged as leaked runJanitor goroutines. No production changes; no goroutine-ignore escapes needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * services: adopt worker.RunTicker in 4 more janitors (Phase 7) Convert the bedrock, eventbridge, support and timestreamwrite janitors — whose run loops were the exact ticker + ctx.Done + single-sweep shape — to worker.RunTicker, matching the sqs/acm references. The sweep ctx now carries the worker logging tags. Other janitors with multi-statement tick branches, extra select cases, or stop-channel patterns were intentionally left unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * sqs: stop move tasks on Close + enable goleak detection (Phase 4 follow-up) Production fix: Close() now cancels in-flight StartMessageMoveTask goroutines (via each move task's stored cancel func) in addition to stopping the janitor, so no background goroutine outlives the backend. goleak flagged both runJanitor and runMoveTask as leaking. Tests: add a goleak TestMain and route every backend construction through a t.Cleanup(b.Close) (constructor helpers gained a *testing.T param; inline NewHandler(NewInMemoryBackend()) sites were extracted to a cleaned-up var). No assertions changed; no goroutine-ignore escapes needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * lambda: tie async invocations to backend lifecycle + enable goleak (Phase 4 follow-up) Production fix: async (Event) invocation goroutines spawned by enqueueAsyncInvocation were detached and could block in waitForAsyncResult for up to timeout+grace with nothing tied to shutdown. Add a shutdown channel + asyncWG: the spawn sites run via asyncWG.Go, waitForAsyncResult selects on shutdown, and Close() closes the channel (once) and waits for the group after shutting down the function-URL/runtime servers. goleak confirmed the leak. Tests: add a goleak TestMain and a closeBackend(t, b) helper; route all NewInMemoryBackend sites through t.Cleanup(b.Close). No goroutine-ignore escapes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * services: replace hand-rolled pointer-deref helpers with pkgs/ptrconv dms, dynamodb and resourcegroupstaggingapi each defined private *string/*bool deref helpers (ptrStr/ptrBool/derefStr/derefOrEmpty/ptrStringValue) with semantics identical to ptrconv.String/Bool. Route all call sites through ptrconv and delete the duplicates (dms.ptrStr alone had 131 callers). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * s3: replace nilStringIfEmpty with pkgs/ptrconv.NilIfEmpty The private nilStringIfEmpty helper was identical to ptrconv.NilIfEmpty (empty string -> nil, else pointer). Route all 19 call sites through ptrconv and remove the duplicate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * awserr: use canonical X-Amzn-Requestid header literal The canonicalheader linter flagged the non-canonical "x-amzn-RequestId" literal in requestID(). Header.Get is case-insensitive so behaviour is unchanged; this matches the canonical form already used in glacier/apigateway. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * services: adopt collections.SortedKeys for the sort-map-keys idiom (Phase 6) Replace the hand-rolled `keys := make([]T,0,len(m)); for k := range m { keys=append(keys,k) }; sort.Strings(keys)` idiom with a single collections.SortedKeys(m) call across 80 service files. Also harden the helper: SortedKeys now always returns a non-nil slice (empty for a nil/empty map), faithfully matching the idiom it replaces, so callers that marshal the result emit a JSON array rather than null. This fixes a codecommit regression (ListAssociatedApprovalRuleTemplatesForRepository returning null for an empty template set) and keeps all call sites behaviour-identical. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * worker: make pkgs/worker the resilient background-work standard Enrich the worker primitive so all background work is panic-resilient and has uniform start/stop/timer hooks: - RunTicker now recovers from sweep panics (logged with worker tags, loop continues) — all existing adopters get resilience with no call-site change. - Add functional options (WithImmediate, WithOnPanic) so janitor variants are absorbed by the primitive rather than hand-rolled. - Add RunTickerN for janitors with multiple independent tickers. - Add Group: a per-backend supervisor bundling tracked goroutines (Go), periodic sweeps (Ticker), and one-shot cancellable timers (After) under one panic-recovered lifecycle, with a deterministic Stop that cancels, stops pending timers, and joins — the standard replacement for raw time.AfterFunc and untracked `go func` that outlive a backend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * eks,transfer,autoscaling,acm: stop background timers on shutdown (leak fix) These backends scheduled delayed state transitions / hook expiries with raw time.AfterFunc but never stopped them, so the timer goroutines (and their backend-capturing closures) outlived teardown. - eks, transfer: had no Close at all. Route the state-transition timers through a per-backend worker.Group (panic-recovered) and add Close()->work.Stop(), invoked from a new handler Shutdown (service.Shutdowner, called at server shutdown via cli.go). - autoscaling: add a defensive Close() that stops any in-flight lifecycle-hook expiry timers, wired into a new handler Shutdown. - acm: add Close() that stops all in-flight auto-validation timers and call it from the existing handler Shutdown (previously only the janitor was stopped). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * service: add AccountRegion helper to collapse provider config boilerplate ~140 service providers repeat the same config.Provider type-assertion to pull account ID and region off the AppContext. AccountRegion centralises it with the exact same empty-fallback behaviour, ready for fan-out adoption. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * comprehend,timestreamquery: hoist fixed regexes to package level These compiled the same fixed regex on every call: comprehend recompiled the email/SSN PII patterns per DetectPiiEntities/ContainsPIIEntities request (hot path), and timestreamquery recompiled the rate() schedule regex on every next/previousInvocationTime call. Hoist them to package-level vars compiled once at init. User-supplied/dynamic patterns (cloudwatchlogs query terms, macie2 custom-identifier regex) are intentionally left compiled at call time. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * service: add AccountRegionOrDefault for the default-seeded provider idiom The empty-fallback AccountRegion only fits providers that intentionally leave account/region empty when unconfigured. The dominant provider idiom instead seeds config.DefaultAccountID/DefaultRegion and overwrites from config.Provider. AccountRegionOrDefault matches that exactly so ~110 providers can collapse the block without changing the no-config fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * services: adopt service.AccountRegion(OrDefault) across 100 providers Collapse the repeated config.Provider account/region extraction block in provider.go into a single helper call: ec2/lambda use AccountRegion (empty fallback), and 98 default-seeded providers use AccountRegionOrDefault (which falls back to config.DefaultAccountID/DefaultRegion). Behaviour-preserving; providers with extra GlobalConfig reads, nil-ctx wraps, per-branch backend construction, or non-default fallbacks were left untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * worker: fix data race in Group.After timer tracking The `var t *time.Timer; t = time.AfterFunc(d, func(){ ...uses t... })` pattern let the fired callback read t while the scheduling goroutine wrote it (-race flagged it via eks/transfer state-transition tests). Track timers by an integer id captured before scheduling instead, so the callback never reads the timer pointer it is stored under. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * services: migrate 27 janitors to worker.RunTicker/RunTickerN Replace the remaining hand-rolled time.NewTicker janitor loops with the worker primitives, standardising on panic-recovered, leak-safe background sweeps: - single-sweep janitors (with per-sweep TaskTimeout) -> worker.RunTicker - multi-ticker janitors (cloudwatch metric+alarm, dynamodb table+TTL) -> worker.RunTickerN with one Sweep per cadence Hand-rolled recover() blocks (s3, dynamodb) are dropped since RunTicker now recovers centrally; all telemetry (RecordWorkerTask/Items) and sweep logic is preserved. No hand-rolled janitor ticker loops remain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * services: adopt arn.Build for hand-rolled ARNs (66 files) Replace fmt.Sprintf("arn:aws:...") ARN construction with pkgs/arn.Build / BuildS3 across services, deriving the partition centrally and covering the global (empty-region) and iam/s3 special forms. Behaviour-preserving: every converted ARN is byte-identical (verified by the services' existing ARN assertions). Sites with a local variable named `arn` had that local renamed (arnStr/fnARN/planARN) to avoid shadowing the package; shapes not expressible by arn.Build (e.g. macie2's iam service-linked-role ARN) were left untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * eks,autoscaling,transfer: add goleak TestMain to guard timer leaks With state-transition/hook timers now stopped via Close (worker.Group / timer cleanup), add a goleak TestMain to each so any future background-goroutine leak (an unstopped timer, a new janitor without shutdown) fails the suite. No test cleanup rollout was needed — the suites already leave no goroutines running. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * worker: root Group at the service context + own logging/metrics Redesign worker.Group so background work is service-context-rooted and the package owns the cross-cutting concerns: - NewGroup(ctx, service, opts...) derives from the service/lifecycle context (no more context.Background); it always logs via the context logger. - Inject a Metrics sink (WithMetrics, default pkgs/telemetry-backed) so the worker auto-emits per-sweep task status (success/panic) and tests can fake it. - Group.Ticker is now the self-contained periodic primitive (recovery + per-sweep timeout + WithImmediate); After/Go/Stop unchanged in spirit. Thread the service context through the eks and transfer backend constructors (NewInMemoryBackend(ctx, ...)) — providers pass JanitorCtx, tests pass t.Context(), and internal/teststack threads it via the handlers struct. No context.Background() outside the service-context initialization. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * worker: Group records only the panic task, leaving sweep telemetry intact Janitors emit success/items/depth telemetry at a finer granularity than the ticker that drives them, so auto-emitting a per-ticker "success" would double-count or coarsen it. Group now records only the "panic" task (the failure a sweep cannot catch) via the injected Metrics; sweeps keep their own telemetry. Metrics is narrowed to RecordTask. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo * services: standardize all janitors on worker.Group; drop RunTicker/RunTickerN Convert all 32 remaining janitors from worker.RunTicker/RunTickerN to the worker.Group pattern: Run(ctx) creates a service-context-rooted Group, registers its sweeps via g.Ticker (multi-ticker janitors register several), blocks on ctx.Done, then g.Stop()s — preserving the existing StartWorker/cancel lifecycle while routing every background worker through one resilient, panic-recovering, service-context-rooted primitive. mediaconvert's fire-and-forget StartJanitor and cloudwatch/dynamodb's multi-ticker loops are expressed as Group registrations. With no callers left, RunTicker, RunTickerN and the Sweep type are removed. Also thread the service context through the remaining external callers of the eks/transfer constructors: the cloudformation phase3-6 test-backend helper chain (gaining a *testing.T) and internal/teststack. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018oP7aXeXn2Eb1SL874KkPo --------- Co-authored-by: Claude <noreply@anthropic.com>
PreviousNext