carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1# deployment-buckets: the durable heart of a CARLOS deployment — the
2# deployment bucket (apps, releases, channels, instance records, host
3# config; routing metadata only, nothing customer-shaped) paired with one
4# regional data bucket (parked databases, WAL streams, leases, blobs —
5# the residency promise). Boxes are disposable; these buckets are not,
6# hence prevent_destroy, versioning, SSE, and a full public-access block
7# on both.
8
9# The deployment bucket: apps, releases, channels, instance records, host
10# config. Routing metadata only — nothing customer-shaped rests here.
11resource "aws_s3_bucket" "deployment" {
12 bucket = var.deployment_bucket_name
13 lifecycle { prevent_destroy = true }
14}
15
16# The regional data bucket: parked databases, WAL streams, leases, blobs.
17# This bucket is the residency promise.
18resource "aws_s3_bucket" "data" {
19 bucket = var.data_bucket_name
20 lifecycle { prevent_destroy = true }
21}
22
23resource "aws_s3_bucket_versioning" "deployment" {
24 bucket = aws_s3_bucket.deployment.id
25 versioning_configuration { status = "Enabled" }
26}
27
28# GeoIP databases (platform geoip spec 2026-10-06 §15 step 0, D1): a deleted
29# or superseded blob under control/geoip/ must not live on as a noncurrent
30# version, because MaxMind's GeoLite EULA requires destroying superseded
31# editions. Forwarded db reads (db region forward spec §5.7, J4): every
32# object under db-reads/ expires. Each rule is scoped to its own prefix;
33# nothing else in this bucket expires.
34resource "aws_s3_bucket_lifecycle_configuration" "deployment" {
35 bucket = aws_s3_bucket.deployment.id
36
37 rule {
38 id = "geoip-noncurrent"
39 status = "Enabled"
40 filter {
41 prefix = "control/geoip/"
42 }
43 noncurrent_version_expiration {
44 noncurrent_days = 1
45 }
46 abort_incomplete_multipart_upload {
47 days_after_initiation = 1
48 }
49 }
50
51 # Forwarded db reads (db region forward spec §5.7, J4): every object under
52 # db-reads/ (requests, queue entries, picked markers, sealed chunks,
53 # results, cancels) expires a day after it is written, each noncurrent
54 # version a day after it becomes noncurrent, and expired delete markers
55 # go. The protocol deletes nothing, so these rules are its only deletion;
56 # a read's ciphertext lives until they act, typically two to four days.
57 rule {
58 id = "db-reads-expire"
59 status = "Enabled"
60 filter {
61 prefix = "db-reads/"
62 }
63 expiration {
64 days = 1
65 }
66 noncurrent_version_expiration {
67 noncurrent_days = 1
68 }
69 abort_incomplete_multipart_upload {
70 days_after_initiation = 1
71 }
72 }
73
74 # S3 refuses an expired-object-delete-marker expiration beside days in one
75 # rule, so the markers have a rule of their own.
76 rule {
77 id = "db-reads-delete-markers"
78 status = "Enabled"
79 filter {
80 prefix = "db-reads/"
81 }
82 expiration {
83 expired_object_delete_marker = true
84 }
85 }
86
87 depends_on = [aws_s3_bucket_versioning.deployment]
88}
89
90resource "aws_s3_bucket_versioning" "data" {
91 bucket = aws_s3_bucket.data.id
92 versioning_configuration { status = "Enabled" }
93}
94
95resource "aws_s3_bucket_public_access_block" "deployment" {
96 bucket = aws_s3_bucket.deployment.id
97 block_public_acls = true
98 ignore_public_acls = true
99 block_public_policy = true
100 restrict_public_buckets = true
101}
102
103resource "aws_s3_bucket_public_access_block" "data" {
104 bucket = aws_s3_bucket.data.id
105 block_public_acls = true
106 ignore_public_acls = true
107 block_public_policy = true
108 restrict_public_buckets = true
109}
110
111resource "aws_s3_bucket_server_side_encryption_configuration" "deployment" {
112 bucket = aws_s3_bucket.deployment.id
113 rule {
114 apply_server_side_encryption_by_default { sse_algorithm = "AES256" }
115 }
116}
117
118resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
119 bucket = aws_s3_bucket.data.id
120 rule {
121 apply_server_side_encryption_by_default { sse_algorithm = "AES256" }
122 }
123}
124
125# --- Box evidence (region HA spec 1 §5.1, §5.9, §6) ------------------------
126# control/boxes/<ref>.json is a box's AWS-signed identity, the evidence its
127# enrollment reads. control/box-volumes/, control/box-enrollment/ and
128# control/box-fences/ are the volume records, membership confirmations
129# and termination fence records regional workers write. Every one is
130# written once and never changed or deleted. Storage enforces that, so no
131# bug or stolen box credential can rewrite the evidence behind a decision.
132# (control/boxes/*.bind.json is no longer written: enrollment replaced the
133# operator bind. Its statement stays harmless until operator_role_arns is
134# retired with it.)
135#
136# EVERY statement here names one of these prefixes and nothing wider. A
137# broad Deny on this bucket has broken lease releases before.
138
139locals {
140 box_evidence_prefixes = ["control/boxes", "control/box-volumes", "control/box-enrollment", "control/box-fences"]
141}
142
143resource "aws_s3_bucket_policy" "deployment_box_records" {
144 bucket = aws_s3_bucket.deployment.id
145 depends_on = [aws_s3_bucket_public_access_block.deployment]
146 policy = jsonencode({
147 Version = "2012-10-17"
148 Statement = [
149 {
150 # Evidence may be created, never replaced. The qualifier leaves
151 # multipart preparation alone and still covers its completion.
152 Sid = "BoxRecordsAreCreateOnly"
153 Effect = "Deny"
154 Principal = "*"
155 Action = "s3:PutObject"
156 Resource = [for p in local.box_evidence_prefixes : "${aws_s3_bucket.deployment.arn}/${p}/*"]
157 Condition = {
158 Null = { "s3:if-none-match" = "true" }
159 Bool = { "s3:ObjectCreationOperation" = "true" }
160 }
161 },
162 {
163 Sid = "BoxRecordsAreNeverDeleted"
164 Effect = "Deny"
165 Principal = "*"
166 Action = ["s3:DeleteObject", "s3:DeleteObjectVersion"]
167 Resource = [for p in local.box_evidence_prefixes : "${aws_s3_bucket.deployment.arn}/${p}/*"]
168 },
169 {
170 Sid = "OnlyBoxRolesWriteTerminationFences"
171 Effect = "Deny"
172 Principal = "*"
173 Action = "s3:PutObject"
174 Resource = "${aws_s3_bucket.deployment.arn}/control/box-fences/*"
175 Condition = {
176 ArnNotEquals = {
177 "aws:PrincipalArn" = length(var.box_fence_writer_role_arns) > 0 ? var.box_fence_writer_role_arns : ["arn:aws:iam::000000000000:role/nobody"]
178 }
179 }
180 },
181 {
182 # With no operators named, the list is one ARN nobody has, so the
183 # Deny covers everyone.
184 Sid = "OnlyOperatorsWriteBinds"
185 Effect = "Deny"
186 Principal = "*"
187 Action = "s3:PutObject"
188 Resource = "${aws_s3_bucket.deployment.arn}/control/boxes/*.bind.json"
189 Condition = {
190 ArnNotLike = {
191 "aws:PrincipalArn" = length(var.operator_role_arns) > 0 ? var.operator_role_arns : ["arn:aws:iam::000000000000:role/nobody"]
192 }
193 }
194 },
195 ]
196 })
197}
198