parity: per-service AWS emulation deepening (DO NOT auto-merge — for review)#2334
parity: per-service AWS emulation deepening (DO NOT auto-merge — for review)#2334agbishop wants to merge 133 commits into
Conversation
…matchers & case-insensitive prefix/suffix
…header + DeleteSecret force/recovery conflict - handleError now sets the X-Amzn-Errortype response header (awsJson1_1 protocol) in addition to the body __type, matching real AWS so SDKs/CLI can construct the typed exception from the header. - DeleteSecret now rejects ForceDeleteWithoutRecovery combined with RecoveryWindowInDays with InvalidParameterException, matching AWS's mutual-exclusivity rule (previously the recovery window was silently ignored). - Adds table-driven tests for both behaviors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ce comparator Add the AWS Step Functions StringMatches glob comparator to ChoiceRule. '*' matches zero or more characters; backslash escapes the next character so \* matches a literal asterisk and \\ a literal backslash. Matching is anchored at both ends, implemented via a backtracking two-pointer algorithm to avoid catastrophic backtracking. Adds white-box and end-to-end Choice table tests covering AWS doc examples, escaping, and anchoring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…hape + correct filter-pattern semantics - Fix filter-pattern term semantics to match AWS: '?' is now OR (optional), '-' is exclusion, plain/quoted terms are AND. Previously '?' was wrongly treated as negation. '?' terms are ignored when combined with required/exclude terms, mirroring documented AWS behaviour. Shared by FilterLogEvents, subscription filters and metric filters. - FilterLogEvents now returns FilteredLogEvent objects (logStreamName + eventId) instead of bare OutputLogEvent, matching the AWS response shape; results are interleaved across streams and sorted ascending by timestamp. - Add logStreamNamePrefix support and enforce InvalidParameterException when logStreamNames and logStreamNamePrefix are both set. - Return searchedLogStreams (empty list, per AWS deprecation contract). - Table-driven tests for OR/exclude patterns, event shape, prefix filtering, and mutual-exclusivity error. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…y on closed shards
… nested anything-but, String.Array filter matching
…ation ChangeResourceRecordSets DELETE now enforces AWS's exact-match rule: a DELETE must supply the same TTL and the same (unordered) set of resource record values (or matching AliasTarget) as the existing record set. Mismatches return InvalidChangeBatch with the AWS message 'Tried to delete resource record set [...] but the values provided do not match the current values' instead of silently deleting. Adds table-driven backend tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…import (ImportRestApi/PutRestApi)
Replace the canned ImportRestApi/PutRestApi stubs (which returned a fixed
{id:stub0000,name:imported-api} and created zero resources) with a real
importer that parses Swagger 2.0 and OpenAPI 3.0 documents and materialises
the full resource tree (parentId/pathPart/path), methods (authorization,
requestParameters, requestModels, operationName, apiKeyRequired from security),
integrations from x-amazon-apigateway-integration (type AWS/AWS_PROXY/HTTP/
HTTP_PROXY/MOCK, integrationHttpMethod, uri, requestTemplates, passthrough,
timeout), integration responses (default vs selectionPattern), method responses
and models (definitions / components.schemas).
Also fixes routing: POST /restapis?mode=import now dispatches to ImportRestApi
(previously always CreateRestApi) and PUT /restapis/{id} to PutRestApi
(previously unrouted) with merge/overwrite semantics, passing the raw spec body
through verbatim instead of corrupting it with path/query field injection.
Errors use AWS codes (BadRequestException/NotFoundException). Table-driven
tests cover Swagger 2.0, OAS 3.0, integration/response/model fidelity, REST
routing, merge vs overwrite, and error cases.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…iner/network validation Add the structural validation real AWS ECS applies to RegisterTaskDefinition, surfaced as ClientException (matching the AWS error code): - containerDefinitions must be non-empty - each container requires a well-formed name and an image - container names must be unique within a task definition - networkMode must be one of bridge/host/awsvpc/none - awsvpc mode: a port mapping hostPort (when set) must equal its containerPort - FARGATE compatibility requires networkMode=awsvpc plus task-level cpu+memory Also fix errorCode to return the bare AWS exception code (e.g. ClientException) in __type / x-amzn-errortype instead of the full human-readable message. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…utes over received subset ReceiveMessage now computes MD5OfMessageAttributes over only the message attributes actually returned to the consumer (per MessageAttributeNames filtering), matching real AWS. Previously the send-time digest over the full attribute set was echoed, which fails SDK-side checksum validation when a consumer requests a subset. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nfiguration Qualifier resolution + runtime enum validation - GetFunction and GetFunctionConfiguration now honor the ?Qualifier= query param (version number, alias name, or $LATEST), returning the immutable version snapshot with the version/alias-suffixed ARN and resolved Version, matching real AWS. Previously both always returned the live $LATEST config. - Added InMemoryBackend.GetFunctionByQualifier + complete versionToConfig mapping (preserves Layers/VpcConfig/TracingConfig/Version etc., unlike the lossy invocation-path versionToFn). - CreateFunction/UpdateFunctionConfiguration now reject unknown runtimes with InvalidParameterValueException (enum-value-set message), accepting current + AWS-recognized deprecated runtimes; unknown identifiers are rejected. Docker run path untouched (validation is control-plane only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…n identity policies Previously identity policy documents (managed policies, policy versions, inline user/role/group policies) were only checked with json.Valid, so structurally valid JSON that violated the IAM policy grammar was silently accepted, diverging from real AWS and LocalStack which return MalformedPolicyDocument. Added validateIdentityPolicyDocument enforcing: Version must be 2012-10-17/2008-10-17, Statement required and non-empty, Effect exactly Allow/Deny, exactly one of Action/NotAction and Resource/NotResource, and no Principal in identity policies. Wired into CreatePolicy, CreatePolicyVersion, PutUserPolicy, PutRolePolicy, PutGroupPolicy. Updated placeholder test docs to valid documents. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📊 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: Sat, 20 Jun 2026 04:57:12 GMT |
…re maintains alarm state
…list SET UpdateExpression SET on a list index beyond the current end now appends the value to the end of the list (no NULL padding, no error), and REMOVE on an out-of-range list index is a silent no-op. Previously both returned ErrIndexOutOfRange, failing the whole UpdateItem. This matches documented AWS DynamoDB behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…stitution, recipient limits
- SendTemplatedEmail now substitutes {{var}} placeholders from TemplateData
JSON into stored subject/text/html (previously stored raw placeholders).
- SendBulkTemplatedEmail merges request-level DefaultTemplateData with
per-destination ReplacementTemplateData and renders each message; validates
template existence up front (TemplateDoesNotExist for missing template even
on empty batch).
- Enforce AWS 50-recipient-per-message cap (To+Cc+Bcc) on SendEmail and
SendTemplatedEmail with MessageRejected.
- Reject malformed TemplateData JSON with InvalidParameterValue.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…crypt/ReEncrypt key-id hint mismatch
…ctors, ARN field, label-move semantics
…nd malformed-range 200 fallback
…role ARN AWS drops any IAM path on the role when forming the assumed-role principal ARN: a role at arn:aws:iam::ACCT:role/team/dev/MyRole yields arn:aws:sts::ACCT:assumed-role/MyRole/SESSION (only the bare role name is carried over). buildAssumedRoleArn previously retained the full path, producing assumed-role/team/dev/MyRole/SESSION which diverges from real STS and from AWS CloudTrail/IAM policy matching. Add roleNameFromResource to strip the path; covers AssumeRole, AssumeRoleWithWebIdentity, and AssumeRoleWithSAML which share the construction. Add table-driven tests. Also remove an accidentally-committed goimports atomic-write temp file (.models.go5239108928845688131), a malformed duplicate of models.go. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ables, GetPartitions Real AWS Glue enforces MaxResults (1-100 for catalogs, 1-1000 for partitions) and returns NextToken when more results are available. Without this, SDK clients that automatically paginate would silently receive truncated or unbounded results. Adds paginateSlice[T] generic helper, MaxResults validation, and table-driven tests covering first page, continuation, and out-of-range MaxResults. (go-ossso)
- Fix GetSessionEndpoint hardcoded us-east-1 region (now uses b.region) - Validate empty QueryString in StartQueryExecution (→ InvalidRequestException) - Validate WorkGroup State (only ENABLED/DISABLED accepted, not arbitrary strings) - Omit empty NextToken from ListDataCatalogs response (field fidelity) - Reject GetQueryResults on non-SUCCEEDED queries (CANCELLED/FAILED → 400) - Add workGroupStateEnabled/Disabled constants; replace raw string literals Tests: parity_deepen_test.go covers all five fixes with table-driven cases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…reateVolume/DescribeVolumes Real AWS sets IOPS/throughput defaults per volume type (gp3: 3000/125, gp2: derived from size), requires Iops for io1/io2, and returns these fields in CreateVolume and DescribeVolumes responses. Previously all three were ignored and omitted. - Add Iops and Throughput fields to Volume struct - Add SetVolumePerformance backend method (parallel to SetVolumeEncryption) - Extract parsePositiveInt and defaultIOPSForType helpers to satisfy gocognit - Add volTypeDefaultGP2/gp3DefaultIOPS/etc constants (no magic numbers) - Update volumeItem, createVolumeResponse, and toVolumeItem to return the fields - Table-driven tests: gp3 defaults, custom IOPS/throughput, gp2 size-derived, io1/io2 rejection without Iops, DescribeVolumes round-trip Fixes: go-evvxi
…Id (go-8dvrq)
Two genuine AWS parity gaps fixed:
1. Error responses for 400s were missing __type. AWS SDK clients parse __type
to deserialize errors into typed structs (ResourceInUseException,
InvalidArgumentException, UnknownOperationException). Only 404s had __type;
all 400s returned a bare {message:...} body. Now each error case sets the
correct __type matching real Firehose behavior.
2. PutRecordBatch RequestResponses contained empty structs instead of per-record
{RecordId} entries. Real AWS returns one entry per input record with a unique
RecordId on success. Callers use RecordId for tracking and deduplication.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lvhj)
AWS ECR DescribeImages accepts filter: { tagStatus: "TAGGED"|"UNTAGGED"|"ANY" }.
Previously the filter field was absent and silently ignored — all images were
returned regardless. ListImages already had this filtering via passesTagFilter;
DescribeImages now uses the same function.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ListUpdates was always returning [], DescribeUpdate was synthesizing a fake record for any ID. Add updates map to InMemoryBackend, store Update objects in UpdateClusterConfig, UpdateClusterVpcEndpoint, UpdateClusterVersion, UpdateNodegroupVersion, and UpdateNodegroupConfig handler. Fix ListUpdates to return sorted stored IDs. Fix DescribeUpdate to look up real records and return 404 for unknown IDs.
…-2vbyo) Two genuine AWS behavioral gaps fixed: 1. MountTargetArn missing from mtToResponse — AWS always returns this field in CreateMountTarget and DescribeMountTargets responses. The backend already tracked it; just wasn't included in the JSON shape. 2. DescribeMountTargets ?AccessPointId= filter — real AWS supports resolving mount targets via an access point ID. The handler now looks up the access point to obtain its FileSystemId, then delegates to the existing DescribeMountTargets backend with that filter. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ip tabs Expand the S3 dashboard to surface backend-supported bucket features that had no UI: a functional Public Access Block editor in the Permissions tab plus five new tabs — Object Lock (default retention), Event Notifications (read-only summary), Replication (view + delete), Server Access Logging (target bucket/prefix), and Object Ownership controls. Each lazily loads via switchTab using the existing tab pattern and the AWS SDK. Lint (oxlint), svelte-check (0 errors) and the s3 vitest suite pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197MBJdH1bdve4Z3RR9pffn
Complete the comprehensive S3 dashboard expansion: a canned-ACL selector with current grant count in the Permissions tab (GetBucketAcl/PutBucketAcl), and four configuration tabs — Analytics, Metrics, Inventory, and Intelligent-Tiering — that list stored configurations by Id with delete (List*/Delete* commands; the backend stores these configs and round-trips them). Lint, svelte-check (0 errors) and the s3 vitest suite pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197MBJdH1bdve4Z3RR9pffn
…Arn required (go-chhed)
S3 deep-dive (parity / emulation / perf / leaks / UI) + cross-service context consistencyFollow-up pass on S3 (and a related identity-consistency fix touching DynamoDB). Each commit builds, is S3 behavioral parity
Resource leaks / performance
Request-context consistency (S3 + DynamoDB)Both services bypassed the central UI — comprehensive S3 expansion (
|
…uired field validation (go-vxq5n)
…lds and CallerReference idempotency (go-kfe9z)
…00,43200] (go-ympn2)
…tionPeriod [1,35] (go-neab9)
…tern (lowercase, no trailing/consecutive hyphens) (go-p12p3)
… tests (go-gb6gn)
Resolve the open Dependabot alerts in the ui dependency tree: - undici 7.25.0 → 7.28.0 via overrides (jsdom's transitive dep; ^7.25.0). 7.28.0 is the security-only 7.x release backporting all six advisories: SOCKS5 proxy pool reuse, TLS cert-validation bypass in the SOCKS5 ProxyAgent, Set-Cookie header injection, shared-cache cross-user disclosure, SameSite downgrade, and keep-alive response-queue poisoning. - fast-xml-parser override 5.6.0 → 5.7.3 (XMLBuilder comment/CDATA injection). - cookie override stays 1.0.2 (already patched). - Remove ui/pnpm-lock.yaml: vestigial (CI/Makefile use npm exclusively via `npm --prefix ui ci`), and the sole source of the cookie@0.6.0 alert. package-lock.json regenerated; `npm ci`, oxlint, svelte-check (0 errors) and the vitest suites pass on undici 7.28.0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197MBJdH1bdve4Z3RR9pffn
Per-commit CI runs piled up on rapid commit bursts. Add a concurrency group keyed by PR number (falling back to workflow_run head branch / ref) with cancel-in-progress, so a new push cancels the still-running CI for the same PR and CI settles on the latest commit — which is the only one that matters. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197MBJdH1bdve4Z3RR9pffn
Follow-up to the prior commit, whose `git add` aborted on an already-removed pnpm-lock.yaml pathspec and therefore staged only the lockfile deletion — the package.json override bump and regenerated package-lock.json were left out. This commit applies them: undici 7.25.0 → 7.28.0 and fast-xml-parser 5.6.0 → 5.7.3, closing the remaining Dependabot advisories. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197MBJdH1bdve4Z3RR9pffn
…, sync lifecycle, 1000+ test lines (go-dfjaa) - Add input validation: connection/host name format (regex, 32-char max), tag key/value limits (128/256 chars), tag count max (200), ProviderEndpoint required and max 512 chars for CreateHost, ProviderType enum enforcement - Add ResourceInUseException: DeleteHost blocked by active connections, DeleteRepositoryLink blocked by active sync configs - Paginate all List operations (ListConnections, ListHosts, ListRepositoryLinks, ListSyncConfigurations) using pkgs/page with opaque NextToken round-trip - Add PublishDeploymentStatus and TriggerResourceUpdateOn on CreateSyncConfiguration/UpdateSyncConfiguration with validation - Add real sync status tracking via SetRepositorySyncStatus/SetResourceSyncStatus; auto-seed SUCCEEDED status on sync config creation - Add real sync blocker CRUD: CreateSyncBlocker, GetSyncBlockerSummary returns live blockers sorted by CreatedAt desc, UpdateSyncBlocker resolves with ResolvedAt/ResolvedReason, DeleteSyncConfiguration cleans up blockers/statuses - Fix fieldalignment on all list output structs - handler_audit2_test.go: 1700+ lines of table-driven tests covering all new behaviors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… response fidelity, tests (go-337u7) - Pagination for GetGroups, GetSamplingRules, GetTraceSummaries, GetInsightEvents, GetInsightSummaries, GetIndexingRules, GetSamplingStatisticSummaries, GetServiceGraph, GetTimeSeriesServiceStatistics, GetTraceGraph, ListTagsForResource - PutTraceSegments: max 50 segments per call, max 64KB per document validation - PutEncryptionConfig: Type must be NONE or KMS; KMS requires KeyId; NONE rejects KeyId - GetTraceSummaries: TimeRangeType validation (TraceId/Event/Service) - Insight struct: add EndTime time.Time field - insightView: add EndTime and Categories fields for response fidelity - Comprehensive table-driven tests covering all new behaviors (1000+ lines) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ugn2z) - Fix struct field alignment (govet/fieldalignment): move non-pointer fields to after pointer-containing fields in createWorkspaceSpec, dirResp, WorkspaceBundle - Remove copyloopvar variable captures (Go 1.22+ handles loop var capture) - Fix nonamedreturns: convert named returns in describeWorkspacesPage to unnamed - Preallocate slices with make() (prealloc): createdIDs, collected, ids - Fix gocritic: use make+append instead of append-result-not-assigned - Rename cap→capacity to avoid redefining builtin (revive) - Use assert.Empty instead of assert.Equal with "" (testifylint) - Inline bundleID param to eliminate unparam violation - Add nolint explanations (nolintlint) - Fix double blank line in backend.go (goimports) - Shorten struct tag alignment to fit 120-char line limit (lll) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ifecycle, ACE rule eval, response fidelity (go-kjmmw) - Input validation: CreateUser (name required, role enum), CreateGroup (name required), CreateResource (name required, type must be ROOM/EQUIPMENT) - Entity state lifecycle: DeleteUser/Group/Resource returns EntityStateException if ENABLED; must DeregisterFromWorkMail first - GetAccessControlEffect: implement real rule evaluation with IP CIDR matching, action/notAction filtering, userID/notUserID filtering; first matching rule wins - Response fidelity: DescribeGroup now returns HiddenFromGlobalAddressList; ListUsers now returns UserRole; ListAccessControlRules now returns DateCreated/DateModified - UpdatePrimaryEmailAddress: now handles groups and resources (was user-only) - Pagination: replace fragile fmt.Sprintf token comparison with index-based strconv tokens - Error handling: EntityStateException mapped to 400 in handleError - 783 lines of new table-driven tests in handler_parity_test.go Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Large accumulating PR of genuine per-service AWS emulation/fidelity improvements (match-and-exceed LocalStack). One verified commit per service (build + golangci 0 + tests). Held open for human review — NOT auto-merged. Real behavioral fixes only; honest 'already-accurate' reports where applicable; no padding. CI on this PR backstops any lint missed under concurrent golangci locks.
Landed (verified) — 15 services
anything-butnested matchers matched everything; ci prefix/suffixX-Amzn-Errortype; DeleteSecret force/recovery validationStringMatchesChoice comparator absent (glob)?termwas negation (AWS=OR); FilterLogEvents shape; prefix ignoredIn progress
kms, ssm, s3 — more batching in (~120 services remaining).
🤖 Generated with Claude Code