From bff0f446356fdcd565a11db65b19d1921e4b0f6b Mon Sep 17 00:00:00 2001 From: Steven Welch Date: Sat, 5 Sep 2026 11:07:51 -0600 Subject: [PATCH 1/4] feat(aws): add xnoto.dev website publisher --- aws-github-oidc.tf | 60 ++++++++++++++++++++++++++++++++++++++++++++++ main.tf | 1 + outputs.tf | 7 +++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/aws-github-oidc.tf b/aws-github-oidc.tf index c793498..cb73207 100644 --- a/aws-github-oidc.tf +++ b/aws-github-oidc.tf @@ -406,3 +406,63 @@ resource "aws_iam_role_policy" "github_actions_channel_project_site_deploy" { ] }) } + +# Site publication is separate from infrastructure management and is trusted +# only from xnoto.dev's main branch. It can publish assets but cannot manage +# state, infrastructure resources, or CloudFront distributions. +resource "aws_iam_role" "github_actions_xnoto_dev_site_deploy" { + name = "github-actions-xnoto-dev-site-deploy" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Federated = aws_iam_openid_connect_provider.github_actions.arn + } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" + "token.actions.githubusercontent.com:sub" = "repo:xnoto@121333299/xnoto.dev@1358381234:ref:refs/heads/main" + } + } + } + ] + }) + + tags = { + ManagedBy = "Terraform" + Purpose = "xnoto-dev-site-deployment" + } +} + +resource "aws_iam_role_policy" "github_actions_xnoto_dev_site_deploy" { + name = "xnoto-dev-site-deployment" + role = aws_iam_role.github_actions_xnoto_dev_site_deploy.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "ListSiteAssetBucket" + Effect = "Allow" + Action = ["s3:ListBucket"] + Resource = "arn:aws:s3:::xnoto.dev" + }, + { + Sid = "PublishSiteAssets" + Effect = "Allow" + Action = [ + "s3:AbortMultipartUpload", + "s3:DeleteObject", + "s3:GetObject", + "s3:ListMultipartUploadParts", + "s3:PutObject" + ] + Resource = "arn:aws:s3:::xnoto.dev/*" + } + ] + }) +} diff --git a/main.tf b/main.tf index 23d5a13..581ec3e 100644 --- a/main.tf +++ b/main.tf @@ -30,5 +30,6 @@ locals { "makeitwork.cloud", "onion.makeitwork.cloud", "orthodox.channel", + "xnoto.dev", ]) } diff --git a/outputs.tf b/outputs.tf index 7d97b37..08789bf 100644 --- a/outputs.tf +++ b/outputs.tf @@ -54,6 +54,11 @@ output "channel_project_site_deploy_role_arn" { value = aws_iam_role.github_actions_channel_project_site_deploy.arn } +output "xnoto_dev_site_deploy_role_arn" { + description = "GitHub OIDC role for publishing xnoto.dev static-site assets from main" + value = aws_iam_role.github_actions_xnoto_dev_site_deploy.arn +} + output "twilio_state_bucket_name" { description = "Versioned private S3 bucket for tfroot-twilio OpenTofu state" value = aws_s3_bucket.private[local.twilio_state_bucket].bucket @@ -103,7 +108,7 @@ output "bedrock_opencode_access_key" { } output "bedrock_opencode_iam_user_arn" { - description = "IAM user ARN for OpenCode Bedrock access" + description = "IAM user ARN for OpenCode to invoke Anthropic models via Bedrock" value = aws_iam_user.bedrock_opencode.arn } From 7b43c8845cb44770526e1cb61904b0e4b846ef4d Mon Sep 17 00:00:00 2001 From: Steven Welch Date: Sat, 5 Sep 2026 11:08:31 -0600 Subject: [PATCH 2/4] fix(aws): preserve existing output wording --- outputs.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/outputs.tf b/outputs.tf index 08789bf..1c7920c 100644 --- a/outputs.tf +++ b/outputs.tf @@ -94,7 +94,7 @@ output "sops_secrets_operator_access_key" { } output "sops_secrets_operator_iam_user_arn" { - description = "IAM user ARN for the k3s sops-secrets-operator" + description = "IAM user ARN for the sops-secrets-operator" value = aws_iam_user.sops_secrets_operator.arn } @@ -108,7 +108,7 @@ output "bedrock_opencode_access_key" { } output "bedrock_opencode_iam_user_arn" { - description = "IAM user ARN for OpenCode to invoke Anthropic models via Bedrock" + description = "IAM user ARN for OpenCode Bedrock access" value = aws_iam_user.bedrock_opencode.arn } From 2d5da6afd16e95232819f2f03f64b8ae96e1fce9 Mon Sep 17 00:00:00 2001 From: Steven Welch Date: Sat, 5 Sep 2026 11:09:08 -0600 Subject: [PATCH 3/4] fix(aws): preserve existing output description --- outputs.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outputs.tf b/outputs.tf index 1c7920c..2e69e88 100644 --- a/outputs.tf +++ b/outputs.tf @@ -94,7 +94,7 @@ output "sops_secrets_operator_access_key" { } output "sops_secrets_operator_iam_user_arn" { - description = "IAM user ARN for the sops-secrets-operator" + description = "IAM user ARN for the k3s sops-secrets-operator" value = aws_iam_user.sops_secrets_operator.arn } From c092a90c6619190bc58cba2c5669d864687e5015 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 5 Sep 2026 17:11:10 +0000 Subject: [PATCH 4/4] chore: apply pre-commit fixes --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4afa6ae..867cc3a 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ No modules. | [aws_iam_role.github_actions_channel_project_state](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.github_actions_sops_kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.github_actions_twilio_state](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.github_actions_xnoto_dev_site_deploy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.opencode_mcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.bedrock_batch_invoke](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.bedrock_batch_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | @@ -43,6 +44,7 @@ No modules. | [aws_iam_role_policy.github_actions_channel_project_state](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.github_actions_sops_kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.github_actions_twilio_state](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.github_actions_xnoto_dev_site_deploy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.opencode_mcp_agent_pipe](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.opencode_mcp_secrets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy_attachment.opencode_mcp_oauth](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | @@ -111,6 +113,7 @@ No inputs. | [twilio\_github\_actions\_state\_role\_arn](#output\_twilio\_github\_actions\_state\_role\_arn) | GitHub OIDC role for tfroot-twilio OpenTofu state and SOPS decrypt access | | [twilio\_state\_bucket\_name](#output\_twilio\_state\_bucket\_name) | Versioned private S3 bucket for tfroot-twilio OpenTofu state | | [web\_bucket\_endpoints](#output\_web\_bucket\_endpoints) | Website endpoints for public web S3 buckets | +| [xnoto\_dev\_site\_deploy\_role\_arn](#output\_xnoto\_dev\_site\_deploy\_role\_arn) | GitHub OIDC role for publishing xnoto.dev static-site assets from main | ## AWS Bedrock batch inference (50% discount)