diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 332e4784..42f91801 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -301,6 +301,34 @@ gcloud compute url-maps invalidate-cdn-cache cudly-url-map --path "/*" --- +## Archera insured-commitment comparison (optional) + +The explicit "Compare with Archera" feature is off by default. It is enabled only when all three settings are set; with none set, the platform makes no Archera request. + +| Terraform variable (environment) | Runtime setting | Meaning | +|---|---|---| +| `archera_org_id` | `ARCHERA_ORG_ID` | Archera organization UUID | +| `archera_plan_id` | `ARCHERA_PLAN_ID` | Archera commitment plan UUID (an Archera ID, not a CUDly plan ID) | +| `archera_api_key_secret_arn` (AWS), `archera_api_key_secret_id` (GCP), `archera_api_key_secret_name` (Azure) | `ARCHERA_API_KEY_SECRET` | Reference to the secret holding the Archera API key | + +Create the secret yourself, outside Terraform, so the key never enters Terraform state; Terraform only passes the reference. The platform resolves the key lazily on the first comparison request through the configured secret provider. + +Runtime access is scoped to that one secret: + +- AWS (Lambda and Fargate): `secretsmanager:GetSecretValue` on the secret ARN only. +- GCP (Cloud Run and GKE): a per-secret `roles/secretmanager.secretAccessor` binding on that secret only. +- Azure (Container Apps and AKS): no new role assignment. The secret lives in the platform Key Vault, where the runtime identity already holds the vault-wide Key Vault Secrets User role. For a secret in a different vault, add a secret-scoped role assignment for the runtime identity on that secret; narrowing the vault-wide grant is a separate owner decision. + +Required disclosures, shown verbatim wherever Archera is offered (pkg/common `ArcheraNonGatingDisclosure` and `ArcheraSponsorshipDisclosure`): + +> This is entirely optional. CUDly's purchase and management features work fully without Archera. +> +> For full disclosure, Archera sponsors CUDly's Open Source development from a fraction of their insurance premiums. + +The GCP secret variable takes the short secret ID, not the `projects//secrets/` resource name: the per-secret binding sets the project, and the full name makes the binding be replaced on every apply. + +The comparison shows Archera's own figures as returned by its API. Amounts carry no currency (Archera provides none), premiums are already included in totals, and an unknown value is shown as unknown, never as zero. Products Archera does not document as supported are shown as "not known to be supported by Archera". Nothing in this view is a guarantee or a purchase; the existing Archera disclosures stay in place. + ## Deploying Code Updates When infrastructure already exists and you only need to update application code: diff --git a/terraform/environments/aws/compute.tf b/terraform/environments/aws/compute.tf index 99cc1d95..c38f6c96 100644 --- a/terraform/environments/aws/compute.tf +++ b/terraform/environments/aws/compute.tf @@ -85,6 +85,10 @@ module "compute_lambda" { fire_scheduled_purchases_schedule = var.fire_scheduled_purchases_schedule # Additional environment variables + archera_org_id = var.archera_org_id + archera_plan_id = var.archera_plan_id + archera_api_key_secret_arn = var.archera_api_key_secret_arn + additional_env_vars = merge( { STATIC_DIR = "/app/static" @@ -208,6 +212,10 @@ module "compute_fargate" { enable_execute_command = var.fargate_enable_execute_command # Additional environment variables + archera_org_id = var.archera_org_id + archera_plan_id = var.archera_plan_id + archera_api_key_secret_arn = var.archera_api_key_secret_arn + additional_env_vars = merge( { STATIC_DIR = "/app/static" diff --git a/terraform/environments/aws/variables.tf b/terraform/environments/aws/variables.tf index 27420061..4fccc28c 100644 --- a/terraform/environments/aws/variables.tf +++ b/terraform/environments/aws/variables.tf @@ -532,3 +532,21 @@ variable "enable_docker_build" { type = bool default = true } + +variable "archera_org_id" { + description = "Archera organization UUID for the explicit insured-commitment comparison. Empty disables it." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID for the comparison. Empty disables it." + type = string + default = "" +} + +variable "archera_api_key_secret_arn" { + description = "ARN of the Secrets Manager secret holding the Archera API key (created out-of-band). Empty disables the Archera comparison." + type = string + default = "" +} diff --git a/terraform/environments/azure/compute.tf b/terraform/environments/azure/compute.tf index d8fa403d..28d6c6b7 100644 --- a/terraform/environments/azure/compute.tf +++ b/terraform/environments/azure/compute.tf @@ -79,6 +79,10 @@ module "compute_container_apps" { auto_migrate = var.auto_migrate admin_email = var.admin_email admin_password_secret_name = coalesce(module.secrets.admin_password_secret_name, "") + archera_org_id = var.archera_org_id + archera_plan_id = var.archera_plan_id + archera_api_key_secret_name = var.archera_api_key_secret_name + additional_env_vars = merge( { STATIC_DIR = "/app/static" @@ -160,9 +164,13 @@ module "compute_aks" { key_vault_uri = module.secrets.key_vault_uri # Application configuration - admin_email = var.admin_email - admin_password_secret_name = coalesce(module.secrets.admin_password_secret_name, "") - auto_migrate = var.auto_migrate + admin_email = var.admin_email + admin_password_secret_name = coalesce(module.secrets.admin_password_secret_name, "") + auto_migrate = var.auto_migrate + archera_org_id = var.archera_org_id + archera_plan_id = var.archera_plan_id + archera_api_key_secret_name = var.archera_api_key_secret_name + additional_env_vars = merge( { STATIC_DIR = "/app/static" diff --git a/terraform/environments/azure/variables.tf b/terraform/environments/azure/variables.tf index 522b5d76..6faa1a6a 100644 --- a/terraform/environments/azure/variables.tf +++ b/terraform/environments/azure/variables.tf @@ -558,3 +558,21 @@ variable "max_account_parallelism" { type = number default = 10 } + +variable "archera_org_id" { + description = "Archera organization UUID for the explicit insured-commitment comparison. Empty disables it." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID for the comparison. Empty disables it." + type = string + default = "" +} + +variable "archera_api_key_secret_name" { + description = "Name of the platform Key Vault secret holding the Archera API key (created out-of-band). Empty disables the Archera comparison." + type = string + default = "" +} diff --git a/terraform/environments/gcp/compute.tf b/terraform/environments/gcp/compute.tf index d0289d2b..0ea7fd99 100644 --- a/terraform/environments/gcp/compute.tf +++ b/terraform/environments/gcp/compute.tf @@ -102,6 +102,10 @@ module "compute_cloud_run" { billing_account_id = var.billing_account_id # Additional environment variables + archera_org_id = var.archera_org_id + archera_plan_id = var.archera_plan_id + archera_api_key_secret_id = var.archera_api_key_secret_id + additional_env_vars = merge( { STATIC_DIR = "/app/static" @@ -183,6 +187,10 @@ module "compute_gke" { credential_encryption_key = module.secrets.credential_encryption_key_secret_id } + archera_org_id = var.archera_org_id + archera_plan_id = var.archera_plan_id + archera_api_key_secret_id = var.archera_api_key_secret_id + additional_env_vars = merge( { STATIC_DIR = "/app/static" diff --git a/terraform/environments/gcp/variables.tf b/terraform/environments/gcp/variables.tf index c2ee9e77..52c69166 100644 --- a/terraform/environments/gcp/variables.tf +++ b/terraform/environments/gcp/variables.tf @@ -499,3 +499,21 @@ variable "max_account_parallelism" { type = number default = 10 } + +variable "archera_org_id" { + description = "Archera organization UUID for the explicit insured-commitment comparison. Empty disables it." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID for the comparison. Empty disables it." + type = string + default = "" +} + +variable "archera_api_key_secret_id" { + description = "Short Secret Manager secret ID (not the full resource name) holding the Archera API key (created out-of-band). Empty disables the Archera comparison." + type = string + default = "" +} diff --git a/terraform/modules/compute/aws/fargate/main.tf b/terraform/modules/compute/aws/fargate/main.tf index 546dc44b..2898d6dc 100644 --- a/terraform/modules/compute/aws/fargate/main.tf +++ b/terraform/modules/compute/aws/fargate/main.tf @@ -158,6 +158,8 @@ resource "aws_iam_role_policy" "task_secrets" { var.credential_encryption_key_secret_arn != "" ? "${var.credential_encryption_key_secret_arn}*" : "", var.scheduled_task_secret_arn, var.scheduled_task_secret_arn != "" ? "${var.scheduled_task_secret_arn}*" : "", + var.archera_api_key_secret_arn, + var.archera_api_key_secret_arn != "" ? "${var.archera_api_key_secret_arn}*" : "", ]) }, { @@ -645,6 +647,12 @@ resource "aws_ecs_task_definition" "main" { value = var.scheduled_task_secret_name } ], + [ + for k, v in local.archera_env : { + name = k + value = v + } + ], [ for k, v in var.additional_env_vars : { name = k @@ -1263,3 +1271,13 @@ resource "aws_iam_role_policy" "eventbridge_fire_scheduled_purchases" { ] }) } + +locals { + # Archera settings, set only when non-empty so an unconfigured deployment + # carries no ARCHERA_* variable at all (feature off). + archera_env = merge( + var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {}, + var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {}, + var.archera_api_key_secret_arn != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_arn } : {}, + ) +} diff --git a/terraform/modules/compute/aws/fargate/variables.tf b/terraform/modules/compute/aws/fargate/variables.tf index 48d11c70..643a4e30 100644 --- a/terraform/modules/compute/aws/fargate/variables.tf +++ b/terraform/modules/compute/aws/fargate/variables.tf @@ -327,3 +327,24 @@ variable "email_from_domain" { type = string default = "" } + +# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md). +# All three must be set for the feature to be configured; the key itself is never +# managed here, the operator creates the secret out-of-band. +variable "archera_org_id" { + description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_api_key_secret_arn" { + description = "ARN of the Secrets Manager secret holding the Archera API key. Passed as ARCHERA_API_KEY_SECRET and granted GetSecretValue on this one secret only. Empty disables the comparison." + type = string + default = "" +} diff --git a/terraform/modules/compute/aws/lambda/main.tf b/terraform/modules/compute/aws/lambda/main.tf index 2942497c..6210d4f5 100644 --- a/terraform/modules/compute/aws/lambda/main.tf +++ b/terraform/modules/compute/aws/lambda/main.tf @@ -90,6 +90,7 @@ resource "aws_lambda_function" "main" { var.purchase_approved_reap_after != "" ? { PURCHASE_APPROVED_REAP_AFTER = var.purchase_approved_reap_after } : {}, + local.archera_env, var.additional_env_vars ) } @@ -260,6 +261,8 @@ resource "aws_iam_role_policy" "secrets_access" { var.credential_encryption_key_secret_arn != "" ? "${var.credential_encryption_key_secret_arn}*" : "", var.scheduled_task_secret_arn, var.scheduled_task_secret_arn != "" ? "${var.scheduled_task_secret_arn}*" : "", + var.archera_api_key_secret_arn, + var.archera_api_key_secret_arn != "" ? "${var.archera_api_key_secret_arn}*" : "", ]) }, { @@ -801,3 +804,13 @@ resource "aws_lambda_permission" "eventbridge_fire_scheduled_purchases" { principal = "events.amazonaws.com" source_arn = aws_cloudwatch_event_rule.fire_scheduled_purchases[0].arn } + +locals { + # Archera settings, set only when non-empty so an unconfigured deployment + # carries no ARCHERA_* variable at all (feature off). + archera_env = merge( + var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {}, + var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {}, + var.archera_api_key_secret_arn != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_arn } : {}, + ) +} diff --git a/terraform/modules/compute/aws/lambda/variables.tf b/terraform/modules/compute/aws/lambda/variables.tf index d0d1d5de..908cc2ce 100644 --- a/terraform/modules/compute/aws/lambda/variables.tf +++ b/terraform/modules/compute/aws/lambda/variables.tf @@ -307,3 +307,24 @@ variable "tags" { type = map(string) default = {} } + +# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md). +# All three must be set for the feature to be configured; the key itself is never +# managed here, the operator creates the secret out-of-band. +variable "archera_org_id" { + description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_api_key_secret_arn" { + description = "ARN of the Secrets Manager secret holding the Archera API key. Passed as ARCHERA_API_KEY_SECRET and granted GetSecretValue on this one secret only. Empty disables the comparison." + type = string + default = "" +} diff --git a/terraform/modules/compute/azure/aks/main.tf b/terraform/modules/compute/azure/aks/main.tf index 96ddf4ba..685fecc7 100644 --- a/terraform/modules/compute/azure/aks/main.tf +++ b/terraform/modules/compute/azure/aks/main.tf @@ -419,6 +419,14 @@ resource "kubernetes_deployment" "app" { value = "bearer" } + dynamic "env" { + for_each = local.archera_env + content { + name = env.key + value = env.value + } + } + dynamic "env" { for_each = var.additional_env_vars content { @@ -780,3 +788,13 @@ data "kubernetes_service" "nginx_ingress" { time_sleep.wait_for_lb_ip, ] } + +locals { + # Archera settings, set only when non-empty so an unconfigured deployment + # carries no ARCHERA_* variable at all (feature off). + archera_env = merge( + var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {}, + var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {}, + var.archera_api_key_secret_name != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_name } : {}, + ) +} diff --git a/terraform/modules/compute/azure/aks/variables.tf b/terraform/modules/compute/azure/aks/variables.tf index 9e8ec88c..435e523a 100644 --- a/terraform/modules/compute/azure/aks/variables.tf +++ b/terraform/modules/compute/azure/aks/variables.tf @@ -208,3 +208,24 @@ variable "admin_group_object_ids" { type = list(string) default = [] } + +# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md). +# All three must be set for the feature to be configured; the key itself is never +# managed here, the operator creates the secret out-of-band. +variable "archera_org_id" { + description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_api_key_secret_name" { + description = "Name of the Key Vault secret holding the Archera API key, passed as ARCHERA_API_KEY_SECRET. The secret lives in the platform vault, where the runtime identity already holds the vault-wide Key Vault Secrets User role, so no role assignment is added here. Empty disables the comparison." + type = string + default = "" +} diff --git a/terraform/modules/compute/azure/container-apps/main.tf b/terraform/modules/compute/azure/container-apps/main.tf index a48170d5..c84c3540 100644 --- a/terraform/modules/compute/azure/container-apps/main.tf +++ b/terraform/modules/compute/azure/container-apps/main.tf @@ -141,6 +141,7 @@ resource "azurerm_container_app" "main" { # not emit on the HTTP Connector trigger we use. SCHEDULED_TASK_AUTH_MODE = "bearer" }, + local.archera_env, var.additional_env_vars ) content { @@ -343,3 +344,13 @@ resource "azurerm_monitor_diagnostic_setting" "container_app" { enabled = true } } + +locals { + # Archera settings, set only when non-empty so an unconfigured deployment + # carries no ARCHERA_* variable at all (feature off). + archera_env = merge( + var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {}, + var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {}, + var.archera_api_key_secret_name != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_name } : {}, + ) +} diff --git a/terraform/modules/compute/azure/container-apps/variables.tf b/terraform/modules/compute/azure/container-apps/variables.tf index f604c27a..c605deb7 100644 --- a/terraform/modules/compute/azure/container-apps/variables.tf +++ b/terraform/modules/compute/azure/container-apps/variables.tf @@ -258,3 +258,24 @@ variable "ri_exchange_schedule" { type = string default = "0 */6 * * *" } + +# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md). +# All three must be set for the feature to be configured; the key itself is never +# managed here, the operator creates the secret out-of-band. +variable "archera_org_id" { + description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_api_key_secret_name" { + description = "Name of the Key Vault secret holding the Archera API key, passed as ARCHERA_API_KEY_SECRET. The secret lives in the platform vault, where the runtime identity already holds the vault-wide Key Vault Secrets User role, so no role assignment is added here. Empty disables the comparison." + type = string + default = "" +} diff --git a/terraform/modules/compute/gcp/cloud-run/main.tf b/terraform/modules/compute/gcp/cloud-run/main.tf index 19f458ba..c63329a9 100644 --- a/terraform/modules/compute/gcp/cloud-run/main.tf +++ b/terraform/modules/compute/gcp/cloud-run/main.tf @@ -173,6 +173,7 @@ resource "google_cloud_run_v2_service" "main" { SCHEDULED_TASK_OIDC_AUDIENCE = local.scheduled_task_oidc_audiences SCHEDULED_TASK_OIDC_SUBJECTS = local.scheduled_task_oidc_subjects }, + local.archera_env, var.additional_env_vars ) content { @@ -521,3 +522,23 @@ resource "google_logging_project_bucket_config" "cloud_run_logs" { retention_days = var.log_retention_days bucket_id = "_Default" } + +locals { + # Archera settings, set only when non-empty so an unconfigured deployment + # carries no ARCHERA_* variable at all (feature off). + archera_env = merge( + var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {}, + var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {}, + var.archera_api_key_secret_id != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_id } : {}, + ) +} + +# Archera API key: one per-secret reader, only when configured. +resource "google_secret_manager_secret_iam_member" "archera_key_reader" { + count = var.archera_api_key_secret_id != "" ? 1 : 0 + + project = var.project_id + secret_id = var.archera_api_key_secret_id + role = "roles/secretmanager.secretAccessor" + member = "serviceAccount:${google_service_account.cloud_run.email}" +} diff --git a/terraform/modules/compute/gcp/cloud-run/variables.tf b/terraform/modules/compute/gcp/cloud-run/variables.tf index cc054ce4..065fb5af 100644 --- a/terraform/modules/compute/gcp/cloud-run/variables.tf +++ b/terraform/modules/compute/gcp/cloud-run/variables.tf @@ -250,3 +250,28 @@ variable "labels" { type = map(string) default = {} } + +# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md). +# All three must be set for the feature to be configured; the key itself is never +# managed here, the operator creates the secret out-of-band. +variable "archera_org_id" { + description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_api_key_secret_id" { + validation { + condition = !strcontains(var.archera_api_key_secret_id, "/") + error_message = "archera_api_key_secret_id must be the short secret ID, not a projects//secrets/ resource name (the per-secret IAM binding sets project and would be replaced on every apply otherwise)." + } + description = "Short Secret Manager secret ID (not the projects//secrets/ resource name) holding the Archera API key. Passed as ARCHERA_API_KEY_SECRET and bound with a per-secret secretAccessor grant on this one secret only. Empty disables the comparison." + type = string + default = "" +} diff --git a/terraform/modules/compute/gcp/gke/main.tf b/terraform/modules/compute/gcp/gke/main.tf index 61534b33..86bee1d5 100644 --- a/terraform/modules/compute/gcp/gke/main.tf +++ b/terraform/modules/compute/gcp/gke/main.tf @@ -557,6 +557,14 @@ resource "kubernetes_deployment" "app" { value = local.scheduled_task_oidc_subject } + dynamic "env" { + for_each = local.archera_env + content { + name = env.key + value = env.value + } + } + dynamic "env" { for_each = var.additional_env_vars content { @@ -810,3 +818,23 @@ resource "google_service_account" "scheduler" { display_name = "Cloud Scheduler service account for GKE ${var.project_name}" project = var.project_id } + +locals { + # Archera settings, set only when non-empty so an unconfigured deployment + # carries no ARCHERA_* variable at all (feature off). + archera_env = merge( + var.archera_org_id != "" ? { ARCHERA_ORG_ID = var.archera_org_id } : {}, + var.archera_plan_id != "" ? { ARCHERA_PLAN_ID = var.archera_plan_id } : {}, + var.archera_api_key_secret_id != "" ? { ARCHERA_API_KEY_SECRET = var.archera_api_key_secret_id } : {}, + ) +} + +# Archera API key: one per-secret reader, only when configured. +resource "google_secret_manager_secret_iam_member" "archera_key_reader" { + count = var.archera_api_key_secret_id != "" ? 1 : 0 + + project = local.secret_project_id + secret_id = var.archera_api_key_secret_id + role = "roles/secretmanager.secretAccessor" + member = "serviceAccount:${google_service_account.workload.email}" +} diff --git a/terraform/modules/compute/gcp/gke/variables.tf b/terraform/modules/compute/gcp/gke/variables.tf index a0a3f894..28e34d56 100644 --- a/terraform/modules/compute/gcp/gke/variables.tf +++ b/terraform/modules/compute/gcp/gke/variables.tf @@ -363,3 +363,28 @@ variable "master_authorized_networks" { error_message = "master_authorized_networks must not contain 0.0.0.0/0; that reopens the control plane's public endpoint to the whole internet, exactly what this allowlist exists to prevent." } } + +# Archera insured-commitment comparison (default off; see the Archera section of docs/DEPLOYMENT.md). +# All three must be set for the feature to be configured; the key itself is never +# managed here, the operator creates the secret out-of-band. +variable "archera_org_id" { + description = "Archera organization UUID, passed as ARCHERA_ORG_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_plan_id" { + description = "Archera commitment plan UUID, passed as ARCHERA_PLAN_ID. Empty disables the comparison." + type = string + default = "" +} + +variable "archera_api_key_secret_id" { + validation { + condition = !strcontains(var.archera_api_key_secret_id, "/") + error_message = "archera_api_key_secret_id must be the short secret ID, not a projects//secrets/ resource name (the per-secret IAM binding sets project and would be replaced on every apply otherwise)." + } + description = "Short Secret Manager secret ID (not the projects//secrets/ resource name) holding the Archera API key. Passed as ARCHERA_API_KEY_SECRET and bound with a per-secret secretAccessor grant on this one secret only. Empty disables the comparison." + type = string + default = "" +}