Skip to content

Behaviour Coverage

A prediction from chant graph --traffic reaches an engine with every entity the project declares, and not every entity has a rate. This page is the whole of what the lexicons say about their own entities, generated from the rows each contributes through its plugin’s behaviourKinds field. A table transcribed by hand stops being true the first time a row changes, so test/behaviour-coverage.test.ts fails when this page and the rows disagree.

An entity resolves to exactly one verdict, and the second and third are different answers rather than one answer written twice.

VerdictWhat it meansWhere the entity lands
Mappedan engine prices it, as a kind, with its size read from a declared propertyentities, with figures
Declared unmappedits lexicon has looked at this kind of entity and it carries no rate, and the row says whyunpredicted, reason unsupported-kind, with the row’s sentence as the detail
No rowits lexicon owns the entity and has never looked at itunpredicted, reason unsupported-kind, with a detail saying so and naming the lexicon

The distinction between the last two is why the second table in each section exists. “A role is a grant, not a resource traffic flows through” is an answer a reader can act on. “Nothing has an opinion about this” is a missing row in the owning lexicon and should be filed as one. Collapsing them would leave a reader unable to tell a decision from an omission, which is the observation contract’s “absent is not the same as unread”, applied to prediction.

A fourth outcome, provider-not-modelled, is a boundary rather than a verdict about one row. The terraform lexicon declares resources of every provider there is and models one of them, so a google_ resource is reported as belonging to a substrate nothing here models, and nothing needs filing for it.

Neither road ends in a dropped entity or a zero. The request builder refuses a report that leaves an entity in neither map, so one that vanished is a build failure rather than an estate that looks smaller than it is.

The size is the value of the named property, sent verbatim. t3.medium and db.r6g.xlarge are the provider’s own vocabulary, which an engine’s price model is written against, and parsing either into a vCPU count here would put a lossy hop in front of a model that already knows the string. Where the declaration states no size, the request carries none, because a guessed size is a guessed price. A property of the wrong shape (a number where a string is named) is absent rather than coerced.

The region is the request’s unless the row names a property the entity states its own zone in.

The last table in each section is for whatever has no row: the rules a lexicon states as code rather than as rows, each shown with the sentence it produces, and the unknown-type detail a reader will see for anything the lexicon owns and has not classified.

OwnsRows keyed byProviderContributed from
AWS::the entity type, which is the CloudFormation resource typeawslexicons/aws/src/behaviour-kinds.ts
TypeEngine kindSize read fromRegion
AWS::CloudFront::Distributioncdnnonethe request’s
AWS::DynamoDB::TabledatabaseBillingMode (string)the request’s
AWS::EC2::InstancecomputeInstanceType (string)the request’s
AWS::EC2::Volumeblock-storeSize (number)AvailabilityZone, else the request’s
AWS::ECS::Servicecomputenonethe request’s
AWS::EKS::Clustercontrol-planenonethe request’s
AWS::EKS::Nodegroupcomputenonethe request’s
AWS::ElastiCache::CacheClustercacheCacheNodeType (string)the request’s
AWS::ElasticLoadBalancingV2::LoadBalancerload-balancerType (string)the request’s
AWS::Lambda::FunctionserverlessMemorySize (number)the request’s
AWS::RDS::DBClusterdatabaseDBClusterInstanceClass (string)the request’s
AWS::RDS::DBInstancedatabaseDBInstanceClass (string)the request’s
AWS::S3::Bucketobject-storenonethe request’s
AWS::SNS::Topicqueuenonethe request’s
AWS::SQS::Queuequeuenonethe request’s
TypeWhy it carries no rate
AWS::BedrockAgentCore::Gatewaya front door to an agent runtime, billed by what passes through it rather than by existing
AWS::BedrockAgentCore::GatewayTargetone target behind a gateway; the gateway and the runtime are where the meters are
AWS::BedrockAgentCore::Memoryagent memory billed by what is stored and retrieved, which the declaration does not state
AWS::BedrockAgentCore::Runtimean agent runtime billed per invocation and per token, neither of which the declaration states; there is no hour of existence to price
AWS::BedrockAgentCore::WorkloadIdentityan identity a runtime acts as; a grant, with no rate and no capacity
AWS::CloudFormation::Conditiona template predicate deciding whether something is created; it is never created itself
AWS::CloudFormation::Parametera template input, not a thing the account holds. It shapes what is created and is never created itself
AWS::EC2::EIPpriced only while it is attached to nothing, which is a fact about the running account rather than about the declaration
AWS::EC2::InternetGatewaya boundary crossing rather than a resource: no rate of its own and no capacity to saturate
AWS::EC2::NatGatewaypriced as an hourly rate plus a per-gigabyte meter on everything that crosses it. The declaration states the first and nothing at all about the second, and no engine kind here models a half-known price. A figure covering the hourly half alone would read as the cost of the gateway and be wrong by whatever the traffic did
AWS::EC2::Routerouting, which decides where an edge goes and is not itself at either end of one
AWS::EC2::RouteTablerouting, which decides where an edge goes and is not itself at either end of one
AWS::EC2::SecurityGroupa filter on edges that already exist, not a thing at either end of one
AWS::EC2::Subneta network boundary rather than a node: its contribution to a prediction is the zone membership that reaches the engine as containment coverage
AWS::EC2::SubnetRouteTableAssociationan association between two boundaries; nothing flows through it that does not already flow through them
AWS::EC2::VPCa network boundary rather than a node: its contribution to a prediction is the zone membership that reaches the engine as containment coverage
AWS::EC2::VPCGatewayAttachmentan attachment between two boundaries, and neither end is priced by it
AWS::ECR::Repositorypriced by the gigabytes stored in it, which the declaration does not state
AWS::ECS::Clustera namespace for services rather than capacity of its own; the services and their nodes carry the figures
AWS::ECS::TaskDefinitiona template a service runs copies of; the service carries the figures, and pricing both would count the estate twice
AWS::ElasticLoadBalancingV2::Listenera port on a load balancer; the load balancer carries the rate
AWS::ElasticLoadBalancingV2::ListenerRulea routing rule on a listener, and a rule is not a thing at either end of an edge
AWS::ElasticLoadBalancingV2::TargetGroupa set of targets behind a load balancer; the load balancer carries the rate
AWS::Events::Rulepriced by the events matched, which is a fact about traffic the declaration does not state
AWS::IAM::InstanceProfilea wrapper that hands a role to an instance; the instance carries the figures
AWS::IAM::ManagedPolicya policy document is a statement about permission; nothing about it saturates or accrues
AWS::IAM::Policya policy document is a statement about permission; nothing about it saturates or accrues
AWS::IAM::Rolea role is a grant, not a resource traffic flows through: no rate, no capacity, no verdict under a lost zone
AWS::KMS::Keypriced per key per month plus a per-request meter the declaration does not state, and neither half is an hourly rate
AWS::Lambda::EventSourceMappingthe wiring between a queue and a function, both of which are priced where they are declared
AWS::Lambda::Permissiona grant letting one service invoke a function; the function carries the figures
AWS::Logs::LogGrouppriced by the volume ingested into it, which the declaration does not state and no engine can infer from a graph
AWS::RDS::DBSubnetGroupthe set of subnets a database may sit in; the database carries the figures
AWS::Route53::HostedZonepriced per zone per month plus a per-query meter the declaration does not state
AWS::S3::BucketPolicya bucket policy is a grant on the bucket beside it, and the bucket carries the figures
AWS::SNS::Subscriptionpriced by the notifications delivered through it; the topic is what the graph has an edge to
AWS::SQS::QueuePolicya queue policy is a grant on the queue beside it, and the queue carries the figures
AWS::WAFv2::WebACLpriced by the requests inspected through it, which the declaration does not state
A type with no row aboveVerdictWhat the unpredicted entry says
AWS::S3::Bucket.VersioningConfiguration, by ruledeclared unmappeda CloudFormation property type: a nested block of the resource above it, which became an entity of its own in the build. The resource carries the figures, and pricing the block as well would count part of the estate twice
any other AWS:: typeunknown-type, the one verdict that is a defectthe entity has no row in any contributed coverage table. It is a type from a substrate that is modelled, and is neither mapped to an engine kind nor declared unmapped, so nothing has an opinion about it rather than a stated one. Add a row in the lexicon that owns AWS::.
OwnsRows keyed byProviderContributed from
K8s::the entity type, which names the API group and kindkuberneteslexicons/k8s/src/behaviour-kinds.ts
TypeEngine kindSize read fromRegion
K8s::Apps::DaemonSetcomputenonethe request’s
K8s::Apps::Deploymentcomputenonethe request’s
K8s::Apps::StatefulSetcomputenonethe request’s
K8s::Batch::CronJobserverlessnonethe request’s
K8s::Batch::Jobserverlessnonethe request’s
K8s::Core::PersistentVolumeClaimblock-storespec.resources.requests.storage (string)the request’s
K8s::Core::Podcomputenonethe request’s
K8s::Core::Serviceload-balancerspec.type (string)the request’s
K8s::Networking::Ingressload-balancernonethe request’s
TypeWhy it carries no rate
K8s::Argo::Applicationa request to Argo CD to reconcile a source; whatever it creates is priced where that lands
K8s::Autoscaling::HorizontalPodAutoscaleran instruction about how many replicas to run; the workload it scales carries the figures, and a prediction is at one stated traffic level rather than across a scaling range
K8s::Calico::FelixConfigurationtuning for the CNI agent on every node; the nodes carry the figures
K8s::CertManager::Certificatea request to an issuer. The certificate costs nothing; the issuer’s work and the Secret it writes are elsewhere
K8s::CertManager::ClusterIssuerthe issuer a certificate request names; it holds no capacity and serves no traffic
K8s::Core::ConfigMapconfiguration the workloads read; it has no rate and no saturation axis of its own
K8s::Core::LimitRangea default and a ceiling for workloads in a namespace; the workloads carry the figures
K8s::Core::Namespacea boundary the workloads sit inside, and the workloads carry the figures
K8s::Core::ResourceQuotaa ceiling on a namespace’s total requests; the workloads under it carry the figures
K8s::Core::Secretconfiguration the workloads read; it has no rate and no saturation axis of its own
K8s::Core::ServiceAccountan identity, not a workload
K8s::ExternalSecrets::ClusterSecretStorenames where secrets are fetched from; it holds no capacity and serves no traffic
K8s::ExternalSecrets::ExternalSecreta request to copy a value from an external store into a Secret; neither end is a rate
K8s::Flux::GitRepositorya source Flux polls; the workloads it reconciles carry the figures
K8s::Flux::Kustomizationa request to Flux to apply a source; whatever it creates is priced where that lands
K8s::GKE::BackendConfigtuning for a Google load balancer an Ingress creates; the gcp substrate is not modelled here, so neither end is priced here
K8s::HorizontalPodAutoscaleran instruction about how many replicas to run; the workload it scales carries the figures, and a prediction is at one stated traffic level rather than across a scaling range
K8s::Monitoring::PrometheusRulealerting and recording rules evaluated by Prometheus, which carries the figures
K8s::Monitoring::ServiceMonitortells Prometheus what to scrape; Prometheus is a workload elsewhere in the graph and carries the figures
K8s::Networking::IngressClassnames which controller handles an Ingress; the controller and the load balancer it creates carry the figures
K8s::Networking::NetworkPolicya filter on edges that already exist, not a thing at either end of one
K8s::NetworkingGKE::ManagedCertificatea certificate Google issues for an Ingress; the gcp substrate is not modelled here
K8s::NetworkingGKEBeta::FrontendConfigtuning for a Google load balancer an Ingress creates; the gcp substrate is not modelled here
K8s::Policy::PodDisruptionBudgeta constraint on voluntary eviction. It shapes what a lost zone does to a workload and has no rate of its own; expressing that constraint to an engine is a resilience input this contract has no field for
K8s::Rbac::ClusterRolethe cluster-scoped twin of an RBAC role, and a grant for the same reason
K8s::Rbac::ClusterRoleBindingthe cluster-scoped twin of an RBAC binding, and a grant for the same reason
K8s::Rbac::Rolean RBAC role is a grant; the workloads it admits are what cost and saturate
K8s::Rbac::RoleBindingan RBAC binding is a grant; the workloads it admits are what cost and saturate
K8s::Storage::StorageClassthe kind of disk a claim may ask for; the PersistentVolumeClaim carries the figures
K8s::Traefik::IngressRouterouting handled by the Traefik workload, which carries the figures
A type with no row aboveVerdictWhat the unpredicted entry says
any other K8s:: typeunknown-type, the one verdict that is a defectthe entity has no row in any contributed coverage table. It is a type from a substrate that is modelled, and is neither mapped to an engine kind nor declared unmapped, so nothing has an opinion about it rather than a stated one. Add a row in the lexicon that owns K8s::.
OwnsRows keyed byProviderContributed from
Terraform::the provider type in a resource block’s address (aws_instance), since every such block arrives as Terraform::Resource; the root’s other blocks key by their entity typeawslexicons/terraform/src/behaviour/kinds.ts
TypeEngine kindSize read fromRegion
aws_albload-balancerbody.load_balancer_type (string)the request’s
aws_cloudfront_distributioncdnnonethe request’s
aws_db_instancedatabasebody.instance_class (string)the request’s
aws_dynamodb_tabledatabasebody.billing_mode (string)the request’s
aws_ebs_volumeblock-storebody.size (number)body.availability_zone, else the request’s
aws_ecs_servicecomputenonethe request’s
aws_eks_clustercontrol-planenonethe request’s
aws_eks_node_groupcomputenonethe request’s
aws_elasticache_clustercachebody.node_type (string)the request’s
aws_instancecomputebody.instance_type (string)the request’s
aws_lambda_functionserverlessbody.memory_size (number)the request’s
aws_lbload-balancerbody.load_balancer_type (string)the request’s
aws_rds_clusterdatabasenonethe request’s
aws_rds_cluster_instancedatabasebody.instance_class (string)the request’s
aws_s3_bucketobject-storenonethe request’s
aws_sns_topicqueuenonethe request’s
aws_sqs_queuequeuenonethe request’s
TypeWhy it carries no rate
Terraform::Dataa read of something that exists outside this root; whatever it reads is priced where it is declared
Terraform::Livechoudoufu’s estate declaration, which names the ownership marker every resource of the root carries and holds nothing itself
Terraform::Localsnamed expressions a root reuses; they exist only in the evaluation
Terraform::Modulea call to a child module; the blocks the call expands to are entities of their own and carry the figures
Terraform::Outputa value the root publishes after an apply, not a thing the account holds
Terraform::Providera provider configuration: how terraform reaches an account, not a thing the account holds
Terraform::Terraformthe root’s settings block, which names providers and a backend and holds nothing in any account
Terraform::Variablea root module input; it shapes what is created and is never created itself
aws_cloudwatch_event_rulepriced by the events matched, which is a fact about traffic the declaration does not state
aws_cloudwatch_log_grouppriced by the volume ingested into it, which the declaration does not state and no engine can infer from a graph
aws_db_subnet_groupthe set of subnets a database may sit in; the database carries the figures
aws_ecr_repositorypriced by the gigabytes stored in it, which the declaration does not state
aws_ecs_clustera namespace for services rather than capacity of its own; the services and their nodes carry the figures
aws_ecs_task_definitiona template a service runs copies of; the service carries the figures, and pricing both would count the estate twice
aws_eippriced only while it is attached to nothing, which is a fact about the running account rather than about the declaration
aws_elasticache_subnet_groupthe set of subnets a cache may sit in; the cache carries the figures
aws_iam_instance_profilea wrapper that hands a role to an instance; the instance carries the figures
aws_iam_policya policy document is a statement about permission; nothing about it saturates or accrues
aws_iam_rolea role is a grant, not a resource traffic flows through: no rate, no capacity, no verdict under a lost zone
aws_iam_role_policya policy document attached inline to a role; a statement about permission
aws_iam_role_policy_attachmentthe attachment of a grant to a role; neither end is priced by it
aws_internet_gatewaya boundary crossing rather than a resource: no rate of its own and no capacity to saturate
aws_kms_keypriced per key per month plus a per-request meter the declaration does not state, and neither half is an hourly rate
aws_lambda_event_source_mappingthe wiring between a queue and a function, both of which are priced where they are declared
aws_lambda_permissiona grant letting one service invoke a function; the function carries the figures
aws_launch_templatea template instances are launched from; the instances carry the figures
aws_lb_listenera port on a load balancer; the load balancer carries the rate
aws_lb_listener_rulea routing rule on a listener, and a rule is not a thing at either end of an edge
aws_lb_target_groupa set of targets behind a load balancer; the load balancer carries the rate
aws_lb_target_group_attachmentone target’s membership of a target group; the target and the load balancer carry the figures
aws_nat_gatewaypriced as an hourly rate plus a per-gigabyte meter on everything that crosses it. The declaration states the first and nothing at all about the second, and no engine kind here models a half-known price
aws_network_interfacewhere an instance’s networking lives; the instance carries the figures
aws_routerouting, which decides where an edge goes and is not itself at either end of one
aws_route53_recorda record in a zone priced per query; the zone is where the meter is, and the declaration does not state it
aws_route53_zonepriced per zone per month plus a per-query meter the declaration does not state
aws_route_tablerouting, which decides where an edge goes and is not itself at either end of one
aws_route_table_associationan association between two boundaries; nothing flows through it that does not already flow through them
aws_s3_bucket_acla grant on the bucket beside it; the bucket carries the figures
aws_s3_bucket_lifecycle_configurationa setting on the bucket beside it; the bucket carries the figures
aws_s3_bucket_ownership_controlsa setting on the bucket beside it; the bucket carries the figures
aws_s3_bucket_policya bucket policy is a grant on the bucket beside it, and the bucket carries the figures
aws_s3_bucket_public_access_blocka setting on the bucket beside it; the bucket carries the figures
aws_s3_bucket_server_side_encryption_configurationa setting on the bucket beside it; the bucket carries the figures
aws_s3_bucket_versioninga setting on the bucket beside it; the bucket carries the figures
aws_security_groupa filter on edges that already exist, not a thing at either end of one
aws_security_group_ruleone rule of a filter on edges that already exist; the rule is not a thing at either end of one
aws_sns_topic_subscriptionpriced by the notifications delivered through it; the topic is what the graph has an edge to
aws_sqs_queue_policya queue policy is a grant on the queue beside it, and the queue carries the figures
aws_subneta network boundary rather than a node: its contribution to a prediction is the zone membership that reaches the engine as containment coverage
aws_vpca network boundary rather than a node: its contribution to a prediction is the zone membership that reaches the engine as containment coverage
aws_vpc_security_group_egress_ruleone rule of a filter on edges that already exist; the rule is not a thing at either end of one
aws_vpc_security_group_ingress_ruleone rule of a filter on edges that already exist; the rule is not a thing at either end of one
aws_wafv2_web_aclpriced by the requests inspected through it, which the declaration does not state
A type with no row aboveVerdictWhat the unpredicted entry says
google_provider-not-modelledGoogle Cloud (the google terraform provider)
google-beta_provider-not-modelledGoogle Cloud (the google-beta terraform provider)
azurerm_provider-not-modelledAzure (the azurerm terraform provider)
azuread_provider-not-modelledAzure (the azuread terraform provider)
kubernetes_provider-not-modelledthe kubernetes terraform provider. The Kubernetes rows are the k8s lexicon’s own types, and a manifest applied through terraform is a different entity with a different shape
helm_provider-not-modelledHelm through terraform (a chart is a package, and what it installs is Kubernetes)
null_provider-not-modelledthe null provider, a utility with nothing in any account
random_provider-not-modelledthe random provider, a utility with nothing in any account
local_provider-not-modelledthe local provider, which writes files on the machine running terraform
tls_provider-not-modelledthe tls provider, a utility with nothing in any account
time_provider-not-modelledthe time provider, a utility with nothing in any account
archive_provider-not-modelledthe archive provider, a utility with nothing in any account
external_provider-not-modelledthe external provider, a program run on the machine running terraform
terraform_provider-not-modelledterraform’s own built-in provider, which holds nothing in any account
any other prefix, for example example_thingprovider-not-modelledthe example terraform provider, which nothing here models
any other Terraform:: typeunknown-type, the one verdict that is a defectthe entity has no row in any contributed coverage table. It is a type from a substrate that is modelled, and is neither mapped to an engine kind nor declared unmapped, so nothing has an opinion about it rather than a stated one. Add a row in the lexicon that owns Terraform::.

41 mapped and 121 declared unmapped across 3 lexicons. Any lexicon not listed here contributes no rows, so its types are unknown-type until it does.

The row belongs to the lexicon that defines the entity. A mapped row names an engine kind and, where there is one, the declared property the size is read from. A declared-unmapped row is a sentence saying why the entity carries no rate. See the behaviourKinds member in the lexicon authoring overview, then run npm run generate:behaviour-coverage and commit this page with the row.