unoverse 0.1.126 → 0.1.128

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -271,6 +271,28 @@ resource "aws_instance" "app" {
271
271
  volume_type = "gp3"
272
272
  }
273
273
 
274
+ # IMDSv2 REQUIRED, and this is not optional in a governed account.
275
+ #
276
+ # AWS's own recommended guardrail denies ec2:RunInstances unless the launch enforces
277
+ # IMDSv2, and organisations apply it as a Service Control Policy. Without this block the
278
+ # AWS default is `optional`, the condition is not met, and the deny fires:
279
+ #
280
+ # UnauthorizedOperation ... ec2:RunInstances ... with an explicit deny in a service
281
+ # control policy
282
+ #
283
+ # That error names no condition, so it reads as "EC2 is banned here" and sends you to your
284
+ # cloud team for a policy change you do not need. The condition is visible only by
285
+ # decoding the failure message (`aws sts decode-authorization-message`), which showed
286
+ # `ec2:MetadataHttpTokens = required`. Proved by dry run 2026-08-06: identical launch
287
+ # refused without this block, accepted with it.
288
+ #
289
+ # It is the right default everywhere regardless. IMDSv1 lets any process that can forge a
290
+ # simple GET read the instance's credentials; IMDSv2 requires a signed token first.
291
+ metadata_options {
292
+ http_endpoint = "enabled"
293
+ http_tokens = "required"
294
+ }
295
+
274
296
  tags = { Name = "${var.name}-app" }
275
297
  }
276
298
 
@@ -578,21 +600,50 @@ resource "aws_cognito_user_pool_domain" "domain" {
578
600
  # NOTE: the secret lands in Terraform state — acceptable at POC, noted in the doc.
579
601
  # Model ACCESS is enabled in the console per model/region, outside Terraform.
580
602
 
603
+ # OPTIONAL, because it is the only thing here that needs IAM write and nothing reads it.
604
+ #
605
+ # The platform never uses these keys. They exist as OUTPUTS, for a developer to paste into
606
+ # the Credentials UI, exactly as they would an OpenAI key. So a universe that does not use
607
+ # the Bedrock nodes was minting a permanent access key for nobody, and paying for it in the
608
+ # one place that matters: `iam:CreateUser` is excluded from AWS's PowerUserAccess policy, so
609
+ # in any managed account this single resource turns a working deploy into a request to
610
+ # somebody's cloud team.
611
+ #
612
+ # DEFAULT TRUE, deliberately. Flipping it to false would DESTROY the user and key in every
613
+ # universe that already has one, and silently break Bedrock for anyone who had pasted those
614
+ # keys into a credential. Set it false where IAM write is not delegated.
581
615
  resource "aws_iam_user" "bedrock" {
582
- name = "${var.name}-bedrock-invoke"
616
+ count = var.bedrock_credentials ? 1 : 0
617
+ name = "${var.name}-bedrock-invoke"
583
618
  }
584
619
 
585
620
  resource "aws_iam_user_policy" "bedrock" {
586
- name = "bedrock-invoke-only"
587
- user = aws_iam_user.bedrock.name
621
+ count = var.bedrock_credentials ? 1 : 0
622
+ name = "bedrock-invoke-only"
623
+ user = aws_iam_user.bedrock[0].name
588
624
  policy = jsonencode({
589
625
  Version = "2012-10-17"
590
626
  Statement = [{
591
627
  Effect = "Allow"
628
+ # WIDE ON RUNTIME, silent on spending.
629
+ #
630
+ # Three named Invoke actions dated fast. `Converse` is the current unified API and the
631
+ # Bedrock nodes already call it; `ApplyGuardrail` is a separate action the guardrail
632
+ # node needs; knowledge bases add `Retrieve`. Each arrival meant editing this list,
633
+ # re-applying, and in a managed account asking an administrator again.
634
+ #
635
+ # NOT `bedrock:*`. That includes CreateProvisionedModelThroughput, which commits money.
636
+ # Everything below is invoke-and-read: it cannot buy capacity, and it cannot create or
637
+ # delete a model or a guardrail.
638
+ #
639
+ # Model access is still granted per model in the Bedrock console. No policy grants it.
592
640
  Action = [
593
- "bedrock:InvokeModel",
594
- "bedrock:InvokeModelWithResponseStream",
595
- "bedrock:InvokeModelWithBidirectionalStream",
641
+ "bedrock:InvokeModel*",
642
+ "bedrock:Converse*",
643
+ "bedrock:ApplyGuardrail",
644
+ "bedrock:Retrieve*",
645
+ "bedrock:List*",
646
+ "bedrock:Get*",
596
647
  ]
597
648
  Resource = "*"
598
649
  }]
@@ -600,7 +651,8 @@ resource "aws_iam_user_policy" "bedrock" {
600
651
  }
601
652
 
602
653
  resource "aws_iam_access_key" "bedrock" {
603
- user = aws_iam_user.bedrock.name
654
+ count = var.bedrock_credentials ? 1 : 0
655
+ user = aws_iam_user.bedrock[0].name
604
656
  }
605
657
 
606
658
  # ── Native ingress (2026-07-29): ONE ALB, host-routed — the thing DO's LB can't
@@ -71,12 +71,12 @@ output "cognito_hosted_ui" {
71
71
 
72
72
  output "bedrock_access_key_id" {
73
73
  description = "Store as a platform awsCredential (accessKeyId) for the Bedrock/Nova nodes"
74
- value = aws_iam_access_key.bedrock.id
74
+ value = one(aws_iam_access_key.bedrock[*].id)
75
75
  }
76
76
 
77
77
  output "bedrock_secret_access_key" {
78
78
  description = "Store as a platform awsCredential (secretAccessKey)"
79
- value = aws_iam_access_key.bedrock.secret
79
+ value = one(aws_iam_access_key.bedrock[*].secret)
80
80
  sensitive = true
81
81
  }
82
82
 
@@ -117,3 +117,16 @@ variable "operator_public_key" {
117
117
  type = string
118
118
  default = ""
119
119
  }
120
+
121
+ # Whether to create the Bedrock IAM user and access key (main.tf, "Bedrock").
122
+ #
123
+ # TRUE preserves what every existing universe already has. FALSE skips the only resource
124
+ # here that needs IAM write, which is what makes a deploy possible in an account where
125
+ # `iam:CreateUser` is not delegated. Nothing in the platform reads the keys: they are
126
+ # outputs, for pasting into a credential, so switching this off costs a manual step and
127
+ # nothing else.
128
+ variable "bedrock_credentials" {
129
+ type = bool
130
+ default = true
131
+ description = "Create an IAM user and access key for the Bedrock nodes. Set false where IAM write is not delegated."
132
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unoverse",
3
- "version": "0.1.126",
3
+ "version": "0.1.128",
4
4
  "description": "The Unoverse front door — create a Studio project, a universe, or a client app, and launch Studio.",
5
5
  "license": "SEE LICENSE IN README.md",
6
6
  "type": "module",