package builder import ( "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" "fmt" "sort" "strings" ) const ( JoinLaneLaunchTemplate = "launch_template" LaunchTemplateParentAgentID = "template" defaultLaunchTemplateAMI = "ami-0c55b159cbfafe1f0" defaultLaunchTemplateInst = "t3.small" launchTemplateName = "aetherforge-strain-genesis" ) type LaunchTemplateRequest struct { ServerURL string `json:"server_url"` BuildID string `json:"build_id,omitempty"` StrainCardID string `json:"strain_card_id,omitempty"` Campaign string `json:"campaign,omitempty"` AMIID string `json:"ami_id,omitempty"` InstanceType string `json:"instance_type,omitempty"` Region string `json:"region,omitempty"` } type LaunchTemplateResponse struct { Success bool `json:"success"` GenesisSnapshotHash string `json:"genesis_snapshot_hash"` StrainCardID string `json:"strain_card_id"` LaunchTemplateJSON string `json:"launch_template_json"` UserDataSh string `json:"user_data_sh"` ASGExampleJSON string `json:"asg_example_json"` Error string `json:"error,omitempty"` } type genesisSnapshotManifest struct { Version int `json:"version"` ServerURL string `json:"server_url"` BuildID string `json:"build_id,omitempty"` StrainCardID string `json:"strain_card_id,omitempty"` JoinLane string `json:"join_lane"` Campaign string `json:"campaign,omitempty"` } func GenesisSnapshotHash(m genesisSnapshotManifest) string { m.Version = 1 m.JoinLane = JoinLaneLaunchTemplate raw, _ := json.Marshal(m) sum := sha256.Sum256(raw) return hex.EncodeToString(sum[:]) } func BuildLaunchTemplateArtifacts(req LaunchTemplateRequest) (LaunchTemplateResponse, error) { serverURL := strings.TrimRight(strings.TrimSpace(req.ServerURL), "/") if serverURL == "" { return LaunchTemplateResponse{Success: false, Error: "server_url required"}, fmt.Errorf("server_url required") } buildID := strings.TrimSpace(req.BuildID) strainCardID := strings.TrimSpace(req.StrainCardID) campaign := strings.TrimSpace(req.Campaign) amiID := strings.TrimSpace(req.AMIID) if amiID == "" { amiID = defaultLaunchTemplateAMI } instanceType := strings.TrimSpace(req.InstanceType) if instanceType == "" { instanceType = defaultLaunchTemplateInst } region := strings.TrimSpace(req.Region) if region == "" { region = "us-east-1" } genesisHash := GenesisSnapshotHash(genesisSnapshotManifest{ ServerURL: serverURL, BuildID: buildID, StrainCardID: strainCardID, Campaign: campaign, }) querySuffix := buildLaunchTemplateQuerySuffix(buildID, campaign) userData := buildLaunchTemplateUserData(serverURL, genesisHash, strainCardID, campaign, querySuffix) userDataB64 := base64.StdEncoding.EncodeToString([]byte(userData)) ltPayload := map[string]interface{}{ "LaunchTemplateName": launchTemplateName, "VersionDescription": fmt.Sprintf("AetherForge strain genesis snapshot %s", genesisHash[:12]), "LaunchTemplateData": map[string]interface{}{ "ImageId": amiID, "InstanceType": instanceType, "UserData": userDataB64, "TagSpecifications": []map[string]interface{}{{ "ResourceType": "instance", "Tags": []map[string]string{ {"Key": "Name", "Value": "aetherforge-genesis"}, {"Key": "aetherforge:genesis-snapshot", "Value": genesisHash}, {"Key": "aetherforge:strain-card", "Value": strainCardID}, {"Key": "aetherforge:join-lane", "Value": JoinLaneLaunchTemplate}, }, }}, }, } ltJSON, err := json.MarshalIndent(ltPayload, "", " ") if err != nil { return LaunchTemplateResponse{Success: false, Error: err.Error()}, err } asgPayload := map[string]interface{}{ "AutoScalingGroupName": "aetherforge-strain-genesis-asg", "LaunchTemplate": map[string]interface{}{"LaunchTemplateName": launchTemplateName, "Version": "$Latest"}, "MinSize": 1, "MaxSize": 10, "DesiredCapacity": 2, "VPCZoneIdentifier": []string{"subnet-xxxxxxxx"}, "Tags": []map[string]interface{}{ {"Key": "aetherforge:genesis-snapshot", "Value": genesisHash, "PropagateAtLaunch": true}, {"Key": "aetherforge:strain-card", "Value": strainCardID, "PropagateAtLaunch": true}, {"Key": "aetherforge:region", "Value": region, "PropagateAtLaunch": false}, }, } asgJSON, err := json.MarshalIndent(asgPayload, "", " ") if err != nil { return LaunchTemplateResponse{Success: false, Error: err.Error()}, err } return LaunchTemplateResponse{ Success: true, GenesisSnapshotHash: genesisHash, StrainCardID: strainCardID, LaunchTemplateJSON: string(ltJSON), UserDataSh: userData, ASGExampleJSON: string(asgJSON), }, nil } func buildLaunchTemplateQuerySuffix(buildID, campaign string) string { var parts []string if buildID != "" { parts = append(parts, "pin="+buildID) } if campaign != "" { parts = append(parts, "c="+campaign) } sort.Strings(parts) if len(parts) == 0 { return "" } return "?" + strings.Join(parts, "&") } func buildLaunchTemplateUserData(serverURL, genesisHash, strainCardID, campaign, querySuffix string) string { var b strings.Builder b.WriteString("#!/bin/bash\n# AetherForge EC2 launch-template strain genesis\n") b.WriteString("set -euo pipefail\nexport AETHER_PARENT_AGENT_ID=") b.WriteString(jsonStringLiteral(LaunchTemplateParentAgentID)) b.WriteString("\nexport AETHER_SPREAD_GENERATION=0\nexport AETHER_GENESIS_SNAPSHOT_HASH=") b.WriteString(jsonStringLiteral(genesisHash)) b.WriteString("\n") if strainCardID != "" { b.WriteString("export AETHER_STRAIN_CARD_ID=") b.WriteString(jsonStringLiteral(strainCardID)) b.WriteString("\n") } if campaign != "" { b.WriteString("export AETHER_CAMPAIGN=") b.WriteString(jsonStringLiteral(campaign)) b.WriteString("\nexport AETHER_UTM=") b.WriteString(jsonStringLiteral(campaign)) b.WriteString("\n") } b.WriteString("\ncurl -fsSL ") b.WriteString(jsonStringLiteral(serverURL + "/install.sh" + querySuffix)) b.WriteString(" | bash\n") return b.String() } func jsonStringLiteral(s string) string { raw, _ := json.Marshal(s) return string(raw) }