carlos / platform Public

geo: AWS region table with approved place names (nearest-region §14)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev cc82bc0f67687a6aa7012a500d347da0ccea0995 parent b0b2d50
2 files changed, +172 −0
  • internal/geo/awsregions.go +77 −0
  • internal/geo/awsregions_test.go +95 −0
diff --git a/internal/geo/awsregions.go b/internal/geo/awsregions.go
new file mode 100644
index 000000000..8fc5671ac
--- /dev/null
+++ b/internal/geo/awsregions.go
@@ -0,0 +1,77 @@
+package geo
+
+// AWSRegion is one AWS commercial region's metro-area point and the place
+// name every surface shows for it (spec §14, copy C23 as approved in the
+// nearest-region copy record).
+//
+// Source: AWS's official region list
+// (https://docs.aws.amazon.com/global-infrastructure/latest/regions/aws-regions.html)
+// as of 2026-10-01. Coordinates are each region's metro area, checked by
+// hand; AWS publishes no facility locations, and tens of kilometres never
+// change a choice between regions.
+type AWSRegion struct {
+ Point
+ Place string
+}
+
+var awsRegions = map[string]AWSRegion{
+ "us-east-1": {Point{39.04, -77.49}, "US East · N. Virginia"},
+ "us-east-2": {Point{39.96, -83.00}, "US East · Ohio"},
+ "us-west-1": {Point{37.77, -122.42}, "US West · N. California"},
+ "us-west-2": {Point{45.84, -119.70}, "US West · Oregon"},
+ "ca-central-1": {Point{45.50, -73.57}, "Canada · Montréal"},
+ "ca-west-1": {Point{51.05, -114.07}, "Canada · Calgary"},
+ "mx-central-1": {Point{20.59, -100.39}, "Mexico · Querétaro"},
+ "sa-east-1": {Point{-23.55, -46.63}, "Brazil · São Paulo"},
+ "eu-west-1": {Point{53.35, -6.26}, "Ireland · Dublin"},
+ "eu-west-2": {Point{51.51, -0.13}, "UK · London"},
+ "eu-west-3": {Point{48.86, 2.35}, "France · Paris"},
+ "eu-central-1": {Point{50.11, 8.68}, "Germany · Frankfurt"},
+ "eu-central-2": {Point{47.37, 8.54}, "Switzerland · Zurich"},
+ "eu-south-1": {Point{45.46, 9.19}, "Italy · Milan"},
+ "eu-south-2": {Point{41.65, -0.89}, "Spain · Aragón"},
+ "eu-north-1": {Point{59.33, 18.07}, "Sweden · Stockholm"},
+ "il-central-1": {Point{32.09, 34.78}, "Israel · Tel Aviv"},
+ "me-south-1": {Point{26.23, 50.59}, "Bahrain"},
+ "me-central-1": {Point{25.20, 55.27}, "UAE"},
+ "af-south-1": {Point{-33.92, 18.42}, "South Africa · Cape Town"},
+ "ap-south-1": {Point{19.08, 72.88}, "India · Mumbai"},
+ "ap-south-2": {Point{17.39, 78.49}, "India · Hyderabad"},
+ "ap-east-1": {Point{22.32, 114.17}, "Hong Kong"},
+ "ap-east-2": {Point{25.03, 121.57}, "Taiwan · Taipei"},
+ "ap-southeast-1": {Point{1.35, 103.82}, "Singapore"},
+ "ap-southeast-2": {Point{-33.87, 151.21}, "Australia · Sydney"},
+ "ap-southeast-3": {Point{-6.21, 106.85}, "Indonesia · Jakarta"},
+ "ap-southeast-4": {Point{-37.81, 144.96}, "Australia · Melbourne"},
+ "ap-southeast-5": {Point{3.14, 101.69}, "Malaysia"},
+ "ap-southeast-6": {Point{-36.85, 174.76}, "New Zealand · Auckland"},
+ "ap-southeast-7": {Point{13.76, 100.50}, "Thailand · Bangkok"},
+ "ap-northeast-1": {Point{35.68, 139.69}, "Japan · Tokyo"},
+ "ap-northeast-2": {Point{37.57, 126.98}, "South Korea · Seoul"},
+ "ap-northeast-3": {Point{34.69, 135.50}, "Japan · Osaka"},
+}
+
+// LookupAWSRegion finds a region in the table.
+func LookupAWSRegion(code string) (AWSRegion, bool) {
+ r, ok := awsRegions[code]
+ return r, ok
+}
+
+func tablePoint(code string) (Point, bool) {
+ r, ok := awsRegions[code]
+ return r.Point, ok
+}
+
+// Nearest is NearestWith over the shipped table.
+func Nearest(p Point, cands []Candidate) (string, bool) {
+ return NearestWith(p, cands, tablePoint)
+}
+
+// PlaceName is the table's place for awsRegion, or fallback (the bare
+// placement code) for a region the table does not know.
+func PlaceName(awsRegion, fallback string) string {
+ if r, ok := awsRegions[awsRegion]; ok {
+ return r.Place
+ }
+ return fallback
+}
diff --git a/internal/geo/awsregions_test.go b/internal/geo/awsregions_test.go
new file mode 100644
index 000000000..0cecda3d6
--- /dev/null
+++ b/internal/geo/awsregions_test.go
@@ -0,0 +1,95 @@
+package geo
+
+import (
+ "encoding/json"
+ "os"
+ "regexp"
+ "strings"
+ "testing"
+)
+
+func TestAWSRegionTable(t *testing.T) {
+ shape := regexp.MustCompile(`^[a-z]{2}(-[a-z]+)+-\d$`)
+ for code, r := range awsRegions {
+ if !shape.MatchString(code) {
+ t.Errorf("%s is not an AWS region code", code)
+ }
+ if r.Lat < -90 || r.Lat > 90 || r.Lon < -180 || r.Lon > 180 {
+ t.Errorf("%s: %v out of range", code, r.Point)
+ }
+ if r.Place == "" || strings.Contains(r.Place, "—") {
+ t.Errorf("%s: place %q empty or contains an em dash", code, r.Place)
+ }
+ }
+ if len(awsRegions) != 34 {
+ t.Errorf("%d regions, want the 34 of spec C23", len(awsRegions))
+ }
+ if PlaceName("xx-nowhere-1", "zz") != "zz" || PlaceName("", "ie") != "ie" {
+ t.Error("PlaceName must fall back to the given code")
+ }
+ if r, ok := LookupAWSRegion("eu-west-2"); !ok || PlaceName("eu-west-2", "uk") != r.Place {
+ t.Error("PlaceName must read the table")
+ }
+}
+
+func TestNearestUsesTheTable(t *testing.T) {
+ london, _ := ZonePoint("Europe/London")
+ got, ok := Nearest(london, []Candidate{
+ {Code: "", Home: true, AWSRegion: "eu-west-1"},
+ {Code: "uk", AWSRegion: "eu-west-2"},
+ })
+ if !ok || got != "uk" {
+ t.Fatalf("Nearest from London = (%q, %v), want uk", got, ok)
+ }
+}
+
+// TestPlaceNamesMatchApprovedRecord fails if any C23-* text in the approved
+// copy record is missing from awsregions.go as a whole quoted Go string
+// literal, or differs from the table's place for that region.
+func TestPlaceNamesMatchApprovedRecord(t *testing.T) {
+ raw, err := os.ReadFile("../../docs/superpowers/plans/2026-10-02-nearest-region-copy.json")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var rec struct {
+ Entries []struct {
+ ID string `json:"id"`
+ Text string `json:"text"`
+ } `json:"entries"`
+ }
+ if err := json.Unmarshal(raw, &rec); err != nil {
+ t.Fatal(err)
+ }
+ src, err := os.ReadFile("awsregions.go")
+ if err != nil {
+ t.Fatal(err)
+ }
+ seen := map[string]bool{}
+ for _, e := range rec.Entries {
+ code, ok := strings.CutPrefix(e.ID, "C23-")
+ if !ok {
+ continue
+ }
+ seen[code] = true
+ if e.Text == "" {
+ t.Errorf("%s: empty text in the record", e.ID)
+ continue
+ }
+ if !strings.Contains(string(src), `"`+e.Text+`"`) {
+ t.Errorf("%s: %q is not a quoted string literal in awsregions.go", e.ID, e.Text)
+ }
+ if r, ok := LookupAWSRegion(code); !ok {
+ t.Errorf("%s: region missing from the table", e.ID)
+ } else if r.Place != e.Text {
+ t.Errorf("%s: table place %q, record %q", e.ID, r.Place, e.Text)
+ }
+ }
+ for code := range awsRegions {
+ if !seen[code] {
+ t.Errorf("%s: in the table but has no C23 entry in the record", code)
+ }
+ }
+ if len(seen) != 34 {
+ t.Errorf("%d C23 entries in the record, want 34", len(seen))
+ }
+}