From fb6494da01df9a5f29899e41dbc31bf53877b919 Mon Sep 17 00:00:00 2001
From: Julian Sommer <115516918+juliansommer@users.noreply.github.com>
Date: Mon, 14 Sep 2026 11:42:01 +1000
Subject: [PATCH] feat: coverage docs
---
Makefile | 9 +-
cmd/aws-model-coverage/main.go | 101 ++-
docs/README.md | 2 +-
docs/aws-model-operation-coverage.md | 627 -----------------
docs/compatibility/acm-api-coverage/README.md | 57 ++
docs/compatibility/acm-api-coverage/intro.md | 7 +
docs/compatibility/aws-api-coverage/README.md | 45 ++
docs/compatibility/aws-api-coverage/intro.md | 3 +
docs/compatibility/ec2-api-coverage/README.md | 665 ++++++++++++++++++
docs/compatibility/ec2-api-coverage/intro.md | 5 +
docs/compatibility/ecr-api-coverage/README.md | 92 +++
docs/compatibility/ecr-api-coverage/intro.md | 7 +
docs/compatibility/ecs-api-coverage/README.md | 97 +++
docs/compatibility/ecs-api-coverage/intro.md | 3 +
docs/compatibility/eks-api-coverage/README.md | 109 +++
docs/compatibility/eks-api-coverage/intro.md | 14 +
.../elbv2-api-coverage/README.md | 88 +++
.../compatibility/elbv2-api-coverage/intro.md | 3 +
docs/compatibility/iam-api-coverage/README.md | 197 ++++++
docs/compatibility/iam-api-coverage/intro.md | 3 +
docs/compatibility/pages.json | 93 +++
docs/compatibility/rds-api-coverage/README.md | 224 ++++++
docs/compatibility/rds-api-coverage/intro.md | 21 +
docs/compatibility/s3-api-coverage/README.md | 29 +
docs/compatibility/s3-api-coverage/intro.md | 7 +
docs/compatibility/sts-api-coverage/README.md | 52 ++
docs/compatibility/sts-api-coverage/intro.md | 9 +
internal/awsmodel/coverage.go | 66 +-
internal/awsmodel/coverage_test.go | 15 +-
internal/awsmodel/page.go | 267 +++++++
internal/awsmodel/page_test.go | 183 +++++
.../integration/conformance-known-findings.md | 2 +-
32 files changed, 2402 insertions(+), 700 deletions(-)
delete mode 100644 docs/aws-model-operation-coverage.md
create mode 100644 docs/compatibility/acm-api-coverage/README.md
create mode 100644 docs/compatibility/acm-api-coverage/intro.md
create mode 100644 docs/compatibility/aws-api-coverage/README.md
create mode 100644 docs/compatibility/aws-api-coverage/intro.md
create mode 100644 docs/compatibility/ec2-api-coverage/README.md
create mode 100644 docs/compatibility/ec2-api-coverage/intro.md
create mode 100644 docs/compatibility/ecr-api-coverage/README.md
create mode 100644 docs/compatibility/ecr-api-coverage/intro.md
create mode 100644 docs/compatibility/ecs-api-coverage/README.md
create mode 100644 docs/compatibility/ecs-api-coverage/intro.md
create mode 100644 docs/compatibility/eks-api-coverage/README.md
create mode 100644 docs/compatibility/eks-api-coverage/intro.md
create mode 100644 docs/compatibility/elbv2-api-coverage/README.md
create mode 100644 docs/compatibility/elbv2-api-coverage/intro.md
create mode 100644 docs/compatibility/iam-api-coverage/README.md
create mode 100644 docs/compatibility/iam-api-coverage/intro.md
create mode 100644 docs/compatibility/pages.json
create mode 100644 docs/compatibility/rds-api-coverage/README.md
create mode 100644 docs/compatibility/rds-api-coverage/intro.md
create mode 100644 docs/compatibility/s3-api-coverage/README.md
create mode 100644 docs/compatibility/s3-api-coverage/intro.md
create mode 100644 docs/compatibility/sts-api-coverage/README.md
create mode 100644 docs/compatibility/sts-api-coverage/intro.md
create mode 100644 internal/awsmodel/page.go
create mode 100644 internal/awsmodel/page_test.go
diff --git a/Makefile b/Makefile
index 4f14dfe6b..104e86e71 100644
--- a/Makefile
+++ b/Makefile
@@ -181,7 +181,7 @@ test-harness:
# JetStream, with only the daemon-side NATS subjects stubbed.
AWS_MODEL_CONFORMANCE_REPORT ?= $(CURDIR)/.cache/aws-model-conformance-report.txt
AWS_MODEL_CONFORMANCE_MODE ?= fail
-AWS_MODEL_OPERATION_COVERAGE_REPORT ?= $(CURDIR)/docs/aws-model-operation-coverage.md
+AWS_MODEL_OPERATION_COVERAGE_DIR ?= $(CURDIR)/docs/compatibility
# -count=1 is load-bearing: the conformance report is written by the test binary,
# so a cached pass skips the run, leaves no report, and the cat below fails the
# target. It also keeps the conformance gate honest — a cached result would mean
@@ -191,14 +191,13 @@ test-integration:
$(_Q)LOG_IGNORE=1 AWS_MODEL_CONFORMANCE_MODE=$(AWS_MODEL_CONFORMANCE_MODE) AWS_MODEL_CONFORMANCE_REPORT=$(AWS_MODEL_CONFORMANCE_REPORT) go test -count=1 -tags=integration -timeout 60s ./tests/integration/... $(_RACEQ)
@cat $(AWS_MODEL_CONFORMANCE_REPORT)
@$(MAKE) --no-print-directory generate-aws-model-coverage
- @echo "AWS operation coverage: $(AWS_MODEL_OPERATION_COVERAGE_REPORT)"
+ @echo "AWS operation coverage: $(AWS_MODEL_OPERATION_COVERAGE_DIR)"
generate-aws-model-coverage:
- @mkdir -p $(dir $(AWS_MODEL_OPERATION_COVERAGE_REPORT))
- @go run ./cmd/aws-model-coverage > $(AWS_MODEL_OPERATION_COVERAGE_REPORT)
+ @go run ./cmd/aws-model-coverage -out $(AWS_MODEL_OPERATION_COVERAGE_DIR)
aws-model-coverage: generate-aws-model-coverage
- @cat $(AWS_MODEL_OPERATION_COVERAGE_REPORT)
+ @go run ./cmd/aws-model-coverage
# Segscan storage oracle: needs the mulga umbrella repo's scripts/segscan
# checked out alongside spinifex (see spinifex/testutil/segscanoracle), which
diff --git a/cmd/aws-model-coverage/main.go b/cmd/aws-model-coverage/main.go
index b36371e1b..8129de6e1 100644
--- a/cmd/aws-model-coverage/main.go
+++ b/cmd/aws-model-coverage/main.go
@@ -1,8 +1,12 @@
package main
import (
+ "errors"
+ "flag"
"fmt"
+ "io/fs"
"os"
+ "path/filepath"
"github.com/mulgadc/spinifex/internal/awsmodel"
"github.com/mulgadc/spinifex/spinifex/gateway"
@@ -10,7 +14,35 @@ import (
_ "github.com/mulgadc/bluebottle/pkg/fipsboot"
)
+const (
+ pagesFile = "pages.json"
+ introFile = "intro.md"
+ pageFile = "README.md"
+)
+
func main() {
+ outputDir := flag.String("out", "", "write one publishable page per service into this directory")
+ flag.Parse()
+
+ coverages, err := compareAll()
+ if err != nil {
+ fail(err)
+ }
+ if *outputDir == "" {
+ fmt.Print(awsmodel.RenderCoverageSummary(coverages))
+ return
+ }
+ if err := writePages(*outputDir, coverages); err != nil {
+ fail(err)
+ }
+}
+
+func fail(err error) {
+ fmt.Fprintf(os.Stderr, "aws-model-coverage: %v\n", err)
+ os.Exit(1)
+}
+
+func compareAll() ([]awsmodel.OperationCoverage, error) {
dispatch := gateway.AWSOperationInventory()
coverages := make([]awsmodel.OperationCoverage, 0, len(awsmodel.Services()))
for _, service := range awsmodel.Services() {
@@ -29,17 +61,74 @@ func main() {
Note: "Spinifex delegates the S3 REST surface to Predastore, which has no operation-name dispatch table to compare mechanically.",
}
default:
- fmt.Fprintf(os.Stderr, "aws-model-coverage: no gateway inventory for %s\n", service)
- os.Exit(1)
+ return nil, fmt.Errorf("no gateway inventory for %s", service)
}
coverage, err := awsmodel.CompareOperations(service, modelInventory)
if err != nil {
- fmt.Fprintf(os.Stderr, "aws-model-coverage: %v\n", err)
- os.Exit(1)
+ return nil, err
}
coverages = append(coverages, coverage)
}
-
- fmt.Print(awsmodel.RenderCoverageMarkdown(coverages))
+ return coverages, nil
+}
+
+func writePages(outputDir string, coverages []awsmodel.OperationCoverage) error {
+ contents, err := os.ReadFile(filepath.Join(outputDir, pagesFile))
+ if err != nil {
+ return fmt.Errorf("read page metadata: %w", err)
+ }
+ pages, err := awsmodel.ParsePageSet(contents)
+ if err != nil {
+ return err
+ }
+
+ for _, coverage := range coverages {
+ page := pages.Services[coverage.Service]
+ intro, err := readIntro(outputDir, page.Slug)
+ if err != nil {
+ return err
+ }
+ body, err := awsmodel.RenderServicePage(coverage, pages, intro)
+ if err != nil {
+ return err
+ }
+ if err := writePage(outputDir, page.Slug, body); err != nil {
+ return err
+ }
+ }
+
+ intro, err := readIntro(outputDir, pages.Index.Slug)
+ if err != nil {
+ return err
+ }
+ body, err := awsmodel.RenderIndexPage(coverages, pages, intro)
+ if err != nil {
+ return err
+ }
+ return writePage(outputDir, pages.Index.Slug, body)
+}
+
+// readIntro returns the hand-written prose for a page, or "" where the page has
+// none. An intro is optional by design: most services have nothing to add.
+func readIntro(outputDir, slug string) (string, error) {
+ contents, err := os.ReadFile(filepath.Join(outputDir, slug, introFile))
+ if errors.Is(err, fs.ErrNotExist) {
+ return "", nil
+ }
+ if err != nil {
+ return "", fmt.Errorf("read %s intro: %w", slug, err)
+ }
+ return string(contents), nil
+}
+
+func writePage(outputDir, slug, body string) error {
+ dir := filepath.Join(outputDir, slug)
+ if err := os.MkdirAll(dir, 0o755); err != nil {
+ return fmt.Errorf("create %s page directory: %w", slug, err)
+ }
+ if err := os.WriteFile(filepath.Join(dir, pageFile), []byte(body), 0o644); err != nil {
+ return fmt.Errorf("write %s page: %w", slug, err)
+ }
+ return nil
}
diff --git a/docs/README.md b/docs/README.md
index 5d8e6974b..a637eb7cc 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -2,7 +2,7 @@
This directory contains the Spinifex documentation. This is available in individual markdown files, and a generated website to aid navigation and browsing documentation at: [https://docs.mulgadc.com](https://docs.mulgadc.com/)
-The [AWS model operation coverage](aws-model-operation-coverage.md) report is generated from Spinifex's dispatch tables and the pinned AWS API models. Run `make aws-model-coverage` to regenerate and print it.
+The [AWS API coverage](compatibility/aws-api-coverage/README.md) pages are generated from Spinifex's dispatch tables and the pinned AWS API models, one page per service. Run `make aws-model-coverage` to regenerate them and print a summary. Only `pages.json` and the `intro.md` files under `compatibility/` are hand-written; every `README.md` there is generated and will be overwritten.
## Frontmatter
diff --git a/docs/aws-model-operation-coverage.md b/docs/aws-model-operation-coverage.md
deleted file mode 100644
index 25013f81d..000000000
--- a/docs/aws-model-operation-coverage.md
+++ /dev/null
@@ -1,627 +0,0 @@
-# AWS model operation coverage
-
-Generated from the cached `aws-sdk-go v1.55.8` `api-2.json` models and Spinifex's authoritative gateway dispatch tables.
-
-Implemented means a modelled operation is registered to a real handler. Stub and deliberately unsupported handlers are reported separately. Shape conformance does not imply behavioural conformance.
-
-| Service | API version | Modelled | Registered | Implemented | Stubbed | Unsupported | Missing | Extra |
-|---|---:|---:|---:|---:|---:|---:|---:|---:|
-| acm | 2015-12-08 | 15 | 9 | 9 | 0 | 0 | 6 | 0 |
-| ec2 | 2016-11-15 | 625 | 121 | 121 | 0 | 0 | 504 | 0 |
-| ecr | 2015-09-21 | 47 | 39 | 19 | 13 | 7 | 11 | 3 |
-| ecs | 2014-11-13 | 56 | 39 | 31 | 5 | 0 | 20 | 3 |
-| eks | 2017-11-01 | 56 | 38 | 34 | 0 | 0 | 22 | 4 |
-| elasticloadbalancingv2 | 2015-12-01 | 46 | 37 | 33 | 0 | 0 | 13 | 4 |
-| iam | 2010-05-08 | 159 | 75 | 75 | 0 | 0 | 84 | 0 |
-| rds | 2014-10-31 | 162 | 43 | 26 | 0 | 12 | 124 | 5 |
-| s3 | 2006-03-01 | 99 | — | — | — | — | — | — |
-| sts | 2011-06-15 | 8 | 4 | 4 | 0 | 0 | 4 | 0 |
-
-## acm
-
-Implements **9 of 15** modelled operations (60.0%).
-
-Implemented (9)
-
-`AddTagsToCertificate`, `DeleteCertificate`, `DescribeCertificate`, `GetCertificate`, `ImportCertificate`, `ListCertificates`, `ListTagsForCertificate`, `RemoveTagsFromCertificate`
-
-`RequestCertificate`
-
-
-
-
-Missing from dispatch (6)
-
-`ExportCertificate`, `GetAccountConfiguration`, `PutAccountConfiguration`, `RenewCertificate`, `ResendValidationEmail`, `UpdateCertificateOptions`
-
-
-
-
-Registered stubs (0)
-
-None.
-
-
-
-Deliberately unsupported (0)
-
-None.
-
-
-
-Registered outside the pinned model (0)
-
-None.
-
-
-
-## ec2
-
-Implements **121 of 625** modelled operations (19.4%).
-
-Implemented (121)
-
-`AllocateAddress`, `AssociateAddress`, `AssociateIamInstanceProfile`, `AssociateRouteTable`, `AttachInternetGateway`, `AttachNetworkInterface`, `AttachVolume`, `AuthorizeSecurityGroupEgress`
-
-`AuthorizeSecurityGroupIngress`, `CancelCapacityReservation`, `CancelSpotInstanceRequests`, `CopyImage`, `CopySnapshot`, `CreateCapacityReservation`, `CreateEgressOnlyInternetGateway`, `CreateImage`
-
-`CreateInternetGateway`, `CreateKeyPair`, `CreateLaunchTemplate`, `CreateLaunchTemplateVersion`, `CreateNatGateway`, `CreateNetworkInterface`, `CreatePlacementGroup`, `CreateRoute`
-
-`CreateRouteTable`, `CreateSecurityGroup`, `CreateSnapshot`, `CreateSubnet`, `CreateTags`, `CreateVolume`, `CreateVpc`, `DeleteEgressOnlyInternetGateway`
-
-`DeleteInternetGateway`, `DeleteKeyPair`, `DeleteLaunchTemplate`, `DeleteLaunchTemplateVersions`, `DeleteNatGateway`, `DeleteNetworkInterface`, `DeletePlacementGroup`, `DeleteRoute`
-
-`DeleteRouteTable`, `DeleteSecurityGroup`, `DeleteSnapshot`, `DeleteSubnet`, `DeleteTags`, `DeleteVolume`, `DeleteVpc`, `DeregisterImage`
-
-`DescribeAccountAttributes`, `DescribeAddresses`, `DescribeAddressesAttribute`, `DescribeAvailabilityZones`, `DescribeCapacityReservations`, `DescribeEgressOnlyInternetGateways`, `DescribeIamInstanceProfileAssociations`, `DescribeImageAttribute`
-
-`DescribeImages`, `DescribeInstanceAttribute`, `DescribeInstanceCreditSpecifications`, `DescribeInstanceStatus`, `DescribeInstanceTypes`, `DescribeInstances`, `DescribeInternetGateways`, `DescribeKeyPairs`
-
-`DescribeLaunchTemplateVersions`, `DescribeLaunchTemplates`, `DescribeNatGateways`, `DescribeNetworkInterfaces`, `DescribePlacementGroups`, `DescribeRegions`, `DescribeRouteTables`, `DescribeSecurityGroupRules`
-
-`DescribeSecurityGroups`, `DescribeSnapshots`, `DescribeSpotInstanceRequests`, `DescribeSubnets`, `DescribeTags`, `DescribeVolumeStatus`, `DescribeVolumes`, `DescribeVolumesModifications`
-
-`DescribeVpcAttribute`, `DescribeVpcs`, `DetachInternetGateway`, `DetachNetworkInterface`, `DetachVolume`, `DisableEbsEncryptionByDefault`, `DisableSerialConsoleAccess`, `DisassociateAddress`
-
-`DisassociateIamInstanceProfile`, `DisassociateRouteTable`, `EnableEbsEncryptionByDefault`, `EnableSerialConsoleAccess`, `GetConsoleOutput`, `GetEbsEncryptionByDefault`, `GetPasswordData`, `GetSerialConsoleAccessStatus`
-
-`ImportKeyPair`, `ModifyImageAttribute`, `ModifyInstanceAttribute`, `ModifyInstanceMetadataOptions`, `ModifyLaunchTemplate`, `ModifyNetworkInterfaceAttribute`, `ModifySubnetAttribute`, `ModifyVolume`
-
-`ModifyVpcAttribute`, `MonitorInstances`, `RebootInstances`, `RegisterImage`, `ReleaseAddress`, `ReplaceIamInstanceProfileAssociation`, `ReplaceRoute`, `ReplaceRouteTableAssociation`
-
-`RequestSpotInstances`, `ResetImageAttribute`, `RevokeSecurityGroupEgress`, `RevokeSecurityGroupIngress`, `RunInstances`, `StartInstances`, `StopInstances`, `TerminateInstances`
-
-`UnmonitorInstances`
-
-
-
-
-Missing from dispatch (504)
-
-`AcceptAddressTransfer`, `AcceptReservedInstancesExchangeQuote`, `AcceptTransitGatewayMulticastDomainAssociations`, `AcceptTransitGatewayPeeringAttachment`, `AcceptTransitGatewayVpcAttachment`, `AcceptVpcEndpointConnections`, `AcceptVpcPeeringConnection`, `AdvertiseByoipCidr`
-
-`AllocateHosts`, `AllocateIpamPoolCidr`, `ApplySecurityGroupsToClientVpnTargetNetwork`, `AssignIpv6Addresses`, `AssignPrivateIpAddresses`, `AssignPrivateNatGatewayAddress`, `AssociateClientVpnTargetNetwork`, `AssociateDhcpOptions`
-
-`AssociateEnclaveCertificateIamRole`, `AssociateInstanceEventWindow`, `AssociateIpamByoasn`, `AssociateIpamResourceDiscovery`, `AssociateNatGatewayAddress`, `AssociateSubnetCidrBlock`, `AssociateTransitGatewayMulticastDomain`, `AssociateTransitGatewayPolicyTable`
-
-`AssociateTransitGatewayRouteTable`, `AssociateTrunkInterface`, `AssociateVpcCidrBlock`, `AttachClassicLinkVpc`, `AttachVerifiedAccessTrustProvider`, `AttachVpnGateway`, `AuthorizeClientVpnIngress`, `BundleInstance`
-
-`CancelBundleTask`, `CancelCapacityReservationFleets`, `CancelConversionTask`, `CancelExportTask`, `CancelImageLaunchPermission`, `CancelImportTask`, `CancelReservedInstancesListing`, `CancelSpotFleetRequests`
-
-`ConfirmProductInstance`, `CopyFpgaImage`, `CreateCapacityReservationFleet`, `CreateCarrierGateway`, `CreateClientVpnEndpoint`, `CreateClientVpnRoute`, `CreateCoipCidr`, `CreateCoipPool`
-
-`CreateCustomerGateway`, `CreateDefaultSubnet`, `CreateDefaultVpc`, `CreateDhcpOptions`, `CreateFleet`, `CreateFlowLogs`, `CreateFpgaImage`, `CreateInstanceConnectEndpoint`
-
-`CreateInstanceEventWindow`, `CreateInstanceExportTask`, `CreateIpam`, `CreateIpamExternalResourceVerificationToken`, `CreateIpamPool`, `CreateIpamResourceDiscovery`, `CreateIpamScope`, `CreateLocalGatewayRoute`
-
-`CreateLocalGatewayRouteTable`, `CreateLocalGatewayRouteTableVirtualInterfaceGroupAssociation`, `CreateLocalGatewayRouteTableVpcAssociation`, `CreateManagedPrefixList`, `CreateNetworkAcl`, `CreateNetworkAclEntry`, `CreateNetworkInsightsAccessScope`, `CreateNetworkInsightsPath`
-
-`CreateNetworkInterfacePermission`, `CreatePublicIpv4Pool`, `CreateReplaceRootVolumeTask`, `CreateReservedInstancesListing`, `CreateRestoreImageTask`, `CreateSnapshots`, `CreateSpotDatafeedSubscription`, `CreateStoreImageTask`
-
-`CreateSubnetCidrReservation`, `CreateTrafficMirrorFilter`, `CreateTrafficMirrorFilterRule`, `CreateTrafficMirrorSession`, `CreateTrafficMirrorTarget`, `CreateTransitGateway`, `CreateTransitGatewayConnect`, `CreateTransitGatewayConnectPeer`
-
-`CreateTransitGatewayMulticastDomain`, `CreateTransitGatewayPeeringAttachment`, `CreateTransitGatewayPolicyTable`, `CreateTransitGatewayPrefixListReference`, `CreateTransitGatewayRoute`, `CreateTransitGatewayRouteTable`, `CreateTransitGatewayRouteTableAnnouncement`, `CreateTransitGatewayVpcAttachment`
-
-`CreateVerifiedAccessEndpoint`, `CreateVerifiedAccessGroup`, `CreateVerifiedAccessInstance`, `CreateVerifiedAccessTrustProvider`, `CreateVpcEndpoint`, `CreateVpcEndpointConnectionNotification`, `CreateVpcEndpointServiceConfiguration`, `CreateVpcPeeringConnection`
-
-`CreateVpnConnection`, `CreateVpnConnectionRoute`, `CreateVpnGateway`, `DeleteCarrierGateway`, `DeleteClientVpnEndpoint`, `DeleteClientVpnRoute`, `DeleteCoipCidr`, `DeleteCoipPool`
-
-`DeleteCustomerGateway`, `DeleteDhcpOptions`, `DeleteFleets`, `DeleteFlowLogs`, `DeleteFpgaImage`, `DeleteInstanceConnectEndpoint`, `DeleteInstanceEventWindow`, `DeleteIpam`
-
-`DeleteIpamExternalResourceVerificationToken`, `DeleteIpamPool`, `DeleteIpamResourceDiscovery`, `DeleteIpamScope`, `DeleteLocalGatewayRoute`, `DeleteLocalGatewayRouteTable`, `DeleteLocalGatewayRouteTableVirtualInterfaceGroupAssociation`, `DeleteLocalGatewayRouteTableVpcAssociation`
-
-`DeleteManagedPrefixList`, `DeleteNetworkAcl`, `DeleteNetworkAclEntry`, `DeleteNetworkInsightsAccessScope`, `DeleteNetworkInsightsAccessScopeAnalysis`, `DeleteNetworkInsightsAnalysis`, `DeleteNetworkInsightsPath`, `DeleteNetworkInterfacePermission`
-
-`DeletePublicIpv4Pool`, `DeleteQueuedReservedInstances`, `DeleteSpotDatafeedSubscription`, `DeleteSubnetCidrReservation`, `DeleteTrafficMirrorFilter`, `DeleteTrafficMirrorFilterRule`, `DeleteTrafficMirrorSession`, `DeleteTrafficMirrorTarget`
-
-`DeleteTransitGateway`, `DeleteTransitGatewayConnect`, `DeleteTransitGatewayConnectPeer`, `DeleteTransitGatewayMulticastDomain`, `DeleteTransitGatewayPeeringAttachment`, `DeleteTransitGatewayPolicyTable`, `DeleteTransitGatewayPrefixListReference`, `DeleteTransitGatewayRoute`
-
-`DeleteTransitGatewayRouteTable`, `DeleteTransitGatewayRouteTableAnnouncement`, `DeleteTransitGatewayVpcAttachment`, `DeleteVerifiedAccessEndpoint`, `DeleteVerifiedAccessGroup`, `DeleteVerifiedAccessInstance`, `DeleteVerifiedAccessTrustProvider`, `DeleteVpcEndpointConnectionNotifications`
-
-`DeleteVpcEndpointServiceConfigurations`, `DeleteVpcEndpoints`, `DeleteVpcPeeringConnection`, `DeleteVpnConnection`, `DeleteVpnConnectionRoute`, `DeleteVpnGateway`, `DeprovisionByoipCidr`, `DeprovisionIpamByoasn`
-
-`DeprovisionIpamPoolCidr`, `DeprovisionPublicIpv4PoolCidr`, `DeregisterInstanceEventNotificationAttributes`, `DeregisterTransitGatewayMulticastGroupMembers`, `DeregisterTransitGatewayMulticastGroupSources`, `DescribeAddressTransfers`, `DescribeAggregateIdFormat`, `DescribeAwsNetworkPerformanceMetricSubscriptions`
-
-`DescribeBundleTasks`, `DescribeByoipCidrs`, `DescribeCapacityBlockOfferings`, `DescribeCapacityReservationFleets`, `DescribeCarrierGateways`, `DescribeClassicLinkInstances`, `DescribeClientVpnAuthorizationRules`, `DescribeClientVpnConnections`
-
-`DescribeClientVpnEndpoints`, `DescribeClientVpnRoutes`, `DescribeClientVpnTargetNetworks`, `DescribeCoipPools`, `DescribeConversionTasks`, `DescribeCustomerGateways`, `DescribeDhcpOptions`, `DescribeElasticGpus`
-
-`DescribeExportImageTasks`, `DescribeExportTasks`, `DescribeFastLaunchImages`, `DescribeFastSnapshotRestores`, `DescribeFleetHistory`, `DescribeFleetInstances`, `DescribeFleets`, `DescribeFlowLogs`
-
-`DescribeFpgaImageAttribute`, `DescribeFpgaImages`, `DescribeHostReservationOfferings`, `DescribeHostReservations`, `DescribeHosts`, `DescribeIdFormat`, `DescribeIdentityIdFormat`, `DescribeImportImageTasks`
-
-`DescribeImportSnapshotTasks`, `DescribeInstanceConnectEndpoints`, `DescribeInstanceEventNotificationAttributes`, `DescribeInstanceEventWindows`, `DescribeInstanceTopology`, `DescribeInstanceTypeOfferings`, `DescribeIpamByoasn`, `DescribeIpamExternalResourceVerificationTokens`
-
-`DescribeIpamPools`, `DescribeIpamResourceDiscoveries`, `DescribeIpamResourceDiscoveryAssociations`, `DescribeIpamScopes`, `DescribeIpams`, `DescribeIpv6Pools`, `DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociations`, `DescribeLocalGatewayRouteTableVpcAssociations`
-
-`DescribeLocalGatewayRouteTables`, `DescribeLocalGatewayVirtualInterfaceGroups`, `DescribeLocalGatewayVirtualInterfaces`, `DescribeLocalGateways`, `DescribeLockedSnapshots`, `DescribeMacHosts`, `DescribeManagedPrefixLists`, `DescribeMovingAddresses`
-
-`DescribeNetworkAcls`, `DescribeNetworkInsightsAccessScopeAnalyses`, `DescribeNetworkInsightsAccessScopes`, `DescribeNetworkInsightsAnalyses`, `DescribeNetworkInsightsPaths`, `DescribeNetworkInterfaceAttribute`, `DescribeNetworkInterfacePermissions`, `DescribePrefixLists`
-
-`DescribePrincipalIdFormat`, `DescribePublicIpv4Pools`, `DescribeReplaceRootVolumeTasks`, `DescribeReservedInstances`, `DescribeReservedInstancesListings`, `DescribeReservedInstancesModifications`, `DescribeReservedInstancesOfferings`, `DescribeScheduledInstanceAvailability`
-
-`DescribeScheduledInstances`, `DescribeSecurityGroupReferences`, `DescribeSnapshotAttribute`, `DescribeSnapshotTierStatus`, `DescribeSpotDatafeedSubscription`, `DescribeSpotFleetInstances`, `DescribeSpotFleetRequestHistory`, `DescribeSpotFleetRequests`
-
-`DescribeSpotPriceHistory`, `DescribeStaleSecurityGroups`, `DescribeStoreImageTasks`, `DescribeTrafficMirrorFilterRules`, `DescribeTrafficMirrorFilters`, `DescribeTrafficMirrorSessions`, `DescribeTrafficMirrorTargets`, `DescribeTransitGatewayAttachments`
-
-`DescribeTransitGatewayConnectPeers`, `DescribeTransitGatewayConnects`, `DescribeTransitGatewayMulticastDomains`, `DescribeTransitGatewayPeeringAttachments`, `DescribeTransitGatewayPolicyTables`, `DescribeTransitGatewayRouteTableAnnouncements`, `DescribeTransitGatewayRouteTables`, `DescribeTransitGatewayVpcAttachments`
-
-`DescribeTransitGateways`, `DescribeTrunkInterfaceAssociations`, `DescribeVerifiedAccessEndpoints`, `DescribeVerifiedAccessGroups`, `DescribeVerifiedAccessInstanceLoggingConfigurations`, `DescribeVerifiedAccessInstances`, `DescribeVerifiedAccessTrustProviders`, `DescribeVolumeAttribute`
-
-`DescribeVpcClassicLink`, `DescribeVpcClassicLinkDnsSupport`, `DescribeVpcEndpointConnectionNotifications`, `DescribeVpcEndpointConnections`, `DescribeVpcEndpointServiceConfigurations`, `DescribeVpcEndpointServicePermissions`, `DescribeVpcEndpointServices`, `DescribeVpcEndpoints`
-
-`DescribeVpcPeeringConnections`, `DescribeVpnConnections`, `DescribeVpnGateways`, `DetachClassicLinkVpc`, `DetachVerifiedAccessTrustProvider`, `DetachVpnGateway`, `DisableAddressTransfer`, `DisableAwsNetworkPerformanceMetricSubscription`
-
-`DisableFastLaunch`, `DisableFastSnapshotRestores`, `DisableImage`, `DisableImageBlockPublicAccess`, `DisableImageDeprecation`, `DisableImageDeregistrationProtection`, `DisableIpamOrganizationAdminAccount`, `DisableSnapshotBlockPublicAccess`
-
-`DisableTransitGatewayRouteTablePropagation`, `DisableVgwRoutePropagation`, `DisableVpcClassicLink`, `DisableVpcClassicLinkDnsSupport`, `DisassociateClientVpnTargetNetwork`, `DisassociateEnclaveCertificateIamRole`, `DisassociateInstanceEventWindow`, `DisassociateIpamByoasn`
-
-`DisassociateIpamResourceDiscovery`, `DisassociateNatGatewayAddress`, `DisassociateSubnetCidrBlock`, `DisassociateTransitGatewayMulticastDomain`, `DisassociateTransitGatewayPolicyTable`, `DisassociateTransitGatewayRouteTable`, `DisassociateTrunkInterface`, `DisassociateVpcCidrBlock`
-
-`EnableAddressTransfer`, `EnableAwsNetworkPerformanceMetricSubscription`, `EnableFastLaunch`, `EnableFastSnapshotRestores`, `EnableImage`, `EnableImageBlockPublicAccess`, `EnableImageDeprecation`, `EnableImageDeregistrationProtection`
-
-`EnableIpamOrganizationAdminAccount`, `EnableReachabilityAnalyzerOrganizationSharing`, `EnableSnapshotBlockPublicAccess`, `EnableTransitGatewayRouteTablePropagation`, `EnableVgwRoutePropagation`, `EnableVolumeIO`, `EnableVpcClassicLink`, `EnableVpcClassicLinkDnsSupport`
-
-`ExportClientVpnClientCertificateRevocationList`, `ExportClientVpnClientConfiguration`, `ExportImage`, `ExportTransitGatewayRoutes`, `GetAssociatedEnclaveCertificateIamRoles`, `GetAssociatedIpv6PoolCidrs`, `GetAwsNetworkPerformanceData`, `GetCapacityReservationUsage`
-
-`GetCoipPoolUsage`, `GetConsoleScreenshot`, `GetDefaultCreditSpecification`, `GetEbsDefaultKmsKeyId`, `GetFlowLogsIntegrationTemplate`, `GetGroupsForCapacityReservation`, `GetHostReservationPurchasePreview`, `GetImageBlockPublicAccessState`
-
-`GetInstanceMetadataDefaults`, `GetInstanceTpmEkPub`, `GetInstanceTypesFromInstanceRequirements`, `GetInstanceUefiData`, `GetIpamAddressHistory`, `GetIpamDiscoveredAccounts`, `GetIpamDiscoveredPublicAddresses`, `GetIpamDiscoveredResourceCidrs`
-
-`GetIpamPoolAllocations`, `GetIpamPoolCidrs`, `GetIpamResourceCidrs`, `GetLaunchTemplateData`, `GetManagedPrefixListAssociations`, `GetManagedPrefixListEntries`, `GetNetworkInsightsAccessScopeAnalysisFindings`, `GetNetworkInsightsAccessScopeContent`
-
-`GetReservedInstancesExchangeQuote`, `GetSecurityGroupsForVpc`, `GetSnapshotBlockPublicAccessState`, `GetSpotPlacementScores`, `GetSubnetCidrReservations`, `GetTransitGatewayAttachmentPropagations`, `GetTransitGatewayMulticastDomainAssociations`, `GetTransitGatewayPolicyTableAssociations`
-
-`GetTransitGatewayPolicyTableEntries`, `GetTransitGatewayPrefixListReferences`, `GetTransitGatewayRouteTableAssociations`, `GetTransitGatewayRouteTablePropagations`, `GetVerifiedAccessEndpointPolicy`, `GetVerifiedAccessGroupPolicy`, `GetVpnConnectionDeviceSampleConfiguration`, `GetVpnConnectionDeviceTypes`
-
-`GetVpnTunnelReplacementStatus`, `ImportClientVpnClientCertificateRevocationList`, `ImportImage`, `ImportInstance`, `ImportSnapshot`, `ImportVolume`, `ListImagesInRecycleBin`, `ListSnapshotsInRecycleBin`
-
-`LockSnapshot`, `ModifyAddressAttribute`, `ModifyAvailabilityZoneGroup`, `ModifyCapacityReservation`, `ModifyCapacityReservationFleet`, `ModifyClientVpnEndpoint`, `ModifyDefaultCreditSpecification`, `ModifyEbsDefaultKmsKeyId`
-
-`ModifyFleet`, `ModifyFpgaImageAttribute`, `ModifyHosts`, `ModifyIdFormat`, `ModifyIdentityIdFormat`, `ModifyInstanceCapacityReservationAttributes`, `ModifyInstanceCreditSpecification`, `ModifyInstanceEventStartTime`
-
-`ModifyInstanceEventWindow`, `ModifyInstanceMaintenanceOptions`, `ModifyInstanceMetadataDefaults`, `ModifyInstancePlacement`, `ModifyIpam`, `ModifyIpamPool`, `ModifyIpamResourceCidr`, `ModifyIpamResourceDiscovery`
-
-`ModifyIpamScope`, `ModifyLocalGatewayRoute`, `ModifyManagedPrefixList`, `ModifyPrivateDnsNameOptions`, `ModifyReservedInstances`, `ModifySecurityGroupRules`, `ModifySnapshotAttribute`, `ModifySnapshotTier`
-
-`ModifySpotFleetRequest`, `ModifyTrafficMirrorFilterNetworkServices`, `ModifyTrafficMirrorFilterRule`, `ModifyTrafficMirrorSession`, `ModifyTransitGateway`, `ModifyTransitGatewayPrefixListReference`, `ModifyTransitGatewayVpcAttachment`, `ModifyVerifiedAccessEndpoint`
-
-`ModifyVerifiedAccessEndpointPolicy`, `ModifyVerifiedAccessGroup`, `ModifyVerifiedAccessGroupPolicy`, `ModifyVerifiedAccessInstance`, `ModifyVerifiedAccessInstanceLoggingConfiguration`, `ModifyVerifiedAccessTrustProvider`, `ModifyVolumeAttribute`, `ModifyVpcEndpoint`
-
-`ModifyVpcEndpointConnectionNotification`, `ModifyVpcEndpointServiceConfiguration`, `ModifyVpcEndpointServicePayerResponsibility`, `ModifyVpcEndpointServicePermissions`, `ModifyVpcPeeringConnectionOptions`, `ModifyVpcTenancy`, `ModifyVpnConnection`, `ModifyVpnConnectionOptions`
-
-`ModifyVpnTunnelCertificate`, `ModifyVpnTunnelOptions`, `MoveAddressToVpc`, `MoveByoipCidrToIpam`, `ProvisionByoipCidr`, `ProvisionIpamByoasn`, `ProvisionIpamPoolCidr`, `ProvisionPublicIpv4PoolCidr`
-
-`PurchaseCapacityBlock`, `PurchaseHostReservation`, `PurchaseReservedInstancesOffering`, `PurchaseScheduledInstances`, `RegisterInstanceEventNotificationAttributes`, `RegisterTransitGatewayMulticastGroupMembers`, `RegisterTransitGatewayMulticastGroupSources`, `RejectTransitGatewayMulticastDomainAssociations`
-
-`RejectTransitGatewayPeeringAttachment`, `RejectTransitGatewayVpcAttachment`, `RejectVpcEndpointConnections`, `RejectVpcPeeringConnection`, `ReleaseHosts`, `ReleaseIpamPoolAllocation`, `ReplaceNetworkAclAssociation`, `ReplaceNetworkAclEntry`
-
-`ReplaceTransitGatewayRoute`, `ReplaceVpnTunnel`, `ReportInstanceStatus`, `RequestSpotFleet`, `ResetAddressAttribute`, `ResetEbsDefaultKmsKeyId`, `ResetFpgaImageAttribute`, `ResetInstanceAttribute`
-
-`ResetNetworkInterfaceAttribute`, `ResetSnapshotAttribute`, `RestoreAddressToClassic`, `RestoreImageFromRecycleBin`, `RestoreManagedPrefixListVersion`, `RestoreSnapshotFromRecycleBin`, `RestoreSnapshotTier`, `RevokeClientVpnIngress`
-
-`RunScheduledInstances`, `SearchLocalGatewayRoutes`, `SearchTransitGatewayMulticastGroups`, `SearchTransitGatewayRoutes`, `SendDiagnosticInterrupt`, `StartNetworkInsightsAccessScopeAnalysis`, `StartNetworkInsightsAnalysis`, `StartVpcEndpointServicePrivateDnsVerification`
-
-`TerminateClientVpnConnections`, `UnassignIpv6Addresses`, `UnassignPrivateIpAddresses`, `UnassignPrivateNatGatewayAddress`, `UnlockSnapshot`, `UpdateSecurityGroupRuleDescriptionsEgress`, `UpdateSecurityGroupRuleDescriptionsIngress`, `WithdrawByoipCidr`
-
-
-
-
-Registered stubs (0)
-
-None.
-
-
-
-Deliberately unsupported (0)
-
-None.
-
-
-
-Registered outside the pinned model (0)
-
-None.
-
-
-
-## ecr
-
-Implements **19 of 47** modelled operations (40.4%).
-
-Implemented (19)
-
-`BatchDeleteImage`, `BatchGetImage`, `CreateRepository`, `DeleteLifecyclePolicy`, `DeleteRepository`, `DeleteRepositoryPolicy`, `DescribeImages`, `DescribeRepositories`
-
-`GetAuthorizationToken`, `GetLifecyclePolicy`, `GetLifecyclePolicyPreview`, `GetRepositoryPolicy`, `ListImages`, `ListTagsForResource`, `PutImage`, `PutImageTagMutability`
-
-`PutLifecyclePolicy`, `SetRepositoryPolicy`, `StartLifecyclePolicyPreview`
-
-
-
-
-Missing from dispatch (11)
-
-`CreatePullThroughCacheRule`, `CreateRepositoryCreationTemplate`, `DeletePullThroughCacheRule`, `DeleteRegistryPolicy`, `DeleteRepositoryCreationTemplate`, `DescribeImageReplicationStatus`, `DescribePullThroughCacheRules`, `DescribeRepositoryCreationTemplates`
-
-`UpdatePullThroughCacheRule`, `UpdateRepositoryCreationTemplate`, `ValidatePullThroughCacheRule`
-
-
-
-
-Registered stubs (13)
-
-`BatchCheckLayerAvailability`, `CompleteLayerUpload`, `DescribeRegistry`, `GetDownloadUrlForLayer`, `GetRegistryPolicy`, `InitiateLayerUpload`, `ListRepositories`, `PutRegistryPolicy`
-
-`PutReplicationConfiguration`, `ReplicateImage`, `TagResource`, `UntagResource`, `UploadLayerPart`
-
-
-
-
-Deliberately unsupported (7)
-
-`BatchGetRepositoryScanningConfiguration`, `DescribeImageScanFindings`, `GetImageScanningConfiguration`, `GetRegistryScanningConfiguration`, `PutImageScanningConfiguration`, `PutRegistryScanningConfiguration`, `StartImageScan`
-
-
-
-
-Registered outside the pinned model (3)
-
-`GetImageScanningConfiguration`, `ListRepositories`, `ReplicateImage`
-
-
-
-
-## ecs
-
-Implements **31 of 56** modelled operations (55.4%).
-
-Implemented (31)
-
-`CreateCapacityProvider`, `CreateCluster`, `CreateService`, `DeleteCapacityProvider`, `DeleteCluster`, `DeleteService`, `DeregisterContainerInstance`, `DeregisterTaskDefinition`
-
-`DescribeCapacityProviders`, `DescribeClusters`, `DescribeContainerInstances`, `DescribeServices`, `DescribeTaskDefinition`, `DescribeTasks`, `ListClusters`, `ListContainerInstances`
-
-`ListServices`, `ListTagsForResource`, `ListTaskDefinitions`, `ListTasks`, `PutClusterCapacityProviders`, `RegisterContainerInstance`, `RegisterTaskDefinition`, `RunTask`
-
-`StartTask`, `StopTask`, `SubmitTaskStateChange`, `TagResource`, `UntagResource`, `UpdateContainerInstancesState`, `UpdateService`
-
-
-
-
-Missing from dispatch (20)
-
-`CreateTaskSet`, `DeleteAccountSetting`, `DeleteAttributes`, `DeleteTaskDefinitions`, `DeleteTaskSet`, `DescribeTaskSets`, `DiscoverPollEndpoint`, `ExecuteCommand`
-
-`GetTaskProtection`, `ListAttributes`, `PutAccountSettingDefault`, `PutAttributes`, `SubmitAttachmentStateChanges`, `SubmitContainerStateChange`, `UpdateCapacityProvider`, `UpdateClusterSettings`
-
-`UpdateContainerAgent`, `UpdateServicePrimaryTaskSet`, `UpdateTaskProtection`, `UpdateTaskSet`
-
-
-
-
-Registered stubs (5)
-
-`ListAccountSettings`, `ListServicesByNamespace`, `ListTaskDefinitionFamilies`, `PutAccountSetting`, `UpdateCluster`
-
-
-
-
-Deliberately unsupported (0)
-
-None.
-
-
-
-Registered outside the pinned model (3)
-
-`PollAssignments`, `ProvisionCapacity`, `ReportTaskGPU`
-
-
-
-
-## eks
-
-Implements **34 of 56** modelled operations (60.7%).
-
-Implemented (34)
-
-`AssociateAccessPolicy`, `AssociateIdentityProviderConfig`, `CreateAccessEntry`, `CreateAddon`, `CreateCluster`, `CreateNodegroup`, `DeleteAccessEntry`, `DeleteAddon`
-
-`DeleteCluster`, `DeleteNodegroup`, `DescribeAccessEntry`, `DescribeAddon`, `DescribeAddonVersions`, `DescribeCluster`, `DescribeIdentityProviderConfig`, `DescribeNodegroup`
-
-`DisassociateAccessPolicy`, `DisassociateIdentityProviderConfig`, `ListAccessEntries`, `ListAccessPolicies`, `ListAddons`, `ListAssociatedAccessPolicies`, `ListClusters`, `ListIdentityProviderConfigs`
-
-`ListNodegroups`, `ListTagsForResource`, `TagResource`, `UntagResource`, `UpdateAccessEntry`, `UpdateAddon`, `UpdateClusterConfig`, `UpdateClusterVersion`
-
-`UpdateNodegroupConfig`, `UpdateNodegroupVersion`
-
-
-
-
-Missing from dispatch (22)
-
-`AssociateEncryptionConfig`, `CreateEksAnywhereSubscription`, `CreateFargateProfile`, `CreatePodIdentityAssociation`, `DeleteEksAnywhereSubscription`, `DeleteFargateProfile`, `DeletePodIdentityAssociation`, `DeregisterCluster`
-
-`DescribeAddonConfiguration`, `DescribeEksAnywhereSubscription`, `DescribeFargateProfile`, `DescribeInsight`, `DescribePodIdentityAssociation`, `DescribeUpdate`, `ListEksAnywhereSubscriptions`, `ListFargateProfiles`
-
-`ListInsights`, `ListPodIdentityAssociations`, `ListUpdates`, `RegisterCluster`, `UpdateEksAnywhereSubscription`, `UpdatePodIdentityAssociation`
-
-
-
-
-Registered stubs (0)
-
-None.
-
-
-
-Deliberately unsupported (0)
-
-None.
-
-
-
-Registered outside the pinned model (4)
-
-`GetRecoveryDirective`, `ListInternalAddons`, `PublishInternal`, `WebhookTokenReview`
-
-
-
-
-## elasticloadbalancingv2
-
-Implements **33 of 46** modelled operations (71.7%).
-
-Implemented (33)
-
-`AddListenerCertificates`, `AddTags`, `CreateListener`, `CreateLoadBalancer`, `CreateRule`, `CreateTargetGroup`, `DeleteListener`, `DeleteLoadBalancer`
-
-`DeleteRule`, `DeleteTargetGroup`, `DeregisterTargets`, `DescribeListenerCertificates`, `DescribeListeners`, `DescribeLoadBalancerAttributes`, `DescribeLoadBalancers`, `DescribeRules`
-
-`DescribeSSLPolicies`, `DescribeTags`, `DescribeTargetGroupAttributes`, `DescribeTargetGroups`, `DescribeTargetHealth`, `ModifyListener`, `ModifyLoadBalancerAttributes`, `ModifyRule`
-
-`ModifyTargetGroup`, `ModifyTargetGroupAttributes`, `RegisterTargets`, `RemoveListenerCertificates`, `RemoveTags`, `SetIpAddressType`, `SetRulePriorities`, `SetSecurityGroups`
-
-`SetSubnets`
-
-
-
-
-Missing from dispatch (13)
-
-`AddTrustStoreRevocations`, `CreateTrustStore`, `DeleteSharedTrustStoreAssociation`, `DeleteTrustStore`, `DescribeAccountLimits`, `DescribeTrustStoreAssociations`, `DescribeTrustStoreRevocations`, `DescribeTrustStores`
-
-`GetResourcePolicy`, `GetTrustStoreCaCertificatesBundle`, `GetTrustStoreRevocationContent`, `ModifyTrustStore`, `RemoveTrustStoreRevocations`
-
-
-
-
-Registered stubs (0)
-
-None.
-
-
-
-Deliberately unsupported (0)
-
-None.
-
-
-
-Registered outside the pinned model (4)
-
-`DescribeListenerAttributes`, `GetLBConfig`, `LBAgentHeartbeat`, `ModifyListenerAttributes`
-
-
-
-
-## iam
-
-Implements **75 of 159** modelled operations (47.2%).
-
-Implemented (75)
-
-`AddRoleToInstanceProfile`, `AddUserToGroup`, `AttachGroupPolicy`, `AttachRolePolicy`, `AttachUserPolicy`, `CreateAccessKey`, `CreateGroup`, `CreateInstanceProfile`
-
-`CreateOpenIDConnectProvider`, `CreatePolicy`, `CreateRole`, `CreateUser`, `DeleteAccessKey`, `DeleteGroup`, `DeleteGroupPolicy`, `DeleteInstanceProfile`
-
-`DeleteOpenIDConnectProvider`, `DeletePolicy`, `DeleteRole`, `DeleteRolePolicy`, `DeleteUser`, `DeleteUserPolicy`, `DetachGroupPolicy`, `DetachRolePolicy`
-
-`DetachUserPolicy`, `GetAccountSummary`, `GetGroup`, `GetGroupPolicy`, `GetInstanceProfile`, `GetOpenIDConnectProvider`, `GetPolicy`, `GetPolicyVersion`
-
-`GetRole`, `GetRolePolicy`, `GetUser`, `GetUserPolicy`, `ListAccessKeys`, `ListAttachedGroupPolicies`, `ListAttachedRolePolicies`, `ListAttachedUserPolicies`
-
-`ListGroupPolicies`, `ListGroups`, `ListGroupsForUser`, `ListInstanceProfileTags`, `ListInstanceProfiles`, `ListInstanceProfilesForRole`, `ListOpenIDConnectProviderTags`, `ListOpenIDConnectProviders`
-
-`ListPolicies`, `ListPolicyTags`, `ListPolicyVersions`, `ListRolePolicies`, `ListRoleTags`, `ListRoles`, `ListUserPolicies`, `ListUserTags`
-
-`ListUsers`, `PutGroupPolicy`, `PutRolePolicy`, `PutUserPolicy`, `RemoveRoleFromInstanceProfile`, `RemoveUserFromGroup`, `TagInstanceProfile`, `TagOpenIDConnectProvider`
-
-`TagPolicy`, `TagRole`, `TagUser`, `UntagInstanceProfile`, `UntagOpenIDConnectProvider`, `UntagPolicy`, `UntagRole`, `UntagUser`
-
-`UpdateAccessKey`, `UpdateAssumeRolePolicy`, `UpdateRole`
-
-
-
-
-Missing from dispatch (84)
-
-`AddClientIDToOpenIDConnectProvider`, `ChangePassword`, `CreateAccountAlias`, `CreateLoginProfile`, `CreatePolicyVersion`, `CreateSAMLProvider`, `CreateServiceLinkedRole`, `CreateServiceSpecificCredential`
-
-`CreateVirtualMFADevice`, `DeactivateMFADevice`, `DeleteAccountAlias`, `DeleteAccountPasswordPolicy`, `DeleteLoginProfile`, `DeletePolicyVersion`, `DeleteRolePermissionsBoundary`, `DeleteSAMLProvider`
-
-`DeleteSSHPublicKey`, `DeleteServerCertificate`, `DeleteServiceLinkedRole`, `DeleteServiceSpecificCredential`, `DeleteSigningCertificate`, `DeleteUserPermissionsBoundary`, `DeleteVirtualMFADevice`, `EnableMFADevice`
-
-`GenerateCredentialReport`, `GenerateOrganizationsAccessReport`, `GenerateServiceLastAccessedDetails`, `GetAccessKeyLastUsed`, `GetAccountAuthorizationDetails`, `GetAccountPasswordPolicy`, `GetContextKeysForCustomPolicy`, `GetContextKeysForPrincipalPolicy`
-
-`GetCredentialReport`, `GetLoginProfile`, `GetMFADevice`, `GetOrganizationsAccessReport`, `GetSAMLProvider`, `GetSSHPublicKey`, `GetServerCertificate`, `GetServiceLastAccessedDetails`
-
-`GetServiceLastAccessedDetailsWithEntities`, `GetServiceLinkedRoleDeletionStatus`, `ListAccountAliases`, `ListEntitiesForPolicy`, `ListMFADeviceTags`, `ListMFADevices`, `ListPoliciesGrantingServiceAccess`, `ListSAMLProviderTags`
-
-`ListSAMLProviders`, `ListSSHPublicKeys`, `ListServerCertificateTags`, `ListServerCertificates`, `ListServiceSpecificCredentials`, `ListSigningCertificates`, `ListVirtualMFADevices`, `PutRolePermissionsBoundary`
-
-`PutUserPermissionsBoundary`, `RemoveClientIDFromOpenIDConnectProvider`, `ResetServiceSpecificCredential`, `ResyncMFADevice`, `SetDefaultPolicyVersion`, `SetSecurityTokenServicePreferences`, `SimulateCustomPolicy`, `SimulatePrincipalPolicy`
-
-`TagMFADevice`, `TagSAMLProvider`, `TagServerCertificate`, `UntagMFADevice`, `UntagSAMLProvider`, `UntagServerCertificate`, `UpdateAccountPasswordPolicy`, `UpdateGroup`
-
-`UpdateLoginProfile`, `UpdateOpenIDConnectProviderThumbprint`, `UpdateRoleDescription`, `UpdateSAMLProvider`, `UpdateSSHPublicKey`, `UpdateServerCertificate`, `UpdateServiceSpecificCredential`, `UpdateSigningCertificate`
-
-`UpdateUser`, `UploadSSHPublicKey`, `UploadServerCertificate`, `UploadSigningCertificate`
-
-
-
-
-Registered stubs (0)
-
-None.
-
-
-
-Deliberately unsupported (0)
-
-None.
-
-
-
-Registered outside the pinned model (0)
-
-None.
-
-
-
-## rds
-
-Implements **26 of 162** modelled operations (16.0%).
-
-Implemented (26)
-
-`AddTagsToResource`, `CreateDBInstance`, `CreateDBParameterGroup`, `CreateDBSnapshot`, `CreateDBSubnetGroup`, `DeleteDBInstance`, `DeleteDBParameterGroup`, `DeleteDBSnapshot`
-
-`DeleteDBSubnetGroup`, `DescribeDBEngineVersions`, `DescribeDBInstanceAutomatedBackups`, `DescribeDBInstances`, `DescribeDBParameterGroups`, `DescribeDBParameters`, `DescribeDBSnapshots`, `DescribeDBSubnetGroups`
-
-`DescribeEvents`, `DescribeOrderableDBInstanceOptions`, `ListTagsForResource`, `ModifyDBInstance`, `ModifyDBParameterGroup`, `RebootDBInstance`, `RemoveTagsFromResource`, `RestoreDBInstanceFromDBSnapshot`
-
-`StartDBInstance`, `StopDBInstance`
-
-
-
-
-Missing from dispatch (124)
-
-`AddRoleToDBCluster`, `AddRoleToDBInstance`, `AddSourceIdentifierToSubscription`, `ApplyPendingMaintenanceAction`, `AuthorizeDBSecurityGroupIngress`, `BacktrackDBCluster`, `CancelExportTask`, `CopyDBClusterParameterGroup`
-
-`CopyDBClusterSnapshot`, `CopyDBParameterGroup`, `CopyDBSnapshot`, `CopyOptionGroup`, `CreateBlueGreenDeployment`, `CreateCustomDBEngineVersion`, `CreateDBClusterEndpoint`, `CreateDBClusterParameterGroup`
-
-`CreateDBClusterSnapshot`, `CreateDBProxy`, `CreateDBProxyEndpoint`, `CreateDBSecurityGroup`, `CreateDBShardGroup`, `CreateEventSubscription`, `CreateGlobalCluster`, `CreateIntegration`
-
-`CreateTenantDatabase`, `DeleteBlueGreenDeployment`, `DeleteCustomDBEngineVersion`, `DeleteDBClusterAutomatedBackup`, `DeleteDBClusterEndpoint`, `DeleteDBClusterParameterGroup`, `DeleteDBClusterSnapshot`, `DeleteDBInstanceAutomatedBackup`
-
-`DeleteDBProxy`, `DeleteDBProxyEndpoint`, `DeleteDBSecurityGroup`, `DeleteDBShardGroup`, `DeleteEventSubscription`, `DeleteGlobalCluster`, `DeleteIntegration`, `DeleteTenantDatabase`
-
-`DeregisterDBProxyTargets`, `DescribeAccountAttributes`, `DescribeBlueGreenDeployments`, `DescribeCertificates`, `DescribeDBClusterAutomatedBackups`, `DescribeDBClusterBacktracks`, `DescribeDBClusterEndpoints`, `DescribeDBClusterParameterGroups`
-
-`DescribeDBClusterParameters`, `DescribeDBClusterSnapshotAttributes`, `DescribeDBClusterSnapshots`, `DescribeDBLogFiles`, `DescribeDBProxies`, `DescribeDBProxyEndpoints`, `DescribeDBProxyTargetGroups`, `DescribeDBProxyTargets`
-
-`DescribeDBRecommendations`, `DescribeDBSecurityGroups`, `DescribeDBShardGroups`, `DescribeDBSnapshotAttributes`, `DescribeDBSnapshotTenantDatabases`, `DescribeEngineDefaultClusterParameters`, `DescribeEngineDefaultParameters`, `DescribeEventCategories`
-
-`DescribeEventSubscriptions`, `DescribeExportTasks`, `DescribeGlobalClusters`, `DescribeIntegrations`, `DescribeOptionGroupOptions`, `DescribePendingMaintenanceActions`, `DescribeReservedDBInstances`, `DescribeReservedDBInstancesOfferings`
-
-`DescribeSourceRegions`, `DescribeTenantDatabases`, `DescribeValidDBInstanceModifications`, `DisableHttpEndpoint`, `DownloadDBLogFilePortion`, `EnableHttpEndpoint`, `FailoverGlobalCluster`, `ModifyActivityStream`
-
-`ModifyCertificates`, `ModifyCurrentDBClusterCapacity`, `ModifyCustomDBEngineVersion`, `ModifyDBClusterEndpoint`, `ModifyDBClusterParameterGroup`, `ModifyDBClusterSnapshotAttribute`, `ModifyDBProxy`, `ModifyDBProxyEndpoint`
-
-`ModifyDBProxyTargetGroup`, `ModifyDBRecommendation`, `ModifyDBShardGroup`, `ModifyDBSnapshot`, `ModifyDBSnapshotAttribute`, `ModifyDBSubnetGroup`, `ModifyEventSubscription`, `ModifyGlobalCluster`
-
-`ModifyIntegration`, `ModifyTenantDatabase`, `PromoteReadReplicaDBCluster`, `PurchaseReservedDBInstancesOffering`, `RebootDBCluster`, `RebootDBShardGroup`, `RegisterDBProxyTargets`, `RemoveFromGlobalCluster`
-
-`RemoveRoleFromDBCluster`, `RemoveRoleFromDBInstance`, `RemoveSourceIdentifierFromSubscription`, `ResetDBClusterParameterGroup`, `ResetDBParameterGroup`, `RestoreDBClusterFromS3`, `RestoreDBClusterFromSnapshot`, `RestoreDBClusterToPointInTime`
-
-`RestoreDBInstanceFromS3`, `RevokeDBSecurityGroupIngress`, `StartActivityStream`, `StartDBCluster`, `StartDBInstanceAutomatedBackupsReplication`, `StartExportTask`, `StopActivityStream`, `StopDBCluster`
-
-`StopDBInstanceAutomatedBackupsReplication`, `SwitchoverBlueGreenDeployment`, `SwitchoverGlobalCluster`, `SwitchoverReadReplica`
-
-
-
-
-Registered stubs (0)
-
-None.
-
-
-
-Deliberately unsupported (12)
-
-`CreateDBCluster`, `CreateDBInstanceReadReplica`, `CreateOptionGroup`, `DeleteDBCluster`, `DeleteOptionGroup`, `DescribeDBClusters`, `DescribeOptionGroups`, `FailoverDBCluster`
-
-`ModifyDBCluster`, `ModifyOptionGroup`, `PromoteReadReplica`, `RestoreDBInstanceToPointInTime`
-
-
-
-
-Registered outside the pinned model (5)
-
-`AcknowledgeDBBootstrap`, `GetDBBootstrapConfig`, `PollDBCommands`, `RegisterDBInstance`, `SubmitDBStateChange`
-
-
-
-
-## s3
-
-Operation coverage is not enumerable: Spinifex delegates the S3 REST surface to Predastore, which has no operation-name dispatch table to compare mechanically.
-
-## sts
-
-Implements **4 of 8** modelled operations (50.0%).
-
-Implemented (4)
-
-`AssumeRole`, `AssumeRoleWithWebIdentity`, `GetCallerIdentity`, `GetSessionToken`
-
-
-
-
-Missing from dispatch (4)
-
-`AssumeRoleWithSAML`, `DecodeAuthorizationMessage`, `GetAccessKeyInfo`, `GetFederationToken`
-
-
-
-
-Registered stubs (0)
-
-None.
-
-
-
-Deliberately unsupported (0)
-
-None.
-
-
-
-Registered outside the pinned model (0)
-
-None.
-
-
diff --git a/docs/compatibility/acm-api-coverage/README.md b/docs/compatibility/acm-api-coverage/README.md
new file mode 100644
index 000000000..2774dfd6c
--- /dev/null
+++ b/docs/compatibility/acm-api-coverage/README.md
@@ -0,0 +1,57 @@
+---
+title: "ACM API Coverage"
+seoTitle: "AWS Certificate Manager API Coverage — Spinifex Docs"
+description: "Every operation in the AWS Certificate Manager API model and whether Spinifex implements it, generated from the gateway dispatch tables on each build."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - acm
+ - certificates
+ - tls
+---
+
+# ACM API Coverage
+
+## Overview
+
+Spinifex implements **9 of the 15** operations in the ACM `2015-12-08` API model, as pinned in `aws-sdk-go v1.55.8` — **60.0%**.
+
+### Import and issuance
+
+Spinifex both stores externally-issued certificates and issues its own for load balancer listener references. Certificates are account-scoped, and a delete is refused while any listener still references the ARN — there is no force flag, matching AWS.
+
+`RequestCertificate` mints an ARN immediately and returns `PENDING_VALIDATION`; it never issues inline except against a tenant private CA, which has no domain to validate. The validation mode is derived from deployment state rather than configured: the DNS provider API where a credential exists, a manual TXT record where the platform hosts the zone, and a private CA otherwise — the only option for a deployment with no publicly delegated domain.
+
+Terraform's canonical certificate, DNS record and validation flow works unmodified in every mode. Where Spinifex owns the record write it emits no `ResourceRecord`, so iterating the validation options yields zero records and the validation resource still blocks correctly by polling until the certificate is issued.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `AddTagsToCertificate` | ✅ Implemented |
+| `DeleteCertificate` | ✅ Implemented |
+| `DescribeCertificate` | ✅ Implemented |
+| `ExportCertificate` | ❌ Not implemented |
+| `GetAccountConfiguration` | ❌ Not implemented |
+| `GetCertificate` | ✅ Implemented |
+| `ImportCertificate` | ✅ Implemented |
+| `ListCertificates` | ✅ Implemented |
+| `ListTagsForCertificate` | ✅ Implemented |
+| `PutAccountConfiguration` | ❌ Not implemented |
+| `RemoveTagsFromCertificate` | ✅ Implemented |
+| `RenewCertificate` | ❌ Not implemented |
+| `RequestCertificate` | ✅ Implemented |
+| `ResendValidationEmail` | ❌ Not implemented |
+| `UpdateCertificateOptions` | ❌ Not implemented |
diff --git a/docs/compatibility/acm-api-coverage/intro.md b/docs/compatibility/acm-api-coverage/intro.md
new file mode 100644
index 000000000..20a461952
--- /dev/null
+++ b/docs/compatibility/acm-api-coverage/intro.md
@@ -0,0 +1,7 @@
+### Import and issuance
+
+Spinifex both stores externally-issued certificates and issues its own for load balancer listener references. Certificates are account-scoped, and a delete is refused while any listener still references the ARN — there is no force flag, matching AWS.
+
+`RequestCertificate` mints an ARN immediately and returns `PENDING_VALIDATION`; it never issues inline except against a tenant private CA, which has no domain to validate. The validation mode is derived from deployment state rather than configured: the DNS provider API where a credential exists, a manual TXT record where the platform hosts the zone, and a private CA otherwise — the only option for a deployment with no publicly delegated domain.
+
+Terraform's canonical certificate, DNS record and validation flow works unmodified in every mode. Where Spinifex owns the record write it emits no `ResourceRecord`, so iterating the validation options yields zero records and the validation resource still blocks correctly by polling until the certificate is issued.
diff --git a/docs/compatibility/aws-api-coverage/README.md b/docs/compatibility/aws-api-coverage/README.md
new file mode 100644
index 000000000..3e311fb80
--- /dev/null
+++ b/docs/compatibility/aws-api-coverage/README.md
@@ -0,0 +1,45 @@
+---
+title: "AWS API Coverage"
+seoTitle: "Which AWS API Operations Spinifex Implements — Spinifex Docs"
+description: "Operation-level coverage of every AWS API Spinifex serves, generated from its gateway dispatch tables and the pinned AWS SDK service models on each build."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - api
+ - operations
+---
+
+# AWS API Coverage
+
+## Overview
+
+Spinifex serves the AWS APIs below. Every page counts the operations in the pinned `aws-sdk-go v1.55.8` `api-2.json` model for its service and reports, operation by operation, whether Spinifex implements it.
+
+| Service | API version | Implemented | Modelled | Coverage |
+|---|---|---:|---:|---:|
+| [ACM](/docs/acm-api-coverage) | 2015-12-08 | 9 | 15 | 60.0% |
+| [EC2](/docs/ec2-api-coverage) | 2016-11-15 | 121 | 625 | 19.4% |
+| [ECR](/docs/ecr-api-coverage) | 2015-09-21 | 19 | 47 | 40.4% |
+| [ECS](/docs/ecs-api-coverage) | 2014-11-13 | 31 | 56 | 55.4% |
+| [EKS](/docs/eks-api-coverage) | 2017-11-01 | 34 | 56 | 60.7% |
+| [ELBv2](/docs/elbv2-api-coverage) | 2015-12-01 | 33 | 46 | 71.7% |
+| [IAM](/docs/iam-api-coverage) | 2010-05-08 | 75 | 159 | 47.2% |
+| [RDS](/docs/rds-api-coverage) | 2014-10-31 | 26 | 162 | 16.0% |
+| [S3](/docs/s3-api-coverage) | 2006-03-01 | — | 99 | — |
+| [STS](/docs/sts-api-coverage) | 2011-06-15 | 4 | 8 | 50.0% |
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+### What "implemented" means here
+
+An operation is implemented when the gateway binds it to a real handler. These pages are generated from those dispatch tables on every build, so they cannot go stale against the code. That is a mechanical fact, and it is the only claim they make. It does not say the handler honours every parameter AWS models, and no page reports parameter or field-level detail: a handler receives a fully-populated typed SDK struct, so nothing distinguishes a field it honours from one it ignores. Behavioural conformance is measured separately by the integration conformance suite.
diff --git a/docs/compatibility/aws-api-coverage/intro.md b/docs/compatibility/aws-api-coverage/intro.md
new file mode 100644
index 000000000..b29835c37
--- /dev/null
+++ b/docs/compatibility/aws-api-coverage/intro.md
@@ -0,0 +1,3 @@
+### What "implemented" means here
+
+An operation is implemented when the gateway binds it to a real handler. These pages are generated from those dispatch tables on every build, so they cannot go stale against the code. That is a mechanical fact, and it is the only claim they make. It does not say the handler honours every parameter AWS models, and no page reports parameter or field-level detail: a handler receives a fully-populated typed SDK struct, so nothing distinguishes a field it honours from one it ignores. Behavioural conformance is measured separately by the integration conformance suite.
diff --git a/docs/compatibility/ec2-api-coverage/README.md b/docs/compatibility/ec2-api-coverage/README.md
new file mode 100644
index 000000000..72f18031a
--- /dev/null
+++ b/docs/compatibility/ec2-api-coverage/README.md
@@ -0,0 +1,665 @@
+---
+title: "EC2 API Coverage"
+seoTitle: "Amazon EC2 API Coverage on Spinifex — Spinifex Docs"
+description: "Every operation in the Amazon EC2 API model and whether Spinifex implements it, covering instances, EBS volumes, VPC networking, tags and security groups."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - ec2
+ - compute
+ - vpc
+---
+
+# EC2 API Coverage
+
+## Overview
+
+Spinifex implements **121 of the 625** operations in the EC2 `2016-11-15` API model, as pinned in `aws-sdk-go v1.55.8` — **19.4%**.
+
+### Spot instances are a mock
+
+Spot Instance Requests are a mock over the on-demand `RunInstances` path. A request synchronously launches real VMs on the operator's own compute and is then reported `active` and `fulfilled`. There is no spot market: no bidding, no price rejection, no interruption and no reclamation, and instances are never taken back.
+
+`DescribeSpotPriceHistory` is the one operation on that surface deliberately left unimplemented. On owned hardware there is no spot-to-on-demand price differential, so any figure it returned would be invented, and an invented price is worse than an absent one.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `AcceptAddressTransfer` | ❌ Not implemented |
+| `AcceptReservedInstancesExchangeQuote` | ❌ Not implemented |
+| `AcceptTransitGatewayMulticastDomainAssociations` | ❌ Not implemented |
+| `AcceptTransitGatewayPeeringAttachment` | ❌ Not implemented |
+| `AcceptTransitGatewayVpcAttachment` | ❌ Not implemented |
+| `AcceptVpcEndpointConnections` | ❌ Not implemented |
+| `AcceptVpcPeeringConnection` | ❌ Not implemented |
+| `AdvertiseByoipCidr` | ❌ Not implemented |
+| `AllocateAddress` | ✅ Implemented |
+| `AllocateHosts` | ❌ Not implemented |
+| `AllocateIpamPoolCidr` | ❌ Not implemented |
+| `ApplySecurityGroupsToClientVpnTargetNetwork` | ❌ Not implemented |
+| `AssignIpv6Addresses` | ❌ Not implemented |
+| `AssignPrivateIpAddresses` | ❌ Not implemented |
+| `AssignPrivateNatGatewayAddress` | ❌ Not implemented |
+| `AssociateAddress` | ✅ Implemented |
+| `AssociateClientVpnTargetNetwork` | ❌ Not implemented |
+| `AssociateDhcpOptions` | ❌ Not implemented |
+| `AssociateEnclaveCertificateIamRole` | ❌ Not implemented |
+| `AssociateIamInstanceProfile` | ✅ Implemented |
+| `AssociateInstanceEventWindow` | ❌ Not implemented |
+| `AssociateIpamByoasn` | ❌ Not implemented |
+| `AssociateIpamResourceDiscovery` | ❌ Not implemented |
+| `AssociateNatGatewayAddress` | ❌ Not implemented |
+| `AssociateRouteTable` | ✅ Implemented |
+| `AssociateSubnetCidrBlock` | ❌ Not implemented |
+| `AssociateTransitGatewayMulticastDomain` | ❌ Not implemented |
+| `AssociateTransitGatewayPolicyTable` | ❌ Not implemented |
+| `AssociateTransitGatewayRouteTable` | ❌ Not implemented |
+| `AssociateTrunkInterface` | ❌ Not implemented |
+| `AssociateVpcCidrBlock` | ❌ Not implemented |
+| `AttachClassicLinkVpc` | ❌ Not implemented |
+| `AttachInternetGateway` | ✅ Implemented |
+| `AttachNetworkInterface` | ✅ Implemented |
+| `AttachVerifiedAccessTrustProvider` | ❌ Not implemented |
+| `AttachVolume` | ✅ Implemented |
+| `AttachVpnGateway` | ❌ Not implemented |
+| `AuthorizeClientVpnIngress` | ❌ Not implemented |
+| `AuthorizeSecurityGroupEgress` | ✅ Implemented |
+| `AuthorizeSecurityGroupIngress` | ✅ Implemented |
+| `BundleInstance` | ❌ Not implemented |
+| `CancelBundleTask` | ❌ Not implemented |
+| `CancelCapacityReservation` | ✅ Implemented |
+| `CancelCapacityReservationFleets` | ❌ Not implemented |
+| `CancelConversionTask` | ❌ Not implemented |
+| `CancelExportTask` | ❌ Not implemented |
+| `CancelImageLaunchPermission` | ❌ Not implemented |
+| `CancelImportTask` | ❌ Not implemented |
+| `CancelReservedInstancesListing` | ❌ Not implemented |
+| `CancelSpotFleetRequests` | ❌ Not implemented |
+| `CancelSpotInstanceRequests` | ✅ Implemented |
+| `ConfirmProductInstance` | ❌ Not implemented |
+| `CopyFpgaImage` | ❌ Not implemented |
+| `CopyImage` | ✅ Implemented |
+| `CopySnapshot` | ✅ Implemented |
+| `CreateCapacityReservation` | ✅ Implemented |
+| `CreateCapacityReservationFleet` | ❌ Not implemented |
+| `CreateCarrierGateway` | ❌ Not implemented |
+| `CreateClientVpnEndpoint` | ❌ Not implemented |
+| `CreateClientVpnRoute` | ❌ Not implemented |
+| `CreateCoipCidr` | ❌ Not implemented |
+| `CreateCoipPool` | ❌ Not implemented |
+| `CreateCustomerGateway` | ❌ Not implemented |
+| `CreateDefaultSubnet` | ❌ Not implemented |
+| `CreateDefaultVpc` | ❌ Not implemented |
+| `CreateDhcpOptions` | ❌ Not implemented |
+| `CreateEgressOnlyInternetGateway` | ✅ Implemented |
+| `CreateFleet` | ❌ Not implemented |
+| `CreateFlowLogs` | ❌ Not implemented |
+| `CreateFpgaImage` | ❌ Not implemented |
+| `CreateImage` | ✅ Implemented |
+| `CreateInstanceConnectEndpoint` | ❌ Not implemented |
+| `CreateInstanceEventWindow` | ❌ Not implemented |
+| `CreateInstanceExportTask` | ❌ Not implemented |
+| `CreateInternetGateway` | ✅ Implemented |
+| `CreateIpam` | ❌ Not implemented |
+| `CreateIpamExternalResourceVerificationToken` | ❌ Not implemented |
+| `CreateIpamPool` | ❌ Not implemented |
+| `CreateIpamResourceDiscovery` | ❌ Not implemented |
+| `CreateIpamScope` | ❌ Not implemented |
+| `CreateKeyPair` | ✅ Implemented |
+| `CreateLaunchTemplate` | ✅ Implemented |
+| `CreateLaunchTemplateVersion` | ✅ Implemented |
+| `CreateLocalGatewayRoute` | ❌ Not implemented |
+| `CreateLocalGatewayRouteTable` | ❌ Not implemented |
+| `CreateLocalGatewayRouteTableVirtualInterfaceGroupAssociation` | ❌ Not implemented |
+| `CreateLocalGatewayRouteTableVpcAssociation` | ❌ Not implemented |
+| `CreateManagedPrefixList` | ❌ Not implemented |
+| `CreateNatGateway` | ✅ Implemented |
+| `CreateNetworkAcl` | ❌ Not implemented |
+| `CreateNetworkAclEntry` | ❌ Not implemented |
+| `CreateNetworkInsightsAccessScope` | ❌ Not implemented |
+| `CreateNetworkInsightsPath` | ❌ Not implemented |
+| `CreateNetworkInterface` | ✅ Implemented |
+| `CreateNetworkInterfacePermission` | ❌ Not implemented |
+| `CreatePlacementGroup` | ✅ Implemented |
+| `CreatePublicIpv4Pool` | ❌ Not implemented |
+| `CreateReplaceRootVolumeTask` | ❌ Not implemented |
+| `CreateReservedInstancesListing` | ❌ Not implemented |
+| `CreateRestoreImageTask` | ❌ Not implemented |
+| `CreateRoute` | ✅ Implemented |
+| `CreateRouteTable` | ✅ Implemented |
+| `CreateSecurityGroup` | ✅ Implemented |
+| `CreateSnapshot` | ✅ Implemented |
+| `CreateSnapshots` | ❌ Not implemented |
+| `CreateSpotDatafeedSubscription` | ❌ Not implemented |
+| `CreateStoreImageTask` | ❌ Not implemented |
+| `CreateSubnet` | ✅ Implemented |
+| `CreateSubnetCidrReservation` | ❌ Not implemented |
+| `CreateTags` | ✅ Implemented |
+| `CreateTrafficMirrorFilter` | ❌ Not implemented |
+| `CreateTrafficMirrorFilterRule` | ❌ Not implemented |
+| `CreateTrafficMirrorSession` | ❌ Not implemented |
+| `CreateTrafficMirrorTarget` | ❌ Not implemented |
+| `CreateTransitGateway` | ❌ Not implemented |
+| `CreateTransitGatewayConnect` | ❌ Not implemented |
+| `CreateTransitGatewayConnectPeer` | ❌ Not implemented |
+| `CreateTransitGatewayMulticastDomain` | ❌ Not implemented |
+| `CreateTransitGatewayPeeringAttachment` | ❌ Not implemented |
+| `CreateTransitGatewayPolicyTable` | ❌ Not implemented |
+| `CreateTransitGatewayPrefixListReference` | ❌ Not implemented |
+| `CreateTransitGatewayRoute` | ❌ Not implemented |
+| `CreateTransitGatewayRouteTable` | ❌ Not implemented |
+| `CreateTransitGatewayRouteTableAnnouncement` | ❌ Not implemented |
+| `CreateTransitGatewayVpcAttachment` | ❌ Not implemented |
+| `CreateVerifiedAccessEndpoint` | ❌ Not implemented |
+| `CreateVerifiedAccessGroup` | ❌ Not implemented |
+| `CreateVerifiedAccessInstance` | ❌ Not implemented |
+| `CreateVerifiedAccessTrustProvider` | ❌ Not implemented |
+| `CreateVolume` | ✅ Implemented |
+| `CreateVpc` | ✅ Implemented |
+| `CreateVpcEndpoint` | ❌ Not implemented |
+| `CreateVpcEndpointConnectionNotification` | ❌ Not implemented |
+| `CreateVpcEndpointServiceConfiguration` | ❌ Not implemented |
+| `CreateVpcPeeringConnection` | ❌ Not implemented |
+| `CreateVpnConnection` | ❌ Not implemented |
+| `CreateVpnConnectionRoute` | ❌ Not implemented |
+| `CreateVpnGateway` | ❌ Not implemented |
+| `DeleteCarrierGateway` | ❌ Not implemented |
+| `DeleteClientVpnEndpoint` | ❌ Not implemented |
+| `DeleteClientVpnRoute` | ❌ Not implemented |
+| `DeleteCoipCidr` | ❌ Not implemented |
+| `DeleteCoipPool` | ❌ Not implemented |
+| `DeleteCustomerGateway` | ❌ Not implemented |
+| `DeleteDhcpOptions` | ❌ Not implemented |
+| `DeleteEgressOnlyInternetGateway` | ✅ Implemented |
+| `DeleteFleets` | ❌ Not implemented |
+| `DeleteFlowLogs` | ❌ Not implemented |
+| `DeleteFpgaImage` | ❌ Not implemented |
+| `DeleteInstanceConnectEndpoint` | ❌ Not implemented |
+| `DeleteInstanceEventWindow` | ❌ Not implemented |
+| `DeleteInternetGateway` | ✅ Implemented |
+| `DeleteIpam` | ❌ Not implemented |
+| `DeleteIpamExternalResourceVerificationToken` | ❌ Not implemented |
+| `DeleteIpamPool` | ❌ Not implemented |
+| `DeleteIpamResourceDiscovery` | ❌ Not implemented |
+| `DeleteIpamScope` | ❌ Not implemented |
+| `DeleteKeyPair` | ✅ Implemented |
+| `DeleteLaunchTemplate` | ✅ Implemented |
+| `DeleteLaunchTemplateVersions` | ✅ Implemented |
+| `DeleteLocalGatewayRoute` | ❌ Not implemented |
+| `DeleteLocalGatewayRouteTable` | ❌ Not implemented |
+| `DeleteLocalGatewayRouteTableVirtualInterfaceGroupAssociation` | ❌ Not implemented |
+| `DeleteLocalGatewayRouteTableVpcAssociation` | ❌ Not implemented |
+| `DeleteManagedPrefixList` | ❌ Not implemented |
+| `DeleteNatGateway` | ✅ Implemented |
+| `DeleteNetworkAcl` | ❌ Not implemented |
+| `DeleteNetworkAclEntry` | ❌ Not implemented |
+| `DeleteNetworkInsightsAccessScope` | ❌ Not implemented |
+| `DeleteNetworkInsightsAccessScopeAnalysis` | ❌ Not implemented |
+| `DeleteNetworkInsightsAnalysis` | ❌ Not implemented |
+| `DeleteNetworkInsightsPath` | ❌ Not implemented |
+| `DeleteNetworkInterface` | ✅ Implemented |
+| `DeleteNetworkInterfacePermission` | ❌ Not implemented |
+| `DeletePlacementGroup` | ✅ Implemented |
+| `DeletePublicIpv4Pool` | ❌ Not implemented |
+| `DeleteQueuedReservedInstances` | ❌ Not implemented |
+| `DeleteRoute` | ✅ Implemented |
+| `DeleteRouteTable` | ✅ Implemented |
+| `DeleteSecurityGroup` | ✅ Implemented |
+| `DeleteSnapshot` | ✅ Implemented |
+| `DeleteSpotDatafeedSubscription` | ❌ Not implemented |
+| `DeleteSubnet` | ✅ Implemented |
+| `DeleteSubnetCidrReservation` | ❌ Not implemented |
+| `DeleteTags` | ✅ Implemented |
+| `DeleteTrafficMirrorFilter` | ❌ Not implemented |
+| `DeleteTrafficMirrorFilterRule` | ❌ Not implemented |
+| `DeleteTrafficMirrorSession` | ❌ Not implemented |
+| `DeleteTrafficMirrorTarget` | ❌ Not implemented |
+| `DeleteTransitGateway` | ❌ Not implemented |
+| `DeleteTransitGatewayConnect` | ❌ Not implemented |
+| `DeleteTransitGatewayConnectPeer` | ❌ Not implemented |
+| `DeleteTransitGatewayMulticastDomain` | ❌ Not implemented |
+| `DeleteTransitGatewayPeeringAttachment` | ❌ Not implemented |
+| `DeleteTransitGatewayPolicyTable` | ❌ Not implemented |
+| `DeleteTransitGatewayPrefixListReference` | ❌ Not implemented |
+| `DeleteTransitGatewayRoute` | ❌ Not implemented |
+| `DeleteTransitGatewayRouteTable` | ❌ Not implemented |
+| `DeleteTransitGatewayRouteTableAnnouncement` | ❌ Not implemented |
+| `DeleteTransitGatewayVpcAttachment` | ❌ Not implemented |
+| `DeleteVerifiedAccessEndpoint` | ❌ Not implemented |
+| `DeleteVerifiedAccessGroup` | ❌ Not implemented |
+| `DeleteVerifiedAccessInstance` | ❌ Not implemented |
+| `DeleteVerifiedAccessTrustProvider` | ❌ Not implemented |
+| `DeleteVolume` | ✅ Implemented |
+| `DeleteVpc` | ✅ Implemented |
+| `DeleteVpcEndpointConnectionNotifications` | ❌ Not implemented |
+| `DeleteVpcEndpointServiceConfigurations` | ❌ Not implemented |
+| `DeleteVpcEndpoints` | ❌ Not implemented |
+| `DeleteVpcPeeringConnection` | ❌ Not implemented |
+| `DeleteVpnConnection` | ❌ Not implemented |
+| `DeleteVpnConnectionRoute` | ❌ Not implemented |
+| `DeleteVpnGateway` | ❌ Not implemented |
+| `DeprovisionByoipCidr` | ❌ Not implemented |
+| `DeprovisionIpamByoasn` | ❌ Not implemented |
+| `DeprovisionIpamPoolCidr` | ❌ Not implemented |
+| `DeprovisionPublicIpv4PoolCidr` | ❌ Not implemented |
+| `DeregisterImage` | ✅ Implemented |
+| `DeregisterInstanceEventNotificationAttributes` | ❌ Not implemented |
+| `DeregisterTransitGatewayMulticastGroupMembers` | ❌ Not implemented |
+| `DeregisterTransitGatewayMulticastGroupSources` | ❌ Not implemented |
+| `DescribeAccountAttributes` | ✅ Implemented |
+| `DescribeAddressTransfers` | ❌ Not implemented |
+| `DescribeAddresses` | ✅ Implemented |
+| `DescribeAddressesAttribute` | ✅ Implemented |
+| `DescribeAggregateIdFormat` | ❌ Not implemented |
+| `DescribeAvailabilityZones` | ✅ Implemented |
+| `DescribeAwsNetworkPerformanceMetricSubscriptions` | ❌ Not implemented |
+| `DescribeBundleTasks` | ❌ Not implemented |
+| `DescribeByoipCidrs` | ❌ Not implemented |
+| `DescribeCapacityBlockOfferings` | ❌ Not implemented |
+| `DescribeCapacityReservationFleets` | ❌ Not implemented |
+| `DescribeCapacityReservations` | ✅ Implemented |
+| `DescribeCarrierGateways` | ❌ Not implemented |
+| `DescribeClassicLinkInstances` | ❌ Not implemented |
+| `DescribeClientVpnAuthorizationRules` | ❌ Not implemented |
+| `DescribeClientVpnConnections` | ❌ Not implemented |
+| `DescribeClientVpnEndpoints` | ❌ Not implemented |
+| `DescribeClientVpnRoutes` | ❌ Not implemented |
+| `DescribeClientVpnTargetNetworks` | ❌ Not implemented |
+| `DescribeCoipPools` | ❌ Not implemented |
+| `DescribeConversionTasks` | ❌ Not implemented |
+| `DescribeCustomerGateways` | ❌ Not implemented |
+| `DescribeDhcpOptions` | ❌ Not implemented |
+| `DescribeEgressOnlyInternetGateways` | ✅ Implemented |
+| `DescribeElasticGpus` | ❌ Not implemented |
+| `DescribeExportImageTasks` | ❌ Not implemented |
+| `DescribeExportTasks` | ❌ Not implemented |
+| `DescribeFastLaunchImages` | ❌ Not implemented |
+| `DescribeFastSnapshotRestores` | ❌ Not implemented |
+| `DescribeFleetHistory` | ❌ Not implemented |
+| `DescribeFleetInstances` | ❌ Not implemented |
+| `DescribeFleets` | ❌ Not implemented |
+| `DescribeFlowLogs` | ❌ Not implemented |
+| `DescribeFpgaImageAttribute` | ❌ Not implemented |
+| `DescribeFpgaImages` | ❌ Not implemented |
+| `DescribeHostReservationOfferings` | ❌ Not implemented |
+| `DescribeHostReservations` | ❌ Not implemented |
+| `DescribeHosts` | ❌ Not implemented |
+| `DescribeIamInstanceProfileAssociations` | ✅ Implemented |
+| `DescribeIdFormat` | ❌ Not implemented |
+| `DescribeIdentityIdFormat` | ❌ Not implemented |
+| `DescribeImageAttribute` | ✅ Implemented |
+| `DescribeImages` | ✅ Implemented |
+| `DescribeImportImageTasks` | ❌ Not implemented |
+| `DescribeImportSnapshotTasks` | ❌ Not implemented |
+| `DescribeInstanceAttribute` | ✅ Implemented |
+| `DescribeInstanceConnectEndpoints` | ❌ Not implemented |
+| `DescribeInstanceCreditSpecifications` | ✅ Implemented |
+| `DescribeInstanceEventNotificationAttributes` | ❌ Not implemented |
+| `DescribeInstanceEventWindows` | ❌ Not implemented |
+| `DescribeInstanceStatus` | ✅ Implemented |
+| `DescribeInstanceTopology` | ❌ Not implemented |
+| `DescribeInstanceTypeOfferings` | ❌ Not implemented |
+| `DescribeInstanceTypes` | ✅ Implemented |
+| `DescribeInstances` | ✅ Implemented |
+| `DescribeInternetGateways` | ✅ Implemented |
+| `DescribeIpamByoasn` | ❌ Not implemented |
+| `DescribeIpamExternalResourceVerificationTokens` | ❌ Not implemented |
+| `DescribeIpamPools` | ❌ Not implemented |
+| `DescribeIpamResourceDiscoveries` | ❌ Not implemented |
+| `DescribeIpamResourceDiscoveryAssociations` | ❌ Not implemented |
+| `DescribeIpamScopes` | ❌ Not implemented |
+| `DescribeIpams` | ❌ Not implemented |
+| `DescribeIpv6Pools` | ❌ Not implemented |
+| `DescribeKeyPairs` | ✅ Implemented |
+| `DescribeLaunchTemplateVersions` | ✅ Implemented |
+| `DescribeLaunchTemplates` | ✅ Implemented |
+| `DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociations` | ❌ Not implemented |
+| `DescribeLocalGatewayRouteTableVpcAssociations` | ❌ Not implemented |
+| `DescribeLocalGatewayRouteTables` | ❌ Not implemented |
+| `DescribeLocalGatewayVirtualInterfaceGroups` | ❌ Not implemented |
+| `DescribeLocalGatewayVirtualInterfaces` | ❌ Not implemented |
+| `DescribeLocalGateways` | ❌ Not implemented |
+| `DescribeLockedSnapshots` | ❌ Not implemented |
+| `DescribeMacHosts` | ❌ Not implemented |
+| `DescribeManagedPrefixLists` | ❌ Not implemented |
+| `DescribeMovingAddresses` | ❌ Not implemented |
+| `DescribeNatGateways` | ✅ Implemented |
+| `DescribeNetworkAcls` | ❌ Not implemented |
+| `DescribeNetworkInsightsAccessScopeAnalyses` | ❌ Not implemented |
+| `DescribeNetworkInsightsAccessScopes` | ❌ Not implemented |
+| `DescribeNetworkInsightsAnalyses` | ❌ Not implemented |
+| `DescribeNetworkInsightsPaths` | ❌ Not implemented |
+| `DescribeNetworkInterfaceAttribute` | ❌ Not implemented |
+| `DescribeNetworkInterfacePermissions` | ❌ Not implemented |
+| `DescribeNetworkInterfaces` | ✅ Implemented |
+| `DescribePlacementGroups` | ✅ Implemented |
+| `DescribePrefixLists` | ❌ Not implemented |
+| `DescribePrincipalIdFormat` | ❌ Not implemented |
+| `DescribePublicIpv4Pools` | ❌ Not implemented |
+| `DescribeRegions` | ✅ Implemented |
+| `DescribeReplaceRootVolumeTasks` | ❌ Not implemented |
+| `DescribeReservedInstances` | ❌ Not implemented |
+| `DescribeReservedInstancesListings` | ❌ Not implemented |
+| `DescribeReservedInstancesModifications` | ❌ Not implemented |
+| `DescribeReservedInstancesOfferings` | ❌ Not implemented |
+| `DescribeRouteTables` | ✅ Implemented |
+| `DescribeScheduledInstanceAvailability` | ❌ Not implemented |
+| `DescribeScheduledInstances` | ❌ Not implemented |
+| `DescribeSecurityGroupReferences` | ❌ Not implemented |
+| `DescribeSecurityGroupRules` | ✅ Implemented |
+| `DescribeSecurityGroups` | ✅ Implemented |
+| `DescribeSnapshotAttribute` | ❌ Not implemented |
+| `DescribeSnapshotTierStatus` | ❌ Not implemented |
+| `DescribeSnapshots` | ✅ Implemented |
+| `DescribeSpotDatafeedSubscription` | ❌ Not implemented |
+| `DescribeSpotFleetInstances` | ❌ Not implemented |
+| `DescribeSpotFleetRequestHistory` | ❌ Not implemented |
+| `DescribeSpotFleetRequests` | ❌ Not implemented |
+| `DescribeSpotInstanceRequests` | ✅ Implemented |
+| `DescribeSpotPriceHistory` | ❌ Not implemented |
+| `DescribeStaleSecurityGroups` | ❌ Not implemented |
+| `DescribeStoreImageTasks` | ❌ Not implemented |
+| `DescribeSubnets` | ✅ Implemented |
+| `DescribeTags` | ✅ Implemented |
+| `DescribeTrafficMirrorFilterRules` | ❌ Not implemented |
+| `DescribeTrafficMirrorFilters` | ❌ Not implemented |
+| `DescribeTrafficMirrorSessions` | ❌ Not implemented |
+| `DescribeTrafficMirrorTargets` | ❌ Not implemented |
+| `DescribeTransitGatewayAttachments` | ❌ Not implemented |
+| `DescribeTransitGatewayConnectPeers` | ❌ Not implemented |
+| `DescribeTransitGatewayConnects` | ❌ Not implemented |
+| `DescribeTransitGatewayMulticastDomains` | ❌ Not implemented |
+| `DescribeTransitGatewayPeeringAttachments` | ❌ Not implemented |
+| `DescribeTransitGatewayPolicyTables` | ❌ Not implemented |
+| `DescribeTransitGatewayRouteTableAnnouncements` | ❌ Not implemented |
+| `DescribeTransitGatewayRouteTables` | ❌ Not implemented |
+| `DescribeTransitGatewayVpcAttachments` | ❌ Not implemented |
+| `DescribeTransitGateways` | ❌ Not implemented |
+| `DescribeTrunkInterfaceAssociations` | ❌ Not implemented |
+| `DescribeVerifiedAccessEndpoints` | ❌ Not implemented |
+| `DescribeVerifiedAccessGroups` | ❌ Not implemented |
+| `DescribeVerifiedAccessInstanceLoggingConfigurations` | ❌ Not implemented |
+| `DescribeVerifiedAccessInstances` | ❌ Not implemented |
+| `DescribeVerifiedAccessTrustProviders` | ❌ Not implemented |
+| `DescribeVolumeAttribute` | ❌ Not implemented |
+| `DescribeVolumeStatus` | ✅ Implemented |
+| `DescribeVolumes` | ✅ Implemented |
+| `DescribeVolumesModifications` | ✅ Implemented |
+| `DescribeVpcAttribute` | ✅ Implemented |
+| `DescribeVpcClassicLink` | ❌ Not implemented |
+| `DescribeVpcClassicLinkDnsSupport` | ❌ Not implemented |
+| `DescribeVpcEndpointConnectionNotifications` | ❌ Not implemented |
+| `DescribeVpcEndpointConnections` | ❌ Not implemented |
+| `DescribeVpcEndpointServiceConfigurations` | ❌ Not implemented |
+| `DescribeVpcEndpointServicePermissions` | ❌ Not implemented |
+| `DescribeVpcEndpointServices` | ❌ Not implemented |
+| `DescribeVpcEndpoints` | ❌ Not implemented |
+| `DescribeVpcPeeringConnections` | ❌ Not implemented |
+| `DescribeVpcs` | ✅ Implemented |
+| `DescribeVpnConnections` | ❌ Not implemented |
+| `DescribeVpnGateways` | ❌ Not implemented |
+| `DetachClassicLinkVpc` | ❌ Not implemented |
+| `DetachInternetGateway` | ✅ Implemented |
+| `DetachNetworkInterface` | ✅ Implemented |
+| `DetachVerifiedAccessTrustProvider` | ❌ Not implemented |
+| `DetachVolume` | ✅ Implemented |
+| `DetachVpnGateway` | ❌ Not implemented |
+| `DisableAddressTransfer` | ❌ Not implemented |
+| `DisableAwsNetworkPerformanceMetricSubscription` | ❌ Not implemented |
+| `DisableEbsEncryptionByDefault` | ✅ Implemented |
+| `DisableFastLaunch` | ❌ Not implemented |
+| `DisableFastSnapshotRestores` | ❌ Not implemented |
+| `DisableImage` | ❌ Not implemented |
+| `DisableImageBlockPublicAccess` | ❌ Not implemented |
+| `DisableImageDeprecation` | ❌ Not implemented |
+| `DisableImageDeregistrationProtection` | ❌ Not implemented |
+| `DisableIpamOrganizationAdminAccount` | ❌ Not implemented |
+| `DisableSerialConsoleAccess` | ✅ Implemented |
+| `DisableSnapshotBlockPublicAccess` | ❌ Not implemented |
+| `DisableTransitGatewayRouteTablePropagation` | ❌ Not implemented |
+| `DisableVgwRoutePropagation` | ❌ Not implemented |
+| `DisableVpcClassicLink` | ❌ Not implemented |
+| `DisableVpcClassicLinkDnsSupport` | ❌ Not implemented |
+| `DisassociateAddress` | ✅ Implemented |
+| `DisassociateClientVpnTargetNetwork` | ❌ Not implemented |
+| `DisassociateEnclaveCertificateIamRole` | ❌ Not implemented |
+| `DisassociateIamInstanceProfile` | ✅ Implemented |
+| `DisassociateInstanceEventWindow` | ❌ Not implemented |
+| `DisassociateIpamByoasn` | ❌ Not implemented |
+| `DisassociateIpamResourceDiscovery` | ❌ Not implemented |
+| `DisassociateNatGatewayAddress` | ❌ Not implemented |
+| `DisassociateRouteTable` | ✅ Implemented |
+| `DisassociateSubnetCidrBlock` | ❌ Not implemented |
+| `DisassociateTransitGatewayMulticastDomain` | ❌ Not implemented |
+| `DisassociateTransitGatewayPolicyTable` | ❌ Not implemented |
+| `DisassociateTransitGatewayRouteTable` | ❌ Not implemented |
+| `DisassociateTrunkInterface` | ❌ Not implemented |
+| `DisassociateVpcCidrBlock` | ❌ Not implemented |
+| `EnableAddressTransfer` | ❌ Not implemented |
+| `EnableAwsNetworkPerformanceMetricSubscription` | ❌ Not implemented |
+| `EnableEbsEncryptionByDefault` | ✅ Implemented |
+| `EnableFastLaunch` | ❌ Not implemented |
+| `EnableFastSnapshotRestores` | ❌ Not implemented |
+| `EnableImage` | ❌ Not implemented |
+| `EnableImageBlockPublicAccess` | ❌ Not implemented |
+| `EnableImageDeprecation` | ❌ Not implemented |
+| `EnableImageDeregistrationProtection` | ❌ Not implemented |
+| `EnableIpamOrganizationAdminAccount` | ❌ Not implemented |
+| `EnableReachabilityAnalyzerOrganizationSharing` | ❌ Not implemented |
+| `EnableSerialConsoleAccess` | ✅ Implemented |
+| `EnableSnapshotBlockPublicAccess` | ❌ Not implemented |
+| `EnableTransitGatewayRouteTablePropagation` | ❌ Not implemented |
+| `EnableVgwRoutePropagation` | ❌ Not implemented |
+| `EnableVolumeIO` | ❌ Not implemented |
+| `EnableVpcClassicLink` | ❌ Not implemented |
+| `EnableVpcClassicLinkDnsSupport` | ❌ Not implemented |
+| `ExportClientVpnClientCertificateRevocationList` | ❌ Not implemented |
+| `ExportClientVpnClientConfiguration` | ❌ Not implemented |
+| `ExportImage` | ❌ Not implemented |
+| `ExportTransitGatewayRoutes` | ❌ Not implemented |
+| `GetAssociatedEnclaveCertificateIamRoles` | ❌ Not implemented |
+| `GetAssociatedIpv6PoolCidrs` | ❌ Not implemented |
+| `GetAwsNetworkPerformanceData` | ❌ Not implemented |
+| `GetCapacityReservationUsage` | ❌ Not implemented |
+| `GetCoipPoolUsage` | ❌ Not implemented |
+| `GetConsoleOutput` | ✅ Implemented |
+| `GetConsoleScreenshot` | ❌ Not implemented |
+| `GetDefaultCreditSpecification` | ❌ Not implemented |
+| `GetEbsDefaultKmsKeyId` | ❌ Not implemented |
+| `GetEbsEncryptionByDefault` | ✅ Implemented |
+| `GetFlowLogsIntegrationTemplate` | ❌ Not implemented |
+| `GetGroupsForCapacityReservation` | ❌ Not implemented |
+| `GetHostReservationPurchasePreview` | ❌ Not implemented |
+| `GetImageBlockPublicAccessState` | ❌ Not implemented |
+| `GetInstanceMetadataDefaults` | ❌ Not implemented |
+| `GetInstanceTpmEkPub` | ❌ Not implemented |
+| `GetInstanceTypesFromInstanceRequirements` | ❌ Not implemented |
+| `GetInstanceUefiData` | ❌ Not implemented |
+| `GetIpamAddressHistory` | ❌ Not implemented |
+| `GetIpamDiscoveredAccounts` | ❌ Not implemented |
+| `GetIpamDiscoveredPublicAddresses` | ❌ Not implemented |
+| `GetIpamDiscoveredResourceCidrs` | ❌ Not implemented |
+| `GetIpamPoolAllocations` | ❌ Not implemented |
+| `GetIpamPoolCidrs` | ❌ Not implemented |
+| `GetIpamResourceCidrs` | ❌ Not implemented |
+| `GetLaunchTemplateData` | ❌ Not implemented |
+| `GetManagedPrefixListAssociations` | ❌ Not implemented |
+| `GetManagedPrefixListEntries` | ❌ Not implemented |
+| `GetNetworkInsightsAccessScopeAnalysisFindings` | ❌ Not implemented |
+| `GetNetworkInsightsAccessScopeContent` | ❌ Not implemented |
+| `GetPasswordData` | ✅ Implemented |
+| `GetReservedInstancesExchangeQuote` | ❌ Not implemented |
+| `GetSecurityGroupsForVpc` | ❌ Not implemented |
+| `GetSerialConsoleAccessStatus` | ✅ Implemented |
+| `GetSnapshotBlockPublicAccessState` | ❌ Not implemented |
+| `GetSpotPlacementScores` | ❌ Not implemented |
+| `GetSubnetCidrReservations` | ❌ Not implemented |
+| `GetTransitGatewayAttachmentPropagations` | ❌ Not implemented |
+| `GetTransitGatewayMulticastDomainAssociations` | ❌ Not implemented |
+| `GetTransitGatewayPolicyTableAssociations` | ❌ Not implemented |
+| `GetTransitGatewayPolicyTableEntries` | ❌ Not implemented |
+| `GetTransitGatewayPrefixListReferences` | ❌ Not implemented |
+| `GetTransitGatewayRouteTableAssociations` | ❌ Not implemented |
+| `GetTransitGatewayRouteTablePropagations` | ❌ Not implemented |
+| `GetVerifiedAccessEndpointPolicy` | ❌ Not implemented |
+| `GetVerifiedAccessGroupPolicy` | ❌ Not implemented |
+| `GetVpnConnectionDeviceSampleConfiguration` | ❌ Not implemented |
+| `GetVpnConnectionDeviceTypes` | ❌ Not implemented |
+| `GetVpnTunnelReplacementStatus` | ❌ Not implemented |
+| `ImportClientVpnClientCertificateRevocationList` | ❌ Not implemented |
+| `ImportImage` | ❌ Not implemented |
+| `ImportInstance` | ❌ Not implemented |
+| `ImportKeyPair` | ✅ Implemented |
+| `ImportSnapshot` | ❌ Not implemented |
+| `ImportVolume` | ❌ Not implemented |
+| `ListImagesInRecycleBin` | ❌ Not implemented |
+| `ListSnapshotsInRecycleBin` | ❌ Not implemented |
+| `LockSnapshot` | ❌ Not implemented |
+| `ModifyAddressAttribute` | ❌ Not implemented |
+| `ModifyAvailabilityZoneGroup` | ❌ Not implemented |
+| `ModifyCapacityReservation` | ❌ Not implemented |
+| `ModifyCapacityReservationFleet` | ❌ Not implemented |
+| `ModifyClientVpnEndpoint` | ❌ Not implemented |
+| `ModifyDefaultCreditSpecification` | ❌ Not implemented |
+| `ModifyEbsDefaultKmsKeyId` | ❌ Not implemented |
+| `ModifyFleet` | ❌ Not implemented |
+| `ModifyFpgaImageAttribute` | ❌ Not implemented |
+| `ModifyHosts` | ❌ Not implemented |
+| `ModifyIdFormat` | ❌ Not implemented |
+| `ModifyIdentityIdFormat` | ❌ Not implemented |
+| `ModifyImageAttribute` | ✅ Implemented |
+| `ModifyInstanceAttribute` | ✅ Implemented |
+| `ModifyInstanceCapacityReservationAttributes` | ❌ Not implemented |
+| `ModifyInstanceCreditSpecification` | ❌ Not implemented |
+| `ModifyInstanceEventStartTime` | ❌ Not implemented |
+| `ModifyInstanceEventWindow` | ❌ Not implemented |
+| `ModifyInstanceMaintenanceOptions` | ❌ Not implemented |
+| `ModifyInstanceMetadataDefaults` | ❌ Not implemented |
+| `ModifyInstanceMetadataOptions` | ✅ Implemented |
+| `ModifyInstancePlacement` | ❌ Not implemented |
+| `ModifyIpam` | ❌ Not implemented |
+| `ModifyIpamPool` | ❌ Not implemented |
+| `ModifyIpamResourceCidr` | ❌ Not implemented |
+| `ModifyIpamResourceDiscovery` | ❌ Not implemented |
+| `ModifyIpamScope` | ❌ Not implemented |
+| `ModifyLaunchTemplate` | ✅ Implemented |
+| `ModifyLocalGatewayRoute` | ❌ Not implemented |
+| `ModifyManagedPrefixList` | ❌ Not implemented |
+| `ModifyNetworkInterfaceAttribute` | ✅ Implemented |
+| `ModifyPrivateDnsNameOptions` | ❌ Not implemented |
+| `ModifyReservedInstances` | ❌ Not implemented |
+| `ModifySecurityGroupRules` | ❌ Not implemented |
+| `ModifySnapshotAttribute` | ❌ Not implemented |
+| `ModifySnapshotTier` | ❌ Not implemented |
+| `ModifySpotFleetRequest` | ❌ Not implemented |
+| `ModifySubnetAttribute` | ✅ Implemented |
+| `ModifyTrafficMirrorFilterNetworkServices` | ❌ Not implemented |
+| `ModifyTrafficMirrorFilterRule` | ❌ Not implemented |
+| `ModifyTrafficMirrorSession` | ❌ Not implemented |
+| `ModifyTransitGateway` | ❌ Not implemented |
+| `ModifyTransitGatewayPrefixListReference` | ❌ Not implemented |
+| `ModifyTransitGatewayVpcAttachment` | ❌ Not implemented |
+| `ModifyVerifiedAccessEndpoint` | ❌ Not implemented |
+| `ModifyVerifiedAccessEndpointPolicy` | ❌ Not implemented |
+| `ModifyVerifiedAccessGroup` | ❌ Not implemented |
+| `ModifyVerifiedAccessGroupPolicy` | ❌ Not implemented |
+| `ModifyVerifiedAccessInstance` | ❌ Not implemented |
+| `ModifyVerifiedAccessInstanceLoggingConfiguration` | ❌ Not implemented |
+| `ModifyVerifiedAccessTrustProvider` | ❌ Not implemented |
+| `ModifyVolume` | ✅ Implemented |
+| `ModifyVolumeAttribute` | ❌ Not implemented |
+| `ModifyVpcAttribute` | ✅ Implemented |
+| `ModifyVpcEndpoint` | ❌ Not implemented |
+| `ModifyVpcEndpointConnectionNotification` | ❌ Not implemented |
+| `ModifyVpcEndpointServiceConfiguration` | ❌ Not implemented |
+| `ModifyVpcEndpointServicePayerResponsibility` | ❌ Not implemented |
+| `ModifyVpcEndpointServicePermissions` | ❌ Not implemented |
+| `ModifyVpcPeeringConnectionOptions` | ❌ Not implemented |
+| `ModifyVpcTenancy` | ❌ Not implemented |
+| `ModifyVpnConnection` | ❌ Not implemented |
+| `ModifyVpnConnectionOptions` | ❌ Not implemented |
+| `ModifyVpnTunnelCertificate` | ❌ Not implemented |
+| `ModifyVpnTunnelOptions` | ❌ Not implemented |
+| `MonitorInstances` | ✅ Implemented |
+| `MoveAddressToVpc` | ❌ Not implemented |
+| `MoveByoipCidrToIpam` | ❌ Not implemented |
+| `ProvisionByoipCidr` | ❌ Not implemented |
+| `ProvisionIpamByoasn` | ❌ Not implemented |
+| `ProvisionIpamPoolCidr` | ❌ Not implemented |
+| `ProvisionPublicIpv4PoolCidr` | ❌ Not implemented |
+| `PurchaseCapacityBlock` | ❌ Not implemented |
+| `PurchaseHostReservation` | ❌ Not implemented |
+| `PurchaseReservedInstancesOffering` | ❌ Not implemented |
+| `PurchaseScheduledInstances` | ❌ Not implemented |
+| `RebootInstances` | ✅ Implemented |
+| `RegisterImage` | ✅ Implemented |
+| `RegisterInstanceEventNotificationAttributes` | ❌ Not implemented |
+| `RegisterTransitGatewayMulticastGroupMembers` | ❌ Not implemented |
+| `RegisterTransitGatewayMulticastGroupSources` | ❌ Not implemented |
+| `RejectTransitGatewayMulticastDomainAssociations` | ❌ Not implemented |
+| `RejectTransitGatewayPeeringAttachment` | ❌ Not implemented |
+| `RejectTransitGatewayVpcAttachment` | ❌ Not implemented |
+| `RejectVpcEndpointConnections` | ❌ Not implemented |
+| `RejectVpcPeeringConnection` | ❌ Not implemented |
+| `ReleaseAddress` | ✅ Implemented |
+| `ReleaseHosts` | ❌ Not implemented |
+| `ReleaseIpamPoolAllocation` | ❌ Not implemented |
+| `ReplaceIamInstanceProfileAssociation` | ✅ Implemented |
+| `ReplaceNetworkAclAssociation` | ❌ Not implemented |
+| `ReplaceNetworkAclEntry` | ❌ Not implemented |
+| `ReplaceRoute` | ✅ Implemented |
+| `ReplaceRouteTableAssociation` | ✅ Implemented |
+| `ReplaceTransitGatewayRoute` | ❌ Not implemented |
+| `ReplaceVpnTunnel` | ❌ Not implemented |
+| `ReportInstanceStatus` | ❌ Not implemented |
+| `RequestSpotFleet` | ❌ Not implemented |
+| `RequestSpotInstances` | ✅ Implemented |
+| `ResetAddressAttribute` | ❌ Not implemented |
+| `ResetEbsDefaultKmsKeyId` | ❌ Not implemented |
+| `ResetFpgaImageAttribute` | ❌ Not implemented |
+| `ResetImageAttribute` | ✅ Implemented |
+| `ResetInstanceAttribute` | ❌ Not implemented |
+| `ResetNetworkInterfaceAttribute` | ❌ Not implemented |
+| `ResetSnapshotAttribute` | ❌ Not implemented |
+| `RestoreAddressToClassic` | ❌ Not implemented |
+| `RestoreImageFromRecycleBin` | ❌ Not implemented |
+| `RestoreManagedPrefixListVersion` | ❌ Not implemented |
+| `RestoreSnapshotFromRecycleBin` | ❌ Not implemented |
+| `RestoreSnapshotTier` | ❌ Not implemented |
+| `RevokeClientVpnIngress` | ❌ Not implemented |
+| `RevokeSecurityGroupEgress` | ✅ Implemented |
+| `RevokeSecurityGroupIngress` | ✅ Implemented |
+| `RunInstances` | ✅ Implemented |
+| `RunScheduledInstances` | ❌ Not implemented |
+| `SearchLocalGatewayRoutes` | ❌ Not implemented |
+| `SearchTransitGatewayMulticastGroups` | ❌ Not implemented |
+| `SearchTransitGatewayRoutes` | ❌ Not implemented |
+| `SendDiagnosticInterrupt` | ❌ Not implemented |
+| `StartInstances` | ✅ Implemented |
+| `StartNetworkInsightsAccessScopeAnalysis` | ❌ Not implemented |
+| `StartNetworkInsightsAnalysis` | ❌ Not implemented |
+| `StartVpcEndpointServicePrivateDnsVerification` | ❌ Not implemented |
+| `StopInstances` | ✅ Implemented |
+| `TerminateClientVpnConnections` | ❌ Not implemented |
+| `TerminateInstances` | ✅ Implemented |
+| `UnassignIpv6Addresses` | ❌ Not implemented |
+| `UnassignPrivateIpAddresses` | ❌ Not implemented |
+| `UnassignPrivateNatGatewayAddress` | ❌ Not implemented |
+| `UnlockSnapshot` | ❌ Not implemented |
+| `UnmonitorInstances` | ✅ Implemented |
+| `UpdateSecurityGroupRuleDescriptionsEgress` | ❌ Not implemented |
+| `UpdateSecurityGroupRuleDescriptionsIngress` | ❌ Not implemented |
+| `WithdrawByoipCidr` | ❌ Not implemented |
diff --git a/docs/compatibility/ec2-api-coverage/intro.md b/docs/compatibility/ec2-api-coverage/intro.md
new file mode 100644
index 000000000..77eb4e5b5
--- /dev/null
+++ b/docs/compatibility/ec2-api-coverage/intro.md
@@ -0,0 +1,5 @@
+### Spot instances are a mock
+
+Spot Instance Requests are a mock over the on-demand `RunInstances` path. A request synchronously launches real VMs on the operator's own compute and is then reported `active` and `fulfilled`. There is no spot market: no bidding, no price rejection, no interruption and no reclamation, and instances are never taken back.
+
+`DescribeSpotPriceHistory` is the one operation on that surface deliberately left unimplemented. On owned hardware there is no spot-to-on-demand price differential, so any figure it returned would be invented, and an invented price is worse than an absent one.
diff --git a/docs/compatibility/ecr-api-coverage/README.md b/docs/compatibility/ecr-api-coverage/README.md
new file mode 100644
index 000000000..49a4356e9
--- /dev/null
+++ b/docs/compatibility/ecr-api-coverage/README.md
@@ -0,0 +1,92 @@
+---
+title: "ECR API Coverage"
+seoTitle: "Elastic Container Registry API Coverage — Spinifex Docs"
+description: "Every operation in the Amazon ECR API model and whether Spinifex implements it, alongside the OCI distribution endpoint that carries the image layers."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - ecr
+ - containers
+ - registry
+---
+
+# ECR API Coverage
+
+## Overview
+
+Spinifex implements **19 of the 47** operations in the ECR `2015-09-21` API model, as pinned in `aws-sdk-go v1.55.8` — **40.4%**.
+
+### Two endpoints, one registry
+
+Repository metadata is served over the AWS API on the gateway endpoint. Image data moves over the OCI Distribution `/v2/` endpoint on that same host, authenticated by the bearer token `GetAuthorizationToken` mints for `docker login`.
+
+The split explains the largest group of unimplemented operations below. The layer-transfer operations — `BatchCheckLayerAvailability`, `InitiateLayerUpload`, `UploadLayerPart`, `CompleteLayerUpload` and `GetDownloadUrlForLayer` — are registered stubs because the `/v2/` endpoint carries that traffic instead. A client using `docker` or any OCI-compatible tool never calls them.
+
+Vulnerability scanning is not offered, so the image-scanning operations refuse deliberately rather than pretending to have found nothing. Registry replication is likewise absent: a deployment is a single registry, with no cross-region peer to replicate to.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `BatchCheckLayerAvailability` | 🟡 Stub |
+| `BatchDeleteImage` | ✅ Implemented |
+| `BatchGetImage` | ✅ Implemented |
+| `BatchGetRepositoryScanningConfiguration` | 🚫 Not supported |
+| `CompleteLayerUpload` | 🟡 Stub |
+| `CreatePullThroughCacheRule` | ❌ Not implemented |
+| `CreateRepository` | ✅ Implemented |
+| `CreateRepositoryCreationTemplate` | ❌ Not implemented |
+| `DeleteLifecyclePolicy` | ✅ Implemented |
+| `DeletePullThroughCacheRule` | ❌ Not implemented |
+| `DeleteRegistryPolicy` | ❌ Not implemented |
+| `DeleteRepository` | ✅ Implemented |
+| `DeleteRepositoryCreationTemplate` | ❌ Not implemented |
+| `DeleteRepositoryPolicy` | ✅ Implemented |
+| `DescribeImageReplicationStatus` | ❌ Not implemented |
+| `DescribeImageScanFindings` | 🚫 Not supported |
+| `DescribeImages` | ✅ Implemented |
+| `DescribePullThroughCacheRules` | ❌ Not implemented |
+| `DescribeRegistry` | 🟡 Stub |
+| `DescribeRepositories` | ✅ Implemented |
+| `DescribeRepositoryCreationTemplates` | ❌ Not implemented |
+| `GetAuthorizationToken` | ✅ Implemented |
+| `GetDownloadUrlForLayer` | 🟡 Stub |
+| `GetLifecyclePolicy` | ✅ Implemented |
+| `GetLifecyclePolicyPreview` | ✅ Implemented |
+| `GetRegistryPolicy` | 🟡 Stub |
+| `GetRegistryScanningConfiguration` | 🚫 Not supported |
+| `GetRepositoryPolicy` | ✅ Implemented |
+| `InitiateLayerUpload` | 🟡 Stub |
+| `ListImages` | ✅ Implemented |
+| `ListTagsForResource` | ✅ Implemented |
+| `PutImage` | ✅ Implemented |
+| `PutImageScanningConfiguration` | 🚫 Not supported |
+| `PutImageTagMutability` | ✅ Implemented |
+| `PutLifecyclePolicy` | ✅ Implemented |
+| `PutRegistryPolicy` | 🟡 Stub |
+| `PutRegistryScanningConfiguration` | 🚫 Not supported |
+| `PutReplicationConfiguration` | 🟡 Stub |
+| `SetRepositoryPolicy` | ✅ Implemented |
+| `StartImageScan` | 🚫 Not supported |
+| `StartLifecyclePolicyPreview` | ✅ Implemented |
+| `TagResource` | 🟡 Stub |
+| `UntagResource` | 🟡 Stub |
+| `UpdatePullThroughCacheRule` | ❌ Not implemented |
+| `UpdateRepositoryCreationTemplate` | ❌ Not implemented |
+| `UploadLayerPart` | 🟡 Stub |
+| `ValidatePullThroughCacheRule` | ❌ Not implemented |
+| `GetImageScanningConfiguration` | 🔒 Outside the pinned model |
+| `ListRepositories` | 🔒 Outside the pinned model |
+| `ReplicateImage` | 🔒 Outside the pinned model |
diff --git a/docs/compatibility/ecr-api-coverage/intro.md b/docs/compatibility/ecr-api-coverage/intro.md
new file mode 100644
index 000000000..5bef24aa5
--- /dev/null
+++ b/docs/compatibility/ecr-api-coverage/intro.md
@@ -0,0 +1,7 @@
+### Two endpoints, one registry
+
+Repository metadata is served over the AWS API on the gateway endpoint. Image data moves over the OCI Distribution `/v2/` endpoint on that same host, authenticated by the bearer token `GetAuthorizationToken` mints for `docker login`.
+
+The split explains the largest group of unimplemented operations below. The layer-transfer operations — `BatchCheckLayerAvailability`, `InitiateLayerUpload`, `UploadLayerPart`, `CompleteLayerUpload` and `GetDownloadUrlForLayer` — are registered stubs because the `/v2/` endpoint carries that traffic instead. A client using `docker` or any OCI-compatible tool never calls them.
+
+Vulnerability scanning is not offered, so the image-scanning operations refuse deliberately rather than pretending to have found nothing. Registry replication is likewise absent: a deployment is a single registry, with no cross-region peer to replicate to.
diff --git a/docs/compatibility/ecs-api-coverage/README.md b/docs/compatibility/ecs-api-coverage/README.md
new file mode 100644
index 000000000..178d298eb
--- /dev/null
+++ b/docs/compatibility/ecs-api-coverage/README.md
@@ -0,0 +1,97 @@
+---
+title: "ECS API Coverage"
+seoTitle: "Elastic Container Service API Coverage — Spinifex Docs"
+description: "Every operation in the Amazon ECS API model and whether Spinifex implements it, covering clusters, services, tasks and container instances on each build."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - ecs
+ - containers
+ - orchestration
+---
+
+# ECS API Coverage
+
+## Overview
+
+Spinifex implements **31 of the 56** operations in the ECS `2014-11-13` API model, as pinned in `aws-sdk-go v1.55.8` — **55.4%**.
+
+### No Fargate
+
+Clusters, services and tasks run on EC2 container instances. There is no Fargate launch type, and no operation below provides one.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `CreateCapacityProvider` | ✅ Implemented |
+| `CreateCluster` | ✅ Implemented |
+| `CreateService` | ✅ Implemented |
+| `CreateTaskSet` | ❌ Not implemented |
+| `DeleteAccountSetting` | ❌ Not implemented |
+| `DeleteAttributes` | ❌ Not implemented |
+| `DeleteCapacityProvider` | ✅ Implemented |
+| `DeleteCluster` | ✅ Implemented |
+| `DeleteService` | ✅ Implemented |
+| `DeleteTaskDefinitions` | ❌ Not implemented |
+| `DeleteTaskSet` | ❌ Not implemented |
+| `DeregisterContainerInstance` | ✅ Implemented |
+| `DeregisterTaskDefinition` | ✅ Implemented |
+| `DescribeCapacityProviders` | ✅ Implemented |
+| `DescribeClusters` | ✅ Implemented |
+| `DescribeContainerInstances` | ✅ Implemented |
+| `DescribeServices` | ✅ Implemented |
+| `DescribeTaskDefinition` | ✅ Implemented |
+| `DescribeTaskSets` | ❌ Not implemented |
+| `DescribeTasks` | ✅ Implemented |
+| `DiscoverPollEndpoint` | ❌ Not implemented |
+| `ExecuteCommand` | ❌ Not implemented |
+| `GetTaskProtection` | ❌ Not implemented |
+| `ListAccountSettings` | 🟡 Stub |
+| `ListAttributes` | ❌ Not implemented |
+| `ListClusters` | ✅ Implemented |
+| `ListContainerInstances` | ✅ Implemented |
+| `ListServices` | ✅ Implemented |
+| `ListServicesByNamespace` | 🟡 Stub |
+| `ListTagsForResource` | ✅ Implemented |
+| `ListTaskDefinitionFamilies` | 🟡 Stub |
+| `ListTaskDefinitions` | ✅ Implemented |
+| `ListTasks` | ✅ Implemented |
+| `PutAccountSetting` | 🟡 Stub |
+| `PutAccountSettingDefault` | ❌ Not implemented |
+| `PutAttributes` | ❌ Not implemented |
+| `PutClusterCapacityProviders` | ✅ Implemented |
+| `RegisterContainerInstance` | ✅ Implemented |
+| `RegisterTaskDefinition` | ✅ Implemented |
+| `RunTask` | ✅ Implemented |
+| `StartTask` | ✅ Implemented |
+| `StopTask` | ✅ Implemented |
+| `SubmitAttachmentStateChanges` | ❌ Not implemented |
+| `SubmitContainerStateChange` | ❌ Not implemented |
+| `SubmitTaskStateChange` | ✅ Implemented |
+| `TagResource` | ✅ Implemented |
+| `UntagResource` | ✅ Implemented |
+| `UpdateCapacityProvider` | ❌ Not implemented |
+| `UpdateCluster` | 🟡 Stub |
+| `UpdateClusterSettings` | ❌ Not implemented |
+| `UpdateContainerAgent` | ❌ Not implemented |
+| `UpdateContainerInstancesState` | ✅ Implemented |
+| `UpdateService` | ✅ Implemented |
+| `UpdateServicePrimaryTaskSet` | ❌ Not implemented |
+| `UpdateTaskProtection` | ❌ Not implemented |
+| `UpdateTaskSet` | ❌ Not implemented |
+| `PollAssignments` | 🔒 Outside the pinned model |
+| `ProvisionCapacity` | 🔒 Outside the pinned model |
+| `ReportTaskGPU` | 🔒 Outside the pinned model |
diff --git a/docs/compatibility/ecs-api-coverage/intro.md b/docs/compatibility/ecs-api-coverage/intro.md
new file mode 100644
index 000000000..77b5501b1
--- /dev/null
+++ b/docs/compatibility/ecs-api-coverage/intro.md
@@ -0,0 +1,3 @@
+### No Fargate
+
+Clusters, services and tasks run on EC2 container instances. There is no Fargate launch type, and no operation below provides one.
diff --git a/docs/compatibility/eks-api-coverage/README.md b/docs/compatibility/eks-api-coverage/README.md
new file mode 100644
index 000000000..f47a6f36c
--- /dev/null
+++ b/docs/compatibility/eks-api-coverage/README.md
@@ -0,0 +1,109 @@
+---
+title: "EKS API Coverage"
+seoTitle: "Elastic Kubernetes Service API Coverage — Spinifex Docs"
+description: "Every operation in the Amazon EKS API model and whether Spinifex implements it, covering clusters, nodegroups, add-ons and access entries on each build."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - eks
+ - kubernetes
+ - containers
+---
+
+# EKS API Coverage
+
+## Overview
+
+Spinifex implements **34 of the 56** operations in the EKS `2017-11-01` API model, as pinned in `aws-sdk-go v1.55.8` — **60.7%**.
+
+### Routing
+
+EKS is REST-JSON, dispatched by HTTP method and path rather than by an action parameter, so the gateway's routing table is the authoritative list of what it serves. Clusters run K3s on control-plane VMs; nodegroups are EC2 instances joined to them.
+
+### Internal routes
+
+Four routes on this surface are internal, not AWS actions, and appear in the table below as registered outside the pinned model:
+
+- `PublishInternal` — the control-plane VM broker, relaying bootstrap and state posts onto the message bus.
+- `WebhookTokenReview` — the token webhook posting bearer tokens for host-side resolution.
+- `ListInternalAddons` — the on-VM add-on sync agent fetching its staged manifests.
+- `GetRecoveryDirective` — the on-VM recovery agent reading its per-member directive at boot.
+
+None is callable with an ordinary tenant credential. Each names the target account in the path rather than taking it from the credential, so each requires a control-plane instance-role session bound to the named cluster; a broad `eks:*` grant does not reach them.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `AssociateAccessPolicy` | ✅ Implemented |
+| `AssociateEncryptionConfig` | ❌ Not implemented |
+| `AssociateIdentityProviderConfig` | ✅ Implemented |
+| `CreateAccessEntry` | ✅ Implemented |
+| `CreateAddon` | ✅ Implemented |
+| `CreateCluster` | ✅ Implemented |
+| `CreateEksAnywhereSubscription` | ❌ Not implemented |
+| `CreateFargateProfile` | ❌ Not implemented |
+| `CreateNodegroup` | ✅ Implemented |
+| `CreatePodIdentityAssociation` | ❌ Not implemented |
+| `DeleteAccessEntry` | ✅ Implemented |
+| `DeleteAddon` | ✅ Implemented |
+| `DeleteCluster` | ✅ Implemented |
+| `DeleteEksAnywhereSubscription` | ❌ Not implemented |
+| `DeleteFargateProfile` | ❌ Not implemented |
+| `DeleteNodegroup` | ✅ Implemented |
+| `DeletePodIdentityAssociation` | ❌ Not implemented |
+| `DeregisterCluster` | ❌ Not implemented |
+| `DescribeAccessEntry` | ✅ Implemented |
+| `DescribeAddon` | ✅ Implemented |
+| `DescribeAddonConfiguration` | ❌ Not implemented |
+| `DescribeAddonVersions` | ✅ Implemented |
+| `DescribeCluster` | ✅ Implemented |
+| `DescribeEksAnywhereSubscription` | ❌ Not implemented |
+| `DescribeFargateProfile` | ❌ Not implemented |
+| `DescribeIdentityProviderConfig` | ✅ Implemented |
+| `DescribeInsight` | ❌ Not implemented |
+| `DescribeNodegroup` | ✅ Implemented |
+| `DescribePodIdentityAssociation` | ❌ Not implemented |
+| `DescribeUpdate` | ❌ Not implemented |
+| `DisassociateAccessPolicy` | ✅ Implemented |
+| `DisassociateIdentityProviderConfig` | ✅ Implemented |
+| `ListAccessEntries` | ✅ Implemented |
+| `ListAccessPolicies` | ✅ Implemented |
+| `ListAddons` | ✅ Implemented |
+| `ListAssociatedAccessPolicies` | ✅ Implemented |
+| `ListClusters` | ✅ Implemented |
+| `ListEksAnywhereSubscriptions` | ❌ Not implemented |
+| `ListFargateProfiles` | ❌ Not implemented |
+| `ListIdentityProviderConfigs` | ✅ Implemented |
+| `ListInsights` | ❌ Not implemented |
+| `ListNodegroups` | ✅ Implemented |
+| `ListPodIdentityAssociations` | ❌ Not implemented |
+| `ListTagsForResource` | ✅ Implemented |
+| `ListUpdates` | ❌ Not implemented |
+| `RegisterCluster` | ❌ Not implemented |
+| `TagResource` | ✅ Implemented |
+| `UntagResource` | ✅ Implemented |
+| `UpdateAccessEntry` | ✅ Implemented |
+| `UpdateAddon` | ✅ Implemented |
+| `UpdateClusterConfig` | ✅ Implemented |
+| `UpdateClusterVersion` | ✅ Implemented |
+| `UpdateEksAnywhereSubscription` | ❌ Not implemented |
+| `UpdateNodegroupConfig` | ✅ Implemented |
+| `UpdateNodegroupVersion` | ✅ Implemented |
+| `UpdatePodIdentityAssociation` | ❌ Not implemented |
+| `GetRecoveryDirective` | 🔒 Outside the pinned model |
+| `ListInternalAddons` | 🔒 Outside the pinned model |
+| `PublishInternal` | 🔒 Outside the pinned model |
+| `WebhookTokenReview` | 🔒 Outside the pinned model |
diff --git a/docs/compatibility/eks-api-coverage/intro.md b/docs/compatibility/eks-api-coverage/intro.md
new file mode 100644
index 000000000..0d0475945
--- /dev/null
+++ b/docs/compatibility/eks-api-coverage/intro.md
@@ -0,0 +1,14 @@
+### Routing
+
+EKS is REST-JSON, dispatched by HTTP method and path rather than by an action parameter, so the gateway's routing table is the authoritative list of what it serves. Clusters run K3s on control-plane VMs; nodegroups are EC2 instances joined to them.
+
+### Internal routes
+
+Four routes on this surface are internal, not AWS actions, and appear in the table below as registered outside the pinned model:
+
+- `PublishInternal` — the control-plane VM broker, relaying bootstrap and state posts onto the message bus.
+- `WebhookTokenReview` — the token webhook posting bearer tokens for host-side resolution.
+- `ListInternalAddons` — the on-VM add-on sync agent fetching its staged manifests.
+- `GetRecoveryDirective` — the on-VM recovery agent reading its per-member directive at boot.
+
+None is callable with an ordinary tenant credential. Each names the target account in the path rather than taking it from the credential, so each requires a control-plane instance-role session bound to the named cluster; a broad `eks:*` grant does not reach them.
diff --git a/docs/compatibility/elbv2-api-coverage/README.md b/docs/compatibility/elbv2-api-coverage/README.md
new file mode 100644
index 000000000..6da72a1f4
--- /dev/null
+++ b/docs/compatibility/elbv2-api-coverage/README.md
@@ -0,0 +1,88 @@
+---
+title: "ELBv2 API Coverage"
+seoTitle: "Elastic Load Balancing v2 API Coverage — Spinifex Docs"
+description: "Every operation in the Elastic Load Balancing v2 API model and whether Spinifex implements it, for both the Application and Network Load Balancers it serves."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - elbv2
+ - load balancing
+ - networking
+---
+
+# ELBv2 API Coverage
+
+## Overview
+
+Spinifex implements **33 of the 46** operations in the ELBv2 `2015-12-01` API model, as pinned in `aws-sdk-go v1.55.8` — **71.7%**.
+
+### Two data planes
+
+The data plane is a system-managed load balancer VM, launched automatically during `CreateLoadBalancer`. Application Load Balancers run HAProxy for the L7 surface — rules, fixed responses and redirects over HTTP and HTTPS. Network Load Balancers run nginx `stream` for the L4 surface — TCP, UDP, TLS and TCP_UDP — because HAProxy cannot load-balance UDP. The agent selects the engine from the configuration the control plane delivers, so the choice follows the load balancer type and is not separately configurable.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `AddListenerCertificates` | ✅ Implemented |
+| `AddTags` | ✅ Implemented |
+| `AddTrustStoreRevocations` | ❌ Not implemented |
+| `CreateListener` | ✅ Implemented |
+| `CreateLoadBalancer` | ✅ Implemented |
+| `CreateRule` | ✅ Implemented |
+| `CreateTargetGroup` | ✅ Implemented |
+| `CreateTrustStore` | ❌ Not implemented |
+| `DeleteListener` | ✅ Implemented |
+| `DeleteLoadBalancer` | ✅ Implemented |
+| `DeleteRule` | ✅ Implemented |
+| `DeleteSharedTrustStoreAssociation` | ❌ Not implemented |
+| `DeleteTargetGroup` | ✅ Implemented |
+| `DeleteTrustStore` | ❌ Not implemented |
+| `DeregisterTargets` | ✅ Implemented |
+| `DescribeAccountLimits` | ❌ Not implemented |
+| `DescribeListenerCertificates` | ✅ Implemented |
+| `DescribeListeners` | ✅ Implemented |
+| `DescribeLoadBalancerAttributes` | ✅ Implemented |
+| `DescribeLoadBalancers` | ✅ Implemented |
+| `DescribeRules` | ✅ Implemented |
+| `DescribeSSLPolicies` | ✅ Implemented |
+| `DescribeTags` | ✅ Implemented |
+| `DescribeTargetGroupAttributes` | ✅ Implemented |
+| `DescribeTargetGroups` | ✅ Implemented |
+| `DescribeTargetHealth` | ✅ Implemented |
+| `DescribeTrustStoreAssociations` | ❌ Not implemented |
+| `DescribeTrustStoreRevocations` | ❌ Not implemented |
+| `DescribeTrustStores` | ❌ Not implemented |
+| `GetResourcePolicy` | ❌ Not implemented |
+| `GetTrustStoreCaCertificatesBundle` | ❌ Not implemented |
+| `GetTrustStoreRevocationContent` | ❌ Not implemented |
+| `ModifyListener` | ✅ Implemented |
+| `ModifyLoadBalancerAttributes` | ✅ Implemented |
+| `ModifyRule` | ✅ Implemented |
+| `ModifyTargetGroup` | ✅ Implemented |
+| `ModifyTargetGroupAttributes` | ✅ Implemented |
+| `ModifyTrustStore` | ❌ Not implemented |
+| `RegisterTargets` | ✅ Implemented |
+| `RemoveListenerCertificates` | ✅ Implemented |
+| `RemoveTags` | ✅ Implemented |
+| `RemoveTrustStoreRevocations` | ❌ Not implemented |
+| `SetIpAddressType` | ✅ Implemented |
+| `SetRulePriorities` | ✅ Implemented |
+| `SetSecurityGroups` | ✅ Implemented |
+| `SetSubnets` | ✅ Implemented |
+| `DescribeListenerAttributes` | 🔒 Outside the pinned model |
+| `GetLBConfig` | 🔒 Outside the pinned model |
+| `LBAgentHeartbeat` | 🔒 Outside the pinned model |
+| `ModifyListenerAttributes` | 🔒 Outside the pinned model |
diff --git a/docs/compatibility/elbv2-api-coverage/intro.md b/docs/compatibility/elbv2-api-coverage/intro.md
new file mode 100644
index 000000000..e892486f2
--- /dev/null
+++ b/docs/compatibility/elbv2-api-coverage/intro.md
@@ -0,0 +1,3 @@
+### Two data planes
+
+The data plane is a system-managed load balancer VM, launched automatically during `CreateLoadBalancer`. Application Load Balancers run HAProxy for the L7 surface — rules, fixed responses and redirects over HTTP and HTTPS. Network Load Balancers run nginx `stream` for the L4 surface — TCP, UDP, TLS and TCP_UDP — because HAProxy cannot load-balance UDP. The agent selects the engine from the configuration the control plane delivers, so the choice follows the load balancer type and is not separately configurable.
diff --git a/docs/compatibility/iam-api-coverage/README.md b/docs/compatibility/iam-api-coverage/README.md
new file mode 100644
index 000000000..7d3af9890
--- /dev/null
+++ b/docs/compatibility/iam-api-coverage/README.md
@@ -0,0 +1,197 @@
+---
+title: "IAM API Coverage"
+seoTitle: "AWS IAM API Operation Coverage on Spinifex — Spinifex Docs"
+description: "Every operation in the AWS IAM API model and whether Spinifex implements it, covering users, roles, policies, groups and instance profiles on each build."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - iam
+ - identity
+ - policies
+---
+
+# IAM API Coverage
+
+## Overview
+
+Spinifex implements **75 of the 159** operations in the IAM `2010-05-08` API model, as pinned in `aws-sdk-go v1.55.8` — **47.2%**.
+
+### Scope
+
+All IAM operations are account-scoped. The root user of an account bypasses policy evaluation entirely, as it does on AWS.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `AddClientIDToOpenIDConnectProvider` | ❌ Not implemented |
+| `AddRoleToInstanceProfile` | ✅ Implemented |
+| `AddUserToGroup` | ✅ Implemented |
+| `AttachGroupPolicy` | ✅ Implemented |
+| `AttachRolePolicy` | ✅ Implemented |
+| `AttachUserPolicy` | ✅ Implemented |
+| `ChangePassword` | ❌ Not implemented |
+| `CreateAccessKey` | ✅ Implemented |
+| `CreateAccountAlias` | ❌ Not implemented |
+| `CreateGroup` | ✅ Implemented |
+| `CreateInstanceProfile` | ✅ Implemented |
+| `CreateLoginProfile` | ❌ Not implemented |
+| `CreateOpenIDConnectProvider` | ✅ Implemented |
+| `CreatePolicy` | ✅ Implemented |
+| `CreatePolicyVersion` | ❌ Not implemented |
+| `CreateRole` | ✅ Implemented |
+| `CreateSAMLProvider` | ❌ Not implemented |
+| `CreateServiceLinkedRole` | ❌ Not implemented |
+| `CreateServiceSpecificCredential` | ❌ Not implemented |
+| `CreateUser` | ✅ Implemented |
+| `CreateVirtualMFADevice` | ❌ Not implemented |
+| `DeactivateMFADevice` | ❌ Not implemented |
+| `DeleteAccessKey` | ✅ Implemented |
+| `DeleteAccountAlias` | ❌ Not implemented |
+| `DeleteAccountPasswordPolicy` | ❌ Not implemented |
+| `DeleteGroup` | ✅ Implemented |
+| `DeleteGroupPolicy` | ✅ Implemented |
+| `DeleteInstanceProfile` | ✅ Implemented |
+| `DeleteLoginProfile` | ❌ Not implemented |
+| `DeleteOpenIDConnectProvider` | ✅ Implemented |
+| `DeletePolicy` | ✅ Implemented |
+| `DeletePolicyVersion` | ❌ Not implemented |
+| `DeleteRole` | ✅ Implemented |
+| `DeleteRolePermissionsBoundary` | ❌ Not implemented |
+| `DeleteRolePolicy` | ✅ Implemented |
+| `DeleteSAMLProvider` | ❌ Not implemented |
+| `DeleteSSHPublicKey` | ❌ Not implemented |
+| `DeleteServerCertificate` | ❌ Not implemented |
+| `DeleteServiceLinkedRole` | ❌ Not implemented |
+| `DeleteServiceSpecificCredential` | ❌ Not implemented |
+| `DeleteSigningCertificate` | ❌ Not implemented |
+| `DeleteUser` | ✅ Implemented |
+| `DeleteUserPermissionsBoundary` | ❌ Not implemented |
+| `DeleteUserPolicy` | ✅ Implemented |
+| `DeleteVirtualMFADevice` | ❌ Not implemented |
+| `DetachGroupPolicy` | ✅ Implemented |
+| `DetachRolePolicy` | ✅ Implemented |
+| `DetachUserPolicy` | ✅ Implemented |
+| `EnableMFADevice` | ❌ Not implemented |
+| `GenerateCredentialReport` | ❌ Not implemented |
+| `GenerateOrganizationsAccessReport` | ❌ Not implemented |
+| `GenerateServiceLastAccessedDetails` | ❌ Not implemented |
+| `GetAccessKeyLastUsed` | ❌ Not implemented |
+| `GetAccountAuthorizationDetails` | ❌ Not implemented |
+| `GetAccountPasswordPolicy` | ❌ Not implemented |
+| `GetAccountSummary` | ✅ Implemented |
+| `GetContextKeysForCustomPolicy` | ❌ Not implemented |
+| `GetContextKeysForPrincipalPolicy` | ❌ Not implemented |
+| `GetCredentialReport` | ❌ Not implemented |
+| `GetGroup` | ✅ Implemented |
+| `GetGroupPolicy` | ✅ Implemented |
+| `GetInstanceProfile` | ✅ Implemented |
+| `GetLoginProfile` | ❌ Not implemented |
+| `GetMFADevice` | ❌ Not implemented |
+| `GetOpenIDConnectProvider` | ✅ Implemented |
+| `GetOrganizationsAccessReport` | ❌ Not implemented |
+| `GetPolicy` | ✅ Implemented |
+| `GetPolicyVersion` | ✅ Implemented |
+| `GetRole` | ✅ Implemented |
+| `GetRolePolicy` | ✅ Implemented |
+| `GetSAMLProvider` | ❌ Not implemented |
+| `GetSSHPublicKey` | ❌ Not implemented |
+| `GetServerCertificate` | ❌ Not implemented |
+| `GetServiceLastAccessedDetails` | ❌ Not implemented |
+| `GetServiceLastAccessedDetailsWithEntities` | ❌ Not implemented |
+| `GetServiceLinkedRoleDeletionStatus` | ❌ Not implemented |
+| `GetUser` | ✅ Implemented |
+| `GetUserPolicy` | ✅ Implemented |
+| `ListAccessKeys` | ✅ Implemented |
+| `ListAccountAliases` | ❌ Not implemented |
+| `ListAttachedGroupPolicies` | ✅ Implemented |
+| `ListAttachedRolePolicies` | ✅ Implemented |
+| `ListAttachedUserPolicies` | ✅ Implemented |
+| `ListEntitiesForPolicy` | ❌ Not implemented |
+| `ListGroupPolicies` | ✅ Implemented |
+| `ListGroups` | ✅ Implemented |
+| `ListGroupsForUser` | ✅ Implemented |
+| `ListInstanceProfileTags` | ✅ Implemented |
+| `ListInstanceProfiles` | ✅ Implemented |
+| `ListInstanceProfilesForRole` | ✅ Implemented |
+| `ListMFADeviceTags` | ❌ Not implemented |
+| `ListMFADevices` | ❌ Not implemented |
+| `ListOpenIDConnectProviderTags` | ✅ Implemented |
+| `ListOpenIDConnectProviders` | ✅ Implemented |
+| `ListPolicies` | ✅ Implemented |
+| `ListPoliciesGrantingServiceAccess` | ❌ Not implemented |
+| `ListPolicyTags` | ✅ Implemented |
+| `ListPolicyVersions` | ✅ Implemented |
+| `ListRolePolicies` | ✅ Implemented |
+| `ListRoleTags` | ✅ Implemented |
+| `ListRoles` | ✅ Implemented |
+| `ListSAMLProviderTags` | ❌ Not implemented |
+| `ListSAMLProviders` | ❌ Not implemented |
+| `ListSSHPublicKeys` | ❌ Not implemented |
+| `ListServerCertificateTags` | ❌ Not implemented |
+| `ListServerCertificates` | ❌ Not implemented |
+| `ListServiceSpecificCredentials` | ❌ Not implemented |
+| `ListSigningCertificates` | ❌ Not implemented |
+| `ListUserPolicies` | ✅ Implemented |
+| `ListUserTags` | ✅ Implemented |
+| `ListUsers` | ✅ Implemented |
+| `ListVirtualMFADevices` | ❌ Not implemented |
+| `PutGroupPolicy` | ✅ Implemented |
+| `PutRolePermissionsBoundary` | ❌ Not implemented |
+| `PutRolePolicy` | ✅ Implemented |
+| `PutUserPermissionsBoundary` | ❌ Not implemented |
+| `PutUserPolicy` | ✅ Implemented |
+| `RemoveClientIDFromOpenIDConnectProvider` | ❌ Not implemented |
+| `RemoveRoleFromInstanceProfile` | ✅ Implemented |
+| `RemoveUserFromGroup` | ✅ Implemented |
+| `ResetServiceSpecificCredential` | ❌ Not implemented |
+| `ResyncMFADevice` | ❌ Not implemented |
+| `SetDefaultPolicyVersion` | ❌ Not implemented |
+| `SetSecurityTokenServicePreferences` | ❌ Not implemented |
+| `SimulateCustomPolicy` | ❌ Not implemented |
+| `SimulatePrincipalPolicy` | ❌ Not implemented |
+| `TagInstanceProfile` | ✅ Implemented |
+| `TagMFADevice` | ❌ Not implemented |
+| `TagOpenIDConnectProvider` | ✅ Implemented |
+| `TagPolicy` | ✅ Implemented |
+| `TagRole` | ✅ Implemented |
+| `TagSAMLProvider` | ❌ Not implemented |
+| `TagServerCertificate` | ❌ Not implemented |
+| `TagUser` | ✅ Implemented |
+| `UntagInstanceProfile` | ✅ Implemented |
+| `UntagMFADevice` | ❌ Not implemented |
+| `UntagOpenIDConnectProvider` | ✅ Implemented |
+| `UntagPolicy` | ✅ Implemented |
+| `UntagRole` | ✅ Implemented |
+| `UntagSAMLProvider` | ❌ Not implemented |
+| `UntagServerCertificate` | ❌ Not implemented |
+| `UntagUser` | ✅ Implemented |
+| `UpdateAccessKey` | ✅ Implemented |
+| `UpdateAccountPasswordPolicy` | ❌ Not implemented |
+| `UpdateAssumeRolePolicy` | ✅ Implemented |
+| `UpdateGroup` | ❌ Not implemented |
+| `UpdateLoginProfile` | ❌ Not implemented |
+| `UpdateOpenIDConnectProviderThumbprint` | ❌ Not implemented |
+| `UpdateRole` | ✅ Implemented |
+| `UpdateRoleDescription` | ❌ Not implemented |
+| `UpdateSAMLProvider` | ❌ Not implemented |
+| `UpdateSSHPublicKey` | ❌ Not implemented |
+| `UpdateServerCertificate` | ❌ Not implemented |
+| `UpdateServiceSpecificCredential` | ❌ Not implemented |
+| `UpdateSigningCertificate` | ❌ Not implemented |
+| `UpdateUser` | ❌ Not implemented |
+| `UploadSSHPublicKey` | ❌ Not implemented |
+| `UploadServerCertificate` | ❌ Not implemented |
+| `UploadSigningCertificate` | ❌ Not implemented |
diff --git a/docs/compatibility/iam-api-coverage/intro.md b/docs/compatibility/iam-api-coverage/intro.md
new file mode 100644
index 000000000..c8fbd116e
--- /dev/null
+++ b/docs/compatibility/iam-api-coverage/intro.md
@@ -0,0 +1,3 @@
+### Scope
+
+All IAM operations are account-scoped. The root user of an account bypasses policy evaluation entirely, as it does on AWS.
diff --git a/docs/compatibility/pages.json b/docs/compatibility/pages.json
new file mode 100644
index 000000000..3f9e04941
--- /dev/null
+++ b/docs/compatibility/pages.json
@@ -0,0 +1,93 @@
+{
+ "category": "Coverage",
+ "index": {
+ "slug": "aws-api-coverage",
+ "name": "All services",
+ "title": "AWS API Coverage",
+ "seoTitle": "Which AWS API Operations Spinifex Implements — Spinifex Docs",
+ "description": "Operation-level coverage of every AWS API Spinifex serves, generated from its gateway dispatch tables and the pinned AWS SDK service models on each build.",
+ "tags": ["aws", "compatibility", "coverage", "api", "operations"]
+ },
+ "services": {
+ "acm": {
+ "slug": "acm-api-coverage",
+ "name": "ACM",
+ "title": "ACM API Coverage",
+ "seoTitle": "AWS Certificate Manager API Coverage — Spinifex Docs",
+ "description": "Every operation in the AWS Certificate Manager API model and whether Spinifex implements it, generated from the gateway dispatch tables on each build.",
+ "tags": ["aws", "compatibility", "coverage", "acm", "certificates", "tls"]
+ },
+ "ec2": {
+ "slug": "ec2-api-coverage",
+ "name": "EC2",
+ "title": "EC2 API Coverage",
+ "seoTitle": "Amazon EC2 API Coverage on Spinifex — Spinifex Docs",
+ "description": "Every operation in the Amazon EC2 API model and whether Spinifex implements it, covering instances, EBS volumes, VPC networking, tags and security groups.",
+ "tags": ["aws", "compatibility", "coverage", "ec2", "compute", "vpc"]
+ },
+ "ecr": {
+ "slug": "ecr-api-coverage",
+ "name": "ECR",
+ "title": "ECR API Coverage",
+ "seoTitle": "Elastic Container Registry API Coverage — Spinifex Docs",
+ "description": "Every operation in the Amazon ECR API model and whether Spinifex implements it, alongside the OCI distribution endpoint that carries the image layers.",
+ "tags": ["aws", "compatibility", "coverage", "ecr", "containers", "registry"]
+ },
+ "ecs": {
+ "slug": "ecs-api-coverage",
+ "name": "ECS",
+ "title": "ECS API Coverage",
+ "seoTitle": "Elastic Container Service API Coverage — Spinifex Docs",
+ "description": "Every operation in the Amazon ECS API model and whether Spinifex implements it, covering clusters, services, tasks and container instances on each build.",
+ "tags": ["aws", "compatibility", "coverage", "ecs", "containers", "orchestration"]
+ },
+ "eks": {
+ "slug": "eks-api-coverage",
+ "name": "EKS",
+ "title": "EKS API Coverage",
+ "seoTitle": "Elastic Kubernetes Service API Coverage — Spinifex Docs",
+ "description": "Every operation in the Amazon EKS API model and whether Spinifex implements it, covering clusters, nodegroups, add-ons and access entries on each build.",
+ "tags": ["aws", "compatibility", "coverage", "eks", "kubernetes", "containers"]
+ },
+ "elasticloadbalancingv2": {
+ "slug": "elbv2-api-coverage",
+ "name": "ELBv2",
+ "title": "ELBv2 API Coverage",
+ "seoTitle": "Elastic Load Balancing v2 API Coverage — Spinifex Docs",
+ "description": "Every operation in the Elastic Load Balancing v2 API model and whether Spinifex implements it, for both the Application and Network Load Balancers it serves.",
+ "tags": ["aws", "compatibility", "coverage", "elbv2", "load balancing", "networking"]
+ },
+ "iam": {
+ "slug": "iam-api-coverage",
+ "name": "IAM",
+ "title": "IAM API Coverage",
+ "seoTitle": "AWS IAM API Operation Coverage on Spinifex — Spinifex Docs",
+ "description": "Every operation in the AWS IAM API model and whether Spinifex implements it, covering users, roles, policies, groups and instance profiles on each build.",
+ "tags": ["aws", "compatibility", "coverage", "iam", "identity", "policies"]
+ },
+ "rds": {
+ "slug": "rds-api-coverage",
+ "name": "RDS",
+ "title": "RDS API Coverage",
+ "seoTitle": "Relational Database Service API Coverage — Spinifex Docs",
+ "description": "Every operation in the Amazon RDS API model and whether Spinifex implements it, for the managed PostgreSQL and MariaDB engines it offers on each build.",
+ "tags": ["aws", "compatibility", "coverage", "rds", "databases", "postgresql", "mariadb"]
+ },
+ "s3": {
+ "slug": "s3-api-coverage",
+ "name": "S3",
+ "title": "S3 API Coverage",
+ "seoTitle": "Amazon S3 API Compatibility on Spinifex — Spinifex Docs",
+ "description": "How Spinifex serves the Amazon S3 API through Predastore, and why its coverage is measured there rather than derived from a gateway dispatch table here.",
+ "tags": ["aws", "compatibility", "coverage", "s3", "storage", "predastore"]
+ },
+ "sts": {
+ "slug": "sts-api-coverage",
+ "name": "STS",
+ "title": "STS API Coverage",
+ "seoTitle": "AWS Security Token Service API Coverage — Spinifex Docs",
+ "description": "Every operation in the AWS STS API model and whether Spinifex implements it, covering role assumption, session tokens and web identity federation (IRSA).",
+ "tags": ["aws", "compatibility", "coverage", "sts", "identity", "credentials"]
+ }
+ }
+}
diff --git a/docs/compatibility/rds-api-coverage/README.md b/docs/compatibility/rds-api-coverage/README.md
new file mode 100644
index 000000000..255bb6f48
--- /dev/null
+++ b/docs/compatibility/rds-api-coverage/README.md
@@ -0,0 +1,224 @@
+---
+title: "RDS API Coverage"
+seoTitle: "Relational Database Service API Coverage — Spinifex Docs"
+description: "Every operation in the Amazon RDS API model and whether Spinifex implements it, for the managed PostgreSQL and MariaDB engines it offers on each build."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - rds
+ - databases
+ - postgresql
+ - mariadb
+---
+
+# RDS API Coverage
+
+## Overview
+
+Spinifex implements **26 of the 162** operations in the RDS `2014-10-31` API model, as pinned in `aws-sdk-go v1.55.8` — **16.0%**.
+
+### Engines
+
+Spinifex offers PostgreSQL and MariaDB. Each DB instance is one dedicated system-owned VM running the engine directly, launched from a platform AMI and hidden from the customer's EC2 API. `Engine` is fixed at create: there is no in-place engine change, no cross-engine snapshot restore and no migration between the two.
+
+`mysql` is not an accepted engine and is not an alias for `mariadb`. MariaDB is offered under its own AWS engine name, exactly as AWS RDS offers it, so a client — including Terraform's `aws_db_instance` — must set `engine = "mariadb"`. Aliasing would report an engine and a version the instance is not running, and the discrepancy would propagate into `DescribeDBInstances`, parameter-group families and snapshot metadata.
+
+Engine versions are pinned per engine. An `EngineVersion` naming anything but the pin is rejected, including a narrower minor version, because the AMI makes no promise about which minor it carries.
+
+### The endpoint is private
+
+The engine is reached over a customer-account ENI injected into a subnet of the DB subnet group, so the endpoint is reachable from inside the VPC only. The DB VM has other NICs that no customer security group governs, and the engine binds none of them — the port is not open there at all, rather than open and gated.
+
+### TLS is required by default
+
+Both engines enforce encrypted connections by default: `rds.force_ssl` on PostgreSQL and `require_secure_transport` on MariaDB. For MariaDB this is a deliberate divergence from AWS, which leaves it off. Both are boolean, modifiable and dynamic, so setting either to `0` in a parameter group restores plaintext without a reboot.
+
+Enforcement requires that the connection is encrypted, not that the client validates the certificate. The engine serves a per-instance certificate signed by the cluster CA carrying both the ENI address and the DNS name, so a client that wants full verification can have it. A deployment holding no cluster CA cannot serve TLS at all, and a parameter group asking for enforcement there is refused rather than quietly ignored.
+
+### Rejected parameters
+
+A parameter whose omission would create a false safety, security or availability guarantee is rejected rather than silently dropped — `MultiAZ=true` on a single-AZ platform, `PubliclyAccessible=true` against a private endpoint, `StorageEncrypted=false` where unencrypted storage is not offered. Parameters that are merely inert are accepted as no-ops.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `AddRoleToDBCluster` | ❌ Not implemented |
+| `AddRoleToDBInstance` | ❌ Not implemented |
+| `AddSourceIdentifierToSubscription` | ❌ Not implemented |
+| `AddTagsToResource` | ✅ Implemented |
+| `ApplyPendingMaintenanceAction` | ❌ Not implemented |
+| `AuthorizeDBSecurityGroupIngress` | ❌ Not implemented |
+| `BacktrackDBCluster` | ❌ Not implemented |
+| `CancelExportTask` | ❌ Not implemented |
+| `CopyDBClusterParameterGroup` | ❌ Not implemented |
+| `CopyDBClusterSnapshot` | ❌ Not implemented |
+| `CopyDBParameterGroup` | ❌ Not implemented |
+| `CopyDBSnapshot` | ❌ Not implemented |
+| `CopyOptionGroup` | ❌ Not implemented |
+| `CreateBlueGreenDeployment` | ❌ Not implemented |
+| `CreateCustomDBEngineVersion` | ❌ Not implemented |
+| `CreateDBCluster` | 🚫 Not supported |
+| `CreateDBClusterEndpoint` | ❌ Not implemented |
+| `CreateDBClusterParameterGroup` | ❌ Not implemented |
+| `CreateDBClusterSnapshot` | ❌ Not implemented |
+| `CreateDBInstance` | ✅ Implemented |
+| `CreateDBInstanceReadReplica` | 🚫 Not supported |
+| `CreateDBParameterGroup` | ✅ Implemented |
+| `CreateDBProxy` | ❌ Not implemented |
+| `CreateDBProxyEndpoint` | ❌ Not implemented |
+| `CreateDBSecurityGroup` | ❌ Not implemented |
+| `CreateDBShardGroup` | ❌ Not implemented |
+| `CreateDBSnapshot` | ✅ Implemented |
+| `CreateDBSubnetGroup` | ✅ Implemented |
+| `CreateEventSubscription` | ❌ Not implemented |
+| `CreateGlobalCluster` | ❌ Not implemented |
+| `CreateIntegration` | ❌ Not implemented |
+| `CreateOptionGroup` | 🚫 Not supported |
+| `CreateTenantDatabase` | ❌ Not implemented |
+| `DeleteBlueGreenDeployment` | ❌ Not implemented |
+| `DeleteCustomDBEngineVersion` | ❌ Not implemented |
+| `DeleteDBCluster` | 🚫 Not supported |
+| `DeleteDBClusterAutomatedBackup` | ❌ Not implemented |
+| `DeleteDBClusterEndpoint` | ❌ Not implemented |
+| `DeleteDBClusterParameterGroup` | ❌ Not implemented |
+| `DeleteDBClusterSnapshot` | ❌ Not implemented |
+| `DeleteDBInstance` | ✅ Implemented |
+| `DeleteDBInstanceAutomatedBackup` | ❌ Not implemented |
+| `DeleteDBParameterGroup` | ✅ Implemented |
+| `DeleteDBProxy` | ❌ Not implemented |
+| `DeleteDBProxyEndpoint` | ❌ Not implemented |
+| `DeleteDBSecurityGroup` | ❌ Not implemented |
+| `DeleteDBShardGroup` | ❌ Not implemented |
+| `DeleteDBSnapshot` | ✅ Implemented |
+| `DeleteDBSubnetGroup` | ✅ Implemented |
+| `DeleteEventSubscription` | ❌ Not implemented |
+| `DeleteGlobalCluster` | ❌ Not implemented |
+| `DeleteIntegration` | ❌ Not implemented |
+| `DeleteOptionGroup` | 🚫 Not supported |
+| `DeleteTenantDatabase` | ❌ Not implemented |
+| `DeregisterDBProxyTargets` | ❌ Not implemented |
+| `DescribeAccountAttributes` | ❌ Not implemented |
+| `DescribeBlueGreenDeployments` | ❌ Not implemented |
+| `DescribeCertificates` | ❌ Not implemented |
+| `DescribeDBClusterAutomatedBackups` | ❌ Not implemented |
+| `DescribeDBClusterBacktracks` | ❌ Not implemented |
+| `DescribeDBClusterEndpoints` | ❌ Not implemented |
+| `DescribeDBClusterParameterGroups` | ❌ Not implemented |
+| `DescribeDBClusterParameters` | ❌ Not implemented |
+| `DescribeDBClusterSnapshotAttributes` | ❌ Not implemented |
+| `DescribeDBClusterSnapshots` | ❌ Not implemented |
+| `DescribeDBClusters` | 🚫 Not supported |
+| `DescribeDBEngineVersions` | ✅ Implemented |
+| `DescribeDBInstanceAutomatedBackups` | ✅ Implemented |
+| `DescribeDBInstances` | ✅ Implemented |
+| `DescribeDBLogFiles` | ❌ Not implemented |
+| `DescribeDBParameterGroups` | ✅ Implemented |
+| `DescribeDBParameters` | ✅ Implemented |
+| `DescribeDBProxies` | ❌ Not implemented |
+| `DescribeDBProxyEndpoints` | ❌ Not implemented |
+| `DescribeDBProxyTargetGroups` | ❌ Not implemented |
+| `DescribeDBProxyTargets` | ❌ Not implemented |
+| `DescribeDBRecommendations` | ❌ Not implemented |
+| `DescribeDBSecurityGroups` | ❌ Not implemented |
+| `DescribeDBShardGroups` | ❌ Not implemented |
+| `DescribeDBSnapshotAttributes` | ❌ Not implemented |
+| `DescribeDBSnapshotTenantDatabases` | ❌ Not implemented |
+| `DescribeDBSnapshots` | ✅ Implemented |
+| `DescribeDBSubnetGroups` | ✅ Implemented |
+| `DescribeEngineDefaultClusterParameters` | ❌ Not implemented |
+| `DescribeEngineDefaultParameters` | ❌ Not implemented |
+| `DescribeEventCategories` | ❌ Not implemented |
+| `DescribeEventSubscriptions` | ❌ Not implemented |
+| `DescribeEvents` | ✅ Implemented |
+| `DescribeExportTasks` | ❌ Not implemented |
+| `DescribeGlobalClusters` | ❌ Not implemented |
+| `DescribeIntegrations` | ❌ Not implemented |
+| `DescribeOptionGroupOptions` | ❌ Not implemented |
+| `DescribeOptionGroups` | 🚫 Not supported |
+| `DescribeOrderableDBInstanceOptions` | ✅ Implemented |
+| `DescribePendingMaintenanceActions` | ❌ Not implemented |
+| `DescribeReservedDBInstances` | ❌ Not implemented |
+| `DescribeReservedDBInstancesOfferings` | ❌ Not implemented |
+| `DescribeSourceRegions` | ❌ Not implemented |
+| `DescribeTenantDatabases` | ❌ Not implemented |
+| `DescribeValidDBInstanceModifications` | ❌ Not implemented |
+| `DisableHttpEndpoint` | ❌ Not implemented |
+| `DownloadDBLogFilePortion` | ❌ Not implemented |
+| `EnableHttpEndpoint` | ❌ Not implemented |
+| `FailoverDBCluster` | 🚫 Not supported |
+| `FailoverGlobalCluster` | ❌ Not implemented |
+| `ListTagsForResource` | ✅ Implemented |
+| `ModifyActivityStream` | ❌ Not implemented |
+| `ModifyCertificates` | ❌ Not implemented |
+| `ModifyCurrentDBClusterCapacity` | ❌ Not implemented |
+| `ModifyCustomDBEngineVersion` | ❌ Not implemented |
+| `ModifyDBCluster` | 🚫 Not supported |
+| `ModifyDBClusterEndpoint` | ❌ Not implemented |
+| `ModifyDBClusterParameterGroup` | ❌ Not implemented |
+| `ModifyDBClusterSnapshotAttribute` | ❌ Not implemented |
+| `ModifyDBInstance` | ✅ Implemented |
+| `ModifyDBParameterGroup` | ✅ Implemented |
+| `ModifyDBProxy` | ❌ Not implemented |
+| `ModifyDBProxyEndpoint` | ❌ Not implemented |
+| `ModifyDBProxyTargetGroup` | ❌ Not implemented |
+| `ModifyDBRecommendation` | ❌ Not implemented |
+| `ModifyDBShardGroup` | ❌ Not implemented |
+| `ModifyDBSnapshot` | ❌ Not implemented |
+| `ModifyDBSnapshotAttribute` | ❌ Not implemented |
+| `ModifyDBSubnetGroup` | ❌ Not implemented |
+| `ModifyEventSubscription` | ❌ Not implemented |
+| `ModifyGlobalCluster` | ❌ Not implemented |
+| `ModifyIntegration` | ❌ Not implemented |
+| `ModifyOptionGroup` | 🚫 Not supported |
+| `ModifyTenantDatabase` | ❌ Not implemented |
+| `PromoteReadReplica` | 🚫 Not supported |
+| `PromoteReadReplicaDBCluster` | ❌ Not implemented |
+| `PurchaseReservedDBInstancesOffering` | ❌ Not implemented |
+| `RebootDBCluster` | ❌ Not implemented |
+| `RebootDBInstance` | ✅ Implemented |
+| `RebootDBShardGroup` | ❌ Not implemented |
+| `RegisterDBProxyTargets` | ❌ Not implemented |
+| `RemoveFromGlobalCluster` | ❌ Not implemented |
+| `RemoveRoleFromDBCluster` | ❌ Not implemented |
+| `RemoveRoleFromDBInstance` | ❌ Not implemented |
+| `RemoveSourceIdentifierFromSubscription` | ❌ Not implemented |
+| `RemoveTagsFromResource` | ✅ Implemented |
+| `ResetDBClusterParameterGroup` | ❌ Not implemented |
+| `ResetDBParameterGroup` | ❌ Not implemented |
+| `RestoreDBClusterFromS3` | ❌ Not implemented |
+| `RestoreDBClusterFromSnapshot` | ❌ Not implemented |
+| `RestoreDBClusterToPointInTime` | ❌ Not implemented |
+| `RestoreDBInstanceFromDBSnapshot` | ✅ Implemented |
+| `RestoreDBInstanceFromS3` | ❌ Not implemented |
+| `RestoreDBInstanceToPointInTime` | 🚫 Not supported |
+| `RevokeDBSecurityGroupIngress` | ❌ Not implemented |
+| `StartActivityStream` | ❌ Not implemented |
+| `StartDBCluster` | ❌ Not implemented |
+| `StartDBInstance` | ✅ Implemented |
+| `StartDBInstanceAutomatedBackupsReplication` | ❌ Not implemented |
+| `StartExportTask` | ❌ Not implemented |
+| `StopActivityStream` | ❌ Not implemented |
+| `StopDBCluster` | ❌ Not implemented |
+| `StopDBInstance` | ✅ Implemented |
+| `StopDBInstanceAutomatedBackupsReplication` | ❌ Not implemented |
+| `SwitchoverBlueGreenDeployment` | ❌ Not implemented |
+| `SwitchoverGlobalCluster` | ❌ Not implemented |
+| `SwitchoverReadReplica` | ❌ Not implemented |
+| `AcknowledgeDBBootstrap` | 🔒 Outside the pinned model |
+| `GetDBBootstrapConfig` | 🔒 Outside the pinned model |
+| `PollDBCommands` | 🔒 Outside the pinned model |
+| `RegisterDBInstance` | 🔒 Outside the pinned model |
+| `SubmitDBStateChange` | 🔒 Outside the pinned model |
diff --git a/docs/compatibility/rds-api-coverage/intro.md b/docs/compatibility/rds-api-coverage/intro.md
new file mode 100644
index 000000000..280cb133b
--- /dev/null
+++ b/docs/compatibility/rds-api-coverage/intro.md
@@ -0,0 +1,21 @@
+### Engines
+
+Spinifex offers PostgreSQL and MariaDB. Each DB instance is one dedicated system-owned VM running the engine directly, launched from a platform AMI and hidden from the customer's EC2 API. `Engine` is fixed at create: there is no in-place engine change, no cross-engine snapshot restore and no migration between the two.
+
+`mysql` is not an accepted engine and is not an alias for `mariadb`. MariaDB is offered under its own AWS engine name, exactly as AWS RDS offers it, so a client — including Terraform's `aws_db_instance` — must set `engine = "mariadb"`. Aliasing would report an engine and a version the instance is not running, and the discrepancy would propagate into `DescribeDBInstances`, parameter-group families and snapshot metadata.
+
+Engine versions are pinned per engine. An `EngineVersion` naming anything but the pin is rejected, including a narrower minor version, because the AMI makes no promise about which minor it carries.
+
+### The endpoint is private
+
+The engine is reached over a customer-account ENI injected into a subnet of the DB subnet group, so the endpoint is reachable from inside the VPC only. The DB VM has other NICs that no customer security group governs, and the engine binds none of them — the port is not open there at all, rather than open and gated.
+
+### TLS is required by default
+
+Both engines enforce encrypted connections by default: `rds.force_ssl` on PostgreSQL and `require_secure_transport` on MariaDB. For MariaDB this is a deliberate divergence from AWS, which leaves it off. Both are boolean, modifiable and dynamic, so setting either to `0` in a parameter group restores plaintext without a reboot.
+
+Enforcement requires that the connection is encrypted, not that the client validates the certificate. The engine serves a per-instance certificate signed by the cluster CA carrying both the ENI address and the DNS name, so a client that wants full verification can have it. A deployment holding no cluster CA cannot serve TLS at all, and a parameter group asking for enforcement there is refused rather than quietly ignored.
+
+### Rejected parameters
+
+A parameter whose omission would create a false safety, security or availability guarantee is rejected rather than silently dropped — `MultiAZ=true` on a single-AZ platform, `PubliclyAccessible=true` against a private endpoint, `StorageEncrypted=false` where unencrypted storage is not offered. Parameters that are merely inert are accepted as no-ops.
diff --git a/docs/compatibility/s3-api-coverage/README.md b/docs/compatibility/s3-api-coverage/README.md
new file mode 100644
index 000000000..974e9ac11
--- /dev/null
+++ b/docs/compatibility/s3-api-coverage/README.md
@@ -0,0 +1,29 @@
+---
+title: "S3 API Coverage"
+seoTitle: "Amazon S3 API Compatibility on Spinifex — Spinifex Docs"
+description: "How Spinifex serves the Amazon S3 API through Predastore, and why its coverage is measured there rather than derived from a gateway dispatch table here."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - s3
+ - storage
+ - predastore
+---
+
+# S3 API Coverage
+
+## Overview
+
+The S3 API model pins **99** operations at API version `2006-03-01`, but Spinifex's coverage of them is not mechanically enumerable: Spinifex delegates the S3 REST surface to Predastore, which has no operation-name dispatch table to compare mechanically.
+
+### Where S3 is served
+
+Spinifex does not dispatch S3 operations. The REST surface is delegated whole to **Predastore**, which serves it directly, so there is no operation-name dispatch table in the gateway to compare against the model — the comparison that produces every other page on this site has nothing to read here.
+
+That is why this page reports no percentage. Claiming one from an empty dispatch table would read as 0% implemented, which is the opposite of the truth: S3 is one of the most complete surfaces in the platform.
+
+Predastore publishes its own measured compatibility. Consult it for the operations, headers and behaviours it supports.
diff --git a/docs/compatibility/s3-api-coverage/intro.md b/docs/compatibility/s3-api-coverage/intro.md
new file mode 100644
index 000000000..5d4edd03c
--- /dev/null
+++ b/docs/compatibility/s3-api-coverage/intro.md
@@ -0,0 +1,7 @@
+### Where S3 is served
+
+Spinifex does not dispatch S3 operations. The REST surface is delegated whole to **Predastore**, which serves it directly, so there is no operation-name dispatch table in the gateway to compare against the model — the comparison that produces every other page on this site has nothing to read here.
+
+That is why this page reports no percentage. Claiming one from an empty dispatch table would read as 0% implemented, which is the opposite of the truth: S3 is one of the most complete surfaces in the platform.
+
+Predastore publishes its own measured compatibility. Consult it for the operations, headers and behaviours it supports.
diff --git a/docs/compatibility/sts-api-coverage/README.md b/docs/compatibility/sts-api-coverage/README.md
new file mode 100644
index 000000000..3f3291b8d
--- /dev/null
+++ b/docs/compatibility/sts-api-coverage/README.md
@@ -0,0 +1,52 @@
+---
+title: "STS API Coverage"
+seoTitle: "AWS Security Token Service API Coverage — Spinifex Docs"
+description: "Every operation in the AWS STS API model and whether Spinifex implements it, covering role assumption, session tokens and web identity federation (IRSA)."
+category: "Coverage"
+sections:
+ - overview
+tags:
+ - aws
+ - compatibility
+ - coverage
+ - sts
+ - identity
+ - credentials
+---
+
+# STS API Coverage
+
+## Overview
+
+Spinifex implements **4 of the 8** operations in the STS `2011-06-15` API model, as pinned in `aws-sdk-go v1.55.8` — **50.0%**.
+
+### Trust policies
+
+Trust policies are validated at write time rather than silently narrowed at assume time. `NotPrincipal`, `NotAction`, empty-string `Action` elements and empty `Principal` blocks are all rejected as malformed.
+
+`Condition` blocks are rejected except on `AssumeRoleWithWebIdentity` with `StringEquals`, which is the shape IRSA needs and which Spinifex evaluates at assume time against the token's issuer, subject and audience. Anything wider is refused rather than accepted and ignored, because an accepted-but-unevaluated condition is a silent over-grant.
+
+### Parameters that are refused, not ignored
+
+Several inputs the model describes are deliberately rejected rather than accepted as no-ops: inline session policies and policy ARNs, session tags, and MFA serial numbers and token codes. Each of them would otherwise appear to restrict or strengthen a session that in fact carries the role's full permissions.
+
+### Operations
+
+| Status | Meaning |
+|---|---|
+| ✅ Implemented | A modelled operation bound to a real handler. |
+| 🟡 Stub | A registered handler that answers with a fixed or empty result. |
+| 🚫 Not supported | A registered handler that deliberately refuses, so a client sees "not offered" rather than an unknown action. |
+| ❌ Not implemented | Modelled by AWS, not registered by Spinifex. |
+| 🔒 Outside the pinned model | Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action. |
+
+| Operation | Status |
+|---|---|
+| `AssumeRole` | ✅ Implemented |
+| `AssumeRoleWithSAML` | ❌ Not implemented |
+| `AssumeRoleWithWebIdentity` | ✅ Implemented |
+| `DecodeAuthorizationMessage` | ❌ Not implemented |
+| `GetAccessKeyInfo` | ❌ Not implemented |
+| `GetCallerIdentity` | ✅ Implemented |
+| `GetFederationToken` | ❌ Not implemented |
+| `GetSessionToken` | ✅ Implemented |
diff --git a/docs/compatibility/sts-api-coverage/intro.md b/docs/compatibility/sts-api-coverage/intro.md
new file mode 100644
index 000000000..2da53c609
--- /dev/null
+++ b/docs/compatibility/sts-api-coverage/intro.md
@@ -0,0 +1,9 @@
+### Trust policies
+
+Trust policies are validated at write time rather than silently narrowed at assume time. `NotPrincipal`, `NotAction`, empty-string `Action` elements and empty `Principal` blocks are all rejected as malformed.
+
+`Condition` blocks are rejected except on `AssumeRoleWithWebIdentity` with `StringEquals`, which is the shape IRSA needs and which Spinifex evaluates at assume time against the token's issuer, subject and audience. Anything wider is refused rather than accepted and ignored, because an accepted-but-unevaluated condition is a silent over-grant.
+
+### Parameters that are refused, not ignored
+
+Several inputs the model describes are deliberately rejected rather than accepted as no-ops: inline session policies and policy ARNs, session tags, and MFA serial numbers and token codes. Each of them would otherwise appear to restrict or strengthen a session that in fact carries the role's full permissions.
diff --git a/internal/awsmodel/coverage.go b/internal/awsmodel/coverage.go
index e94612af3..23df81b14 100644
--- a/internal/awsmodel/coverage.go
+++ b/internal/awsmodel/coverage.go
@@ -123,65 +123,25 @@ func toSet(values []string) map[string]bool {
return set
}
-// RenderCoverageMarkdown renders a reproducible divergence report suitable for
-// publishing directly or checking as a generated artefact.
-func RenderCoverageMarkdown(coverages []OperationCoverage) string {
- ordered := append([]OperationCoverage(nil), coverages...)
- sort.Slice(ordered, func(i, j int) bool { return ordered[i].Service < ordered[j].Service })
-
+// RenderCoverageSummary renders the cross-service counts as plain text for a
+// terminal. The published pages carry the per-operation detail.
+func RenderCoverageSummary(coverages []OperationCoverage) string {
var report strings.Builder
- fmt.Fprintf(&report, "# AWS model operation coverage\n\n")
- fmt.Fprintf(&report, "Generated from the cached `aws-sdk-go %s` `api-2.json` models and Spinifex's authoritative gateway dispatch tables.\n\n", SourceSDKVersion)
- report.WriteString("Implemented means a modelled operation is registered to a real handler. Stub and deliberately unsupported handlers are reported separately. Shape conformance does not imply behavioural conformance.\n\n")
- report.WriteString("| Service | API version | Modelled | Registered | Implemented | Stubbed | Unsupported | Missing | Extra |\n")
- report.WriteString("|---|---:|---:|---:|---:|---:|---:|---:|---:|\n")
- for _, coverage := range ordered {
+ fmt.Fprintf(&report, "AWS model operation coverage (aws-sdk-go %s)\n\n", SourceSDKVersion)
+ for _, coverage := range sortedCoverages(coverages) {
if coverage.Opaque {
- fmt.Fprintf(&report, "| %s | %s | %d | — | — | — | — | — | — |\n",
- coverage.Service, coverage.APIVersion, len(coverage.Modelled))
+ fmt.Fprintf(&report, "%-24s %-12s not enumerable\n", coverage.Service, coverage.APIVersion)
continue
}
- fmt.Fprintf(&report, "| %s | %s | %d | %d | %d | %d | %d | %d | %d |\n",
- coverage.Service, coverage.APIVersion, len(coverage.Modelled), len(coverage.Registered),
- len(coverage.Implemented), len(coverage.Stubbed), len(coverage.Unsupported), len(coverage.Missing), len(coverage.Extra))
- }
-
- for _, coverage := range ordered {
- fmt.Fprintf(&report, "\n## %s\n\n", coverage.Service)
- if coverage.Opaque {
- fmt.Fprintf(&report, "Operation coverage is not enumerable: %s\n", coverage.Note)
- continue
- }
- percentage := float64(0)
- if len(coverage.Modelled) != 0 {
- percentage = 100 * float64(len(coverage.Implemented)) / float64(len(coverage.Modelled))
- }
- fmt.Fprintf(&report, "Implements **%d of %d** modelled operations (%.1f%%).\n", len(coverage.Implemented), len(coverage.Modelled), percentage)
- writeOperationList(&report, "Implemented", coverage.Implemented)
- writeOperationList(&report, "Missing from dispatch", coverage.Missing)
- writeOperationList(&report, "Registered stubs", coverage.Stubbed)
- writeOperationList(&report, "Deliberately unsupported", coverage.Unsupported)
- writeOperationList(&report, "Registered outside the pinned model", coverage.Extra)
- if coverage.Note != "" {
- fmt.Fprintf(&report, "\nNote: %s\n", coverage.Note)
- }
+ fmt.Fprintf(&report, "%-24s %-12s %3d of %3d implemented (%5.1f%%), %3d stubbed, %3d unsupported, %3d outside the model\n",
+ coverage.Service, coverage.APIVersion, len(coverage.Implemented), len(coverage.Modelled),
+ coverage.ImplementedPercent(), len(coverage.Stubbed), len(coverage.Unsupported), len(coverage.Extra))
}
return report.String()
}
-func writeOperationList(report *strings.Builder, title string, operations []string) {
- fmt.Fprintf(report, "\n%s (%d)
\n\n", title, len(operations))
- if len(operations) == 0 {
- report.WriteString("None.\n")
- } else {
- for start := 0; start < len(operations); start += 8 {
- end := min(start+8, len(operations))
- quoted := make([]string, 0, end-start)
- for _, operation := range operations[start:end] {
- quoted = append(quoted, "`"+operation+"`")
- }
- report.WriteString(strings.Join(quoted, ", ") + "\n\n")
- }
- }
- report.WriteString("\n \n")
+func sortedCoverages(coverages []OperationCoverage) []OperationCoverage {
+ ordered := append([]OperationCoverage(nil), coverages...)
+ sort.Slice(ordered, func(i, j int) bool { return ordered[i].Service < ordered[j].Service })
+ return ordered
}
diff --git a/internal/awsmodel/coverage_test.go b/internal/awsmodel/coverage_test.go
index 79c103419..db9bbf3f2 100644
--- a/internal/awsmodel/coverage_test.go
+++ b/internal/awsmodel/coverage_test.go
@@ -32,20 +32,21 @@ func TestCompareOperationsRejectsInvalidInventory(t *testing.T) {
}
}
-func TestRenderCoverageMarkdown(t *testing.T) {
+func TestRenderCoverageSummary(t *testing.T) {
coverage, err := CompareOperations(STS, DispatchInventory{Registered: []string{"AssumeRole"}})
if err != nil {
t.Fatal(err)
}
- report := RenderCoverageMarkdown([]OperationCoverage{coverage})
+ report := RenderCoverageSummary([]OperationCoverage{coverage})
for _, want := range []string{
- "# AWS model operation coverage",
- "| sts | 2011-06-15 | 8 | 1 | 1 | 0 | 0 | 7 | 0 |",
- "Implements **1 of 8** modelled operations (12.5%).",
- "Missing from dispatch (7)",
+ "aws-sdk-go " + SourceSDKVersion,
+ "1 of 8 implemented ( 12.5%)",
} {
if !strings.Contains(report, want) {
- t.Errorf("report does not contain %q:\n%s", want, report)
+ t.Errorf("summary does not contain %q:\n%s", want, report)
}
}
+ if strings.Contains(report, "") {
+ t.Errorf("summary contains raw HTML the docs site would escape:\n%s", report)
+ }
}
diff --git a/internal/awsmodel/page.go b/internal/awsmodel/page.go
new file mode 100644
index 000000000..d98c466db
--- /dev/null
+++ b/internal/awsmodel/page.go
@@ -0,0 +1,267 @@
+package awsmodel
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+)
+
+// Published operation states. The symbol carries the status at a glance and the
+// label disambiguates it; the docs site escapes inline SVG, so these are runes.
+const (
+ StatusImplemented = "✅ Implemented"
+ StatusStub = "🟡 Stub"
+ StatusNotSupported = "🚫 Not supported"
+ StatusNotImplemented = "❌ Not implemented"
+ StatusOutsideModel = "🔒 Outside the pinned model"
+)
+
+// Frontmatter length rules enforced by the docs site. See docs/README.md.
+const (
+ seoTitleSuffix = " — Spinifex Docs"
+ seoTitleMin = 50
+ seoTitleMax = 60
+ descriptionMin = 150
+ descriptionMax = 160
+)
+
+var slugPattern = regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`)
+
+// OperationStatus is one row of a published coverage table.
+type OperationStatus struct {
+ Operation string
+ Status string
+}
+
+// ImplementedPercent is the share of modelled operations bound to a real
+// handler, or zero for a model with no operations.
+func (c OperationCoverage) ImplementedPercent() float64 {
+ if len(c.Modelled) == 0 {
+ return 0
+ }
+ return 100 * float64(len(c.Implemented)) / float64(len(c.Modelled))
+}
+
+// OperationStatuses returns every modelled operation with its dispatch state,
+// followed by the registered operations the pinned model does not describe.
+func (c OperationCoverage) OperationStatuses() []OperationStatus {
+ registered := toSet(c.Registered)
+ stubbed := toSet(c.Stubbed)
+ unsupported := toSet(c.Unsupported)
+
+ statuses := make([]OperationStatus, 0, len(c.Modelled)+len(c.Extra))
+ for _, operation := range c.Modelled {
+ status := StatusNotImplemented
+ switch {
+ case stubbed[operation]:
+ status = StatusStub
+ case unsupported[operation]:
+ status = StatusNotSupported
+ case registered[operation]:
+ status = StatusImplemented
+ }
+ statuses = append(statuses, OperationStatus{Operation: operation, Status: status})
+ }
+ for _, operation := range c.Extra {
+ statuses = append(statuses, OperationStatus{Operation: operation, Status: StatusOutsideModel})
+ }
+ return statuses
+}
+
+// PageMetadata is the checked-in frontmatter for one published coverage page.
+// It is hand-maintained rather than derived, because a description carrying a
+// live count would drift outside the length the docs site enforces.
+type PageMetadata struct {
+ Slug string `json:"slug"`
+ Name string `json:"name"`
+ Title string `json:"title"`
+ SEOTitle string `json:"seoTitle"`
+ Description string `json:"description"`
+ Tags []string `json:"tags"`
+}
+
+// PageSet is the metadata for the index page and every service page.
+type PageSet struct {
+ Category string `json:"category"`
+ Index PageMetadata `json:"index"`
+ Services map[Service]PageMetadata `json:"services"`
+}
+
+// ParsePageSet decodes docs/compatibility/pages.json and checks it describes
+// exactly the services the loader knows about, with publishable frontmatter.
+func ParsePageSet(contents []byte) (PageSet, error) {
+ decoder := json.NewDecoder(bytes.NewReader(contents))
+ decoder.DisallowUnknownFields()
+ var pages PageSet
+ if err := decoder.Decode(&pages); err != nil {
+ return PageSet{}, fmt.Errorf("awsmodel: parse coverage pages: %w", err)
+ }
+ if pages.Category == "" {
+ return PageSet{}, fmt.Errorf("awsmodel: coverage pages: category is empty")
+ }
+
+ slugs := map[string]bool{}
+ if err := validatePage("index", pages.Index, slugs); err != nil {
+ return PageSet{}, err
+ }
+ for _, service := range Services() {
+ page, ok := pages.Services[service]
+ if !ok {
+ return PageSet{}, fmt.Errorf("awsmodel: coverage pages: no entry for service %q", service)
+ }
+ if err := validatePage(string(service), page, slugs); err != nil {
+ return PageSet{}, err
+ }
+ }
+ for service := range pages.Services {
+ if _, ok := modelFiles[service]; !ok {
+ return PageSet{}, fmt.Errorf("awsmodel: coverage pages: unknown service %q", service)
+ }
+ }
+ return pages, nil
+}
+
+func validatePage(owner string, page PageMetadata, slugs map[string]bool) error {
+ fail := func(format string, args ...any) error {
+ return fmt.Errorf("awsmodel: coverage page %s: %s", owner, fmt.Sprintf(format, args...))
+ }
+ if !slugPattern.MatchString(page.Slug) {
+ return fail("slug %q is not lowercase kebab-case", page.Slug)
+ }
+ if slugs[page.Slug] {
+ return fail("slug %q is used by another page", page.Slug)
+ }
+ slugs[page.Slug] = true
+ if page.Name == "" || page.Title == "" {
+ return fail("name and title are required")
+ }
+ if len(page.Tags) == 0 {
+ return fail("at least one tag is required")
+ }
+ if !strings.HasSuffix(page.SEOTitle, seoTitleSuffix) {
+ return fail("seoTitle %q does not end with %q", page.SEOTitle, seoTitleSuffix)
+ }
+ if length := utf8.RuneCountInString(page.SEOTitle); length < seoTitleMin || length > seoTitleMax {
+ return fail("seoTitle is %d characters, want %d-%d", length, seoTitleMin, seoTitleMax)
+ }
+ if length := utf8.RuneCountInString(page.Description); length < descriptionMin || length > descriptionMax {
+ return fail("description is %d characters, want %d-%d", length, descriptionMin, descriptionMax)
+ }
+ return nil
+}
+
+// RenderServicePage renders one publishable coverage page. intro is optional
+// hand-written prose emitted above the table; it may not open a new page
+// section, so its headings must be level three or deeper.
+func RenderServicePage(coverage OperationCoverage, pages PageSet, intro string) (string, error) {
+ if err := checkIntro(string(coverage.Service), intro); err != nil {
+ return "", err
+ }
+ page, ok := pages.Services[coverage.Service]
+ if !ok {
+ return "", fmt.Errorf("awsmodel: coverage pages: no entry for service %q", coverage.Service)
+ }
+
+ var body strings.Builder
+ writeFrontmatter(&body, page, pages.Category)
+ fmt.Fprintf(&body, "# %s\n\n## Overview\n\n", page.Title)
+
+ writeSummary(&body, coverage, page)
+
+ if intro != "" {
+ body.WriteString(strings.TrimSpace(intro) + "\n\n")
+ }
+ if coverage.Opaque {
+ return strings.TrimRight(body.String(), "\n") + "\n", nil
+ }
+
+ body.WriteString("### Operations\n\n")
+ writeStatusLegend(&body)
+ body.WriteString("\n| Operation | Status |\n|---|---|\n")
+ for _, status := range coverage.OperationStatuses() {
+ fmt.Fprintf(&body, "| `%s` | %s |\n", status.Operation, status.Status)
+ }
+ return body.String(), nil
+}
+
+// RenderIndexPage renders the cross-service summary that links to each page.
+func RenderIndexPage(coverages []OperationCoverage, pages PageSet, intro string) (string, error) {
+ if err := checkIntro("index", intro); err != nil {
+ return "", err
+ }
+
+ var body strings.Builder
+ writeFrontmatter(&body, pages.Index, pages.Category)
+ fmt.Fprintf(&body, "# %s\n\n## Overview\n\n", pages.Index.Title)
+ fmt.Fprintf(&body, "Spinifex serves the AWS APIs below. Every page counts the operations in the pinned `aws-sdk-go %s` `api-2.json` model for its service and reports, operation by operation, whether Spinifex implements it.\n\n", SourceSDKVersion)
+ body.WriteString("| Service | API version | Implemented | Modelled | Coverage |\n|---|---|---:|---:|---:|\n")
+ for _, coverage := range sortedCoverages(coverages) {
+ page, ok := pages.Services[coverage.Service]
+ if !ok {
+ return "", fmt.Errorf("awsmodel: coverage pages: no entry for service %q", coverage.Service)
+ }
+ if coverage.Opaque {
+ fmt.Fprintf(&body, "| [%s](/docs/%s) | %s | — | %d | — |\n", page.Name, page.Slug, coverage.APIVersion, len(coverage.Modelled))
+ continue
+ }
+ fmt.Fprintf(&body, "| [%s](/docs/%s) | %s | %d | %d | %.1f%% |\n",
+ page.Name, page.Slug, coverage.APIVersion, len(coverage.Implemented), len(coverage.Modelled), coverage.ImplementedPercent())
+ }
+
+ body.WriteString("\n")
+ writeStatusLegend(&body)
+ if intro != "" {
+ body.WriteString("\n" + strings.TrimSpace(intro) + "\n")
+ }
+ return body.String(), nil
+}
+
+// writeSummary states the implemented-of-modelled count, or why there is none.
+func writeSummary(body *strings.Builder, coverage OperationCoverage, page PageMetadata) {
+ if coverage.Opaque {
+ fmt.Fprintf(body, "The %s API model pins **%d** operations at API version `%s`, but Spinifex's coverage of them is not mechanically enumerable: %s\n\n",
+ page.Name, len(coverage.Modelled), coverage.APIVersion, coverage.Note)
+ return
+ }
+ fmt.Fprintf(body, "Spinifex implements **%d of the %d** operations in the %s `%s` API model, as pinned in `aws-sdk-go %s` — **%.1f%%**.\n\n",
+ len(coverage.Implemented), len(coverage.Modelled), page.Name, coverage.APIVersion, SourceSDKVersion, coverage.ImplementedPercent())
+}
+
+func writeStatusLegend(body *strings.Builder) {
+ body.WriteString("| Status | Meaning |\n|---|---|\n")
+ for _, entry := range [][2]string{
+ {StatusImplemented, "A modelled operation bound to a real handler."},
+ {StatusStub, "A registered handler that answers with a fixed or empty result."},
+ {StatusNotSupported, "A registered handler that deliberately refuses, so a client sees \"not offered\" rather than an unknown action."},
+ {StatusNotImplemented, "Modelled by AWS, not registered by Spinifex."},
+ {StatusOutsideModel, "Registered by Spinifex but absent from the pinned model — an internal route, not a tenant-callable AWS action."},
+ } {
+ fmt.Fprintf(body, "| %s | %s |\n", entry[0], entry[1])
+ }
+}
+
+func writeFrontmatter(body *strings.Builder, page PageMetadata, category string) {
+ body.WriteString("---\n")
+ fmt.Fprintf(body, "title: %s\n", strconv.Quote(page.Title))
+ fmt.Fprintf(body, "seoTitle: %s\n", strconv.Quote(page.SEOTitle))
+ fmt.Fprintf(body, "description: %s\n", strconv.Quote(page.Description))
+ fmt.Fprintf(body, "category: %s\n", strconv.Quote(category))
+ body.WriteString("sections:\n - overview\ntags:\n")
+ for _, tag := range page.Tags {
+ fmt.Fprintf(body, " - %s\n", tag)
+ }
+ body.WriteString("---\n\n")
+}
+
+func checkIntro(owner, intro string) error {
+ for line := range strings.SplitSeq(intro, "\n") {
+ if strings.HasPrefix(line, "# ") || strings.HasPrefix(line, "## ") {
+ return fmt.Errorf("awsmodel: %s intro heading %q opens a new page section; use level three or deeper", owner, strings.TrimSpace(line))
+ }
+ }
+ return nil
+}
diff --git a/internal/awsmodel/page_test.go b/internal/awsmodel/page_test.go
new file mode 100644
index 000000000..ad098b0e9
--- /dev/null
+++ b/internal/awsmodel/page_test.go
@@ -0,0 +1,183 @@
+package awsmodel
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func testPageSet(t *testing.T) PageSet {
+ t.Helper()
+ contents, err := os.ReadFile(filepath.Join("..", "..", "docs", "compatibility", "pages.json"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ pages, err := ParsePageSet(contents)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return pages
+}
+
+func TestParsePageSetAcceptsTheCheckedInFile(t *testing.T) {
+ pages := testPageSet(t)
+
+ for _, service := range Services() {
+ if _, ok := pages.Services[service]; !ok {
+ t.Errorf("no page metadata for service %q", service)
+ }
+ }
+}
+
+func TestParsePageSetRejectsUnpublishableMetadata(t *testing.T) {
+ for name, contents := range map[string]string{
+ "unknown service": `{"category":"Coverage","index":{},"services":{"notaservice":{}}}`,
+ "missing category": `{"index":{},"services":{}}`,
+ "unknown field": `{"category":"Coverage","colour":"blue","index":{},"services":{}}`,
+ "short seoTitle": `{"category":"Coverage","index":{"slug":"aws-api-coverage","name":"All","title":"All",` +
+ `"seoTitle":"Too short — Spinifex Docs","description":"` + strings.Repeat("x", 155) + `","tags":["aws"]}}`,
+ "missing suffix": `{"category":"Coverage","index":{"slug":"aws-api-coverage","name":"All","title":"All",` +
+ `"seoTitle":"` + strings.Repeat("x", 55) + `","description":"` + strings.Repeat("x", 155) + `","tags":["aws"]}}`,
+ "short description": `{"category":"Coverage","index":{"slug":"aws-api-coverage","name":"All","title":"All",` +
+ `"seoTitle":"` + strings.Repeat("x", 39) + ` — Spinifex Docs","description":"too short","tags":["aws"]}}`,
+ "bad slug": `{"category":"Coverage","index":{"slug":"AWS Coverage","name":"All","title":"All",` +
+ `"seoTitle":"` + strings.Repeat("x", 39) + ` — Spinifex Docs","description":"` + strings.Repeat("x", 155) + `","tags":["aws"]}}`,
+ } {
+ t.Run(name, func(t *testing.T) {
+ if _, err := ParsePageSet([]byte(contents)); err == nil {
+ t.Fatal("ParsePageSet accepted unpublishable metadata")
+ }
+ })
+ }
+}
+
+func TestRenderServicePageCarriesEveryStatus(t *testing.T) {
+ pages := testPageSet(t)
+ coverage, err := CompareOperations(STS, DispatchInventory{
+ Registered: []string{"AssumeRole", "GetCallerIdentity", "GetSessionToken", "PublishInternal"},
+ Stubbed: []string{"GetSessionToken"},
+ Unsupported: []string{"GetCallerIdentity"},
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ page, err := RenderServicePage(coverage, pages, "### Scope\n\nHand-written prose.\n")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, want := range []string{
+ `title: "STS API Coverage"`,
+ `category: "Coverage"`,
+ "sections:\n - overview\n",
+ "# STS API Coverage\n\n## Overview\n",
+ "Spinifex implements **1 of the 8** operations in the STS `2011-06-15` API model",
+ "### Scope\n\nHand-written prose.",
+ "| `AssumeRole` | " + StatusImplemented + " |",
+ "| `GetSessionToken` | " + StatusStub + " |",
+ "| `GetCallerIdentity` | " + StatusNotSupported + " |",
+ "| `AssumeRoleWithSAML` | " + StatusNotImplemented + " |",
+ "| `PublishInternal` | " + StatusOutsideModel + " |",
+ } {
+ if !strings.Contains(page, want) {
+ t.Errorf("page does not contain %q:\n%s", want, page)
+ }
+ }
+ if strings.Contains(page, "