Files
orbit/internal/transport/httpserver/console/index.html

279 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="dark">
<title>Orbit Console · 星轨控制台</title>
<link rel="stylesheet" href="/console/styles.css">
</head>
<body>
<div class="ambient ambient-one"></div>
<div class="ambient ambient-two"></div>
<div class="app-shell">
<aside class="sidebar">
<div class="brand">
<div class="brand-mark"><span></span><span></span><span></span></div>
<div><strong>Orbit</strong><small>星轨控制台</small></div>
</div>
<div class="workspace-label">CONTROL PLANE</div>
<nav class="nav-list" aria-label="控制台导航">
<button class="nav-item active" data-view="overview"><span class="nav-icon">⌂</span><span>总览</span><em>01</em></button>
<button class="nav-item" data-view="tasks"><span class="nav-icon">◇</span><span>任务执行</span><em>02</em></button>
<button class="nav-item" data-view="schedules"><span class="nav-icon">◷</span><span>定时计划</span><em>03</em></button>
<button class="nav-item" data-view="workflows"><span class="nav-icon">⌘</span><span>流程实例</span><em>04</em></button>
<button class="nav-item" data-view="subscriptions"><span class="nav-icon">⌁</span><span>结果订阅</span><em>05</em></button>
</nav>
<div class="sidebar-bottom">
<div class="rail-card">
<div class="rail-card-top"><span class="status-dot"></span><span id="side-status">等待连接</span></div>
<p id="side-endpoint">API 未连接</p>
<div class="rail-progress"><span id="side-progress"></span></div>
</div>
<div class="sidebar-foot"><span class="pulse-dot"></span> Pulse · Weave <span class="foot-version">v1</span></div>
</div>
</aside>
<main class="main-content">
<header class="topbar">
<div class="crumbs"><span>Orbit</span><b>/</b><strong id="page-title">总览</strong></div>
<div class="topbar-actions">
<span class="live-chip"><i></i><span id="live-label">本地环境</span></span>
<span class="last-updated" id="last-updated">尚未刷新</span>
<button class="icon-button" id="refresh-button" title="刷新数据" aria-label="刷新数据">↻</button>
</div>
</header>
<div class="page-view active" id="view-overview" data-page="overview">
<section class="hero" id="overview">
<div class="hero-copy">
<div class="eyebrow"><span class="eyebrow-line"></span> ORBIT CONTROL PLANE</div>
<h1>让每一次执行<br><span>都清晰可见。</span></h1>
<p>任务、定时、流程和交付状态,在一块屏幕上保持有序运转。</p>
<div class="hero-actions">
<button class="primary-button" data-view="tasks">查看任务 <span>↗</span></button>
<button class="quiet-button" id="connect-hero">连接环境</button>
</div>
</div>
<div class="hero-visual" aria-hidden="true">
<div class="orbit-ring ring-one"></div>
<div class="orbit-ring ring-two"></div>
<div class="orbit-ring ring-three"></div>
<div class="orbit-core"><span>O</span></div>
<div class="orbit-node node-a"></div><div class="orbit-node node-b"></div><div class="orbit-node node-c"></div>
<div class="hero-visual-label"><b>LIVE</b><span>任务流持续观测</span></div>
</div>
</section>
<section class="metric-grid" aria-label="运行概览">
<article class="metric-card metric-highlight"><div class="metric-top"><span>服务状态</span><span class="metric-icon green">✦</span></div><strong id="metric-health">—</strong><small id="metric-health-sub">等待就绪检查</small><div class="sparkline green-line"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></article>
<article class="metric-card"><div class="metric-top"><span>任务总览</span><span class="metric-icon purple">◇</span></div><strong id="metric-tasks">—</strong><small id="metric-tasks-sub">连接凭据后加载</small><div class="mini-bar"><i id="task-bar-succeeded"></i><i id="task-bar-running"></i><i id="task-bar-waiting"></i><i id="task-bar-other"></i></div></article>
<article class="metric-card"><div class="metric-top"><span>流程实例</span><span class="metric-icon blue">⌘</span></div><strong id="metric-workflows">—</strong><small id="metric-workflows-sub">等待工作流权限</small><div class="sparkline blue-line"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></article>
<article class="metric-card"><div class="metric-top"><span>结果订阅</span><span class="metric-icon orange">⌁</span></div><strong id="metric-subscriptions">—</strong><small id="metric-subscriptions-sub">等待事件权限</small><div class="subscription-meter"><span id="subscription-meter-fill"></span></div></article>
</section>
<section class="content-grid single-column">
<article class="panel connect-panel" id="connection-panel">
<div class="panel-heading"><div><span class="panel-kicker">ENVIRONMENT</span><h2>连接环境</h2></div><span class="connection-state" id="connection-state">未连接</span></div>
<p class="panel-description">凭据只在当前浏览器会话中使用,不会上传到 Orbit Console。</p>
<label class="field-label" for="api-url">API 地址</label><div class="input-wrap"><span class="input-prefix">↗</span><input id="api-url" type="url" value="" placeholder="http://127.0.0.1:8080"></div>
<label class="field-label" for="queue-id">队列 ID</label><div class="input-wrap"><span class="input-prefix">#</span><input id="queue-id" type="text" placeholder="从凭据文件自动读取"></div>
<label class="field-label" for="token">Bearer Token</label><div class="input-wrap"><span class="input-prefix">●</span><input id="token" type="password" placeholder="粘贴开发凭据 token"><button class="reveal-button" id="reveal-token" type="button">显示</button></div>
<div class="connect-row"><label class="file-button"><input id="credential-file" type="file" accept="application/json">选择凭据 JSON</label><button class="primary-button compact" id="connect-button">连接 <span>→</span></button></div>
<div class="security-note"><span>▣</span><span>当前页面只调用公开 API 和授权接口,不读取数据库。</span></div>
</article>
</section>
</div>
<div class="page-view" id="view-tasks" data-page="tasks">
<section class="content-grid single-column">
<article class="panel wide-panel" id="tasks">
<div class="panel-heading"><div><span class="panel-kicker">PULSE / TASKS</span><h2>任务执行流</h2></div><div class="panel-tools"><span class="table-count" id="task-count">0 项</span><button class="text-button" data-view="overview">返回总览 <span>←</span></button></div></div>
<div class="table-wrap"><table><thead><tr><th>任务</th><th>处理器</th><th>状态</th><th>修订</th><th>创建时间</th></tr></thead><tbody id="task-table"><tr><td colspan="5" class="empty-row"><span class="empty-icon">◇</span><b>还没有任务数据</b><small>连接一个具备 tasks:read 权限的凭据后自动加载</small></td></tr></tbody></table></div>
</article>
</section>
</div>
<div class="page-view" id="view-schedules" data-page="schedules">
<section class="content-grid single-column">
<article class="panel" id="schedules"><div class="panel-heading"><div><span class="panel-kicker">PULSE / SCHEDULES</span><h2>定时计划</h2></div><span class="table-count" id="schedule-page-hint">点击计划查看详情</span></div><div class="schedule-list" id="schedule-list"><div class="empty-compact"><span>◷</span><div><b>等待计划数据</b><small>需要 schedules:read 权限</small></div></div></div></article>
</section>
</div>
<div class="page-view" id="view-workflows" data-page="workflows">
<section class="content-grid single-column">
<article class="panel" id="workflows"><div class="panel-heading"><div><span class="panel-kicker">WEAVE / WORKFLOWS</span><h2>流程实例</h2></div><span class="table-count">点击实例查看详情</span></div><div class="workflow-list" id="workflow-list"><div class="empty-compact"><span>⌘</span><div><b>等待流程数据</b><small>需要 workflows:read 权限</small></div></div></div></article>
</section>
</div>
<div class="page-view" id="view-subscriptions" data-page="subscriptions">
<section class="content-grid single-column">
<article class="panel" id="subscriptions"><div class="panel-heading"><div><span class="panel-kicker">EVENTS / DELIVERY</span><h2>结果订阅</h2></div><span class="live-label-small"><i></i>自动刷新</span></div><div class="subscription-list" id="subscription-list"><div class="empty-compact"><span>⌁</span><div><b>等待订阅数据</b><small>需要 events:read 权限</small></div></div></div></article>
</section>
</div>
<footer class="page-footer"><span><span class="footer-orbit">◉</span> Orbit Console · 星轨控制台</span><span>数据每 10 秒刷新 · <a href="/version" target="_blank" rel="noreferrer">查看服务版本</a></span></footer>
</main>
</div>
<div class="drawer-backdrop" id="task-drawer-backdrop" hidden>
<aside class="task-drawer" role="dialog" aria-modal="true" aria-labelledby="detail-title">
<div class="drawer-header">
<div><span class="panel-kicker">PULSE / TASK DETAIL</span><h2 id="detail-title">任务详情</h2><small class="drawer-id" id="detail-id">—</small></div>
<button class="icon-button" id="close-task-drawer" type="button" aria-label="关闭任务详情">×</button>
</div>
<div class="drawer-status-line"><span class="state-pill" id="detail-state">—</span><span id="detail-updated">—</span></div>
<div class="detail-grid">
<div><span>处理器</span><b id="detail-handler">—</b></div>
<div><span>修订</span><b id="detail-revision">—</b></div>
<div><span>执行尝试</span><b id="detail-attempt-count">—</b></div>
<div><span>效果状态</span><b id="detail-effect">—</b></div>
<div><span>创建时间</span><b id="detail-created">—</b></div>
<div><span>截止时间</span><b id="detail-deadline">—</b></div>
</div>
<div class="detail-block" id="detail-result-block" hidden><div class="detail-block-heading"><span>最终结果</span><small>只读快照</small></div><pre id="detail-result"></pre></div>
<div class="detail-block"><div class="detail-block-heading"><span>执行时间线</span><small id="detail-attempts-count">加载中</small></div><div class="detail-list" id="detail-attempts"><div class="detail-loading">正在读取尝试历史…</div></div></div>
<div class="detail-block"><div class="detail-block-heading"><span>操作审计</span><small id="detail-operations-count">加载中</small></div><div class="detail-list" id="detail-operations"><div class="detail-loading">正在读取操作审计…</div></div></div>
<div class="drawer-actions" id="detail-actions" hidden>
<button class="quiet-button danger-button" id="task-cancel-button" type="button">取消任务</button>
<button class="primary-button compact" id="task-retry-button" type="button">安全重试 <span>→</span></button>
</div>
<p class="drawer-note" id="detail-action-note">写操作需要对应的管理权限;服务端会再次校验版本、状态、幂等键和队列范围。</p>
<form class="action-form" id="task-action-form" hidden>
<div class="action-form-heading"><span class="panel-kicker" id="action-kicker">TASK CONTROL</span><h3 id="action-title">任务操作</h3></div>
<p id="action-description"></p>
<label class="field-label" for="action-reason">操作原因</label><textarea id="action-reason" rows="3" maxlength="1024" placeholder="说明本次操作的原因"></textarea>
<div id="action-evidence-wrap"><label class="field-label" for="action-evidence">证据引用</label><input id="action-evidence" type="text" maxlength="512" placeholder="例如 evidence:reconcile-001"></div>
<div id="action-timeout-wrap"><label class="field-label" for="action-timeout">新任务总时限(毫秒)</label><input id="action-timeout" type="number" min="1" max="2592000000" step="1" value="60000"></div>
<label class="check-row" id="action-safe-wrap"><input id="action-safe" type="checkbox"><span>我确认旧执行已经结束,按原业务身份重新执行是安全的。</span></label>
<div class="action-form-buttons"><button class="quiet-button" id="action-cancel" type="button">返回</button><button class="primary-button compact" id="action-submit" type="submit">提交操作 <span>→</span></button></div>
<div class="action-error" id="action-error" role="alert"></div>
</form>
</aside>
</div>
<div class="drawer-backdrop" id="schedule-drawer-backdrop" hidden>
<aside class="task-drawer schedule-drawer" role="dialog" aria-modal="true" aria-labelledby="schedule-detail-title">
<div class="drawer-header">
<div><span class="panel-kicker">PULSE / SCHEDULE DETAIL</span><h2 id="schedule-detail-title">定时计划</h2><small class="drawer-id" id="schedule-detail-id">—</small></div>
<button class="icon-button" id="close-schedule-drawer" type="button" aria-label="关闭计划详情">×</button>
</div>
<div class="drawer-status-line"><span class="state-pill" id="schedule-detail-state">—</span><span id="schedule-detail-updated">—</span></div>
<div class="detail-grid">
<div><span>计划名称</span><b id="schedule-detail-name">—</b></div>
<div><span>队列</span><b id="schedule-detail-queue">—</b></div>
<div><span>控制修订</span><b id="schedule-detail-revision">—</b></div>
<div><span>当前版本</span><b id="schedule-detail-version">—</b></div>
<div><span>下一次触发</span><b id="schedule-detail-next">—</b></div>
<div><span>时区</span><b id="schedule-detail-timezone">—</b></div>
</div>
<div class="detail-block"><div class="detail-block-heading"><span>当前版本规则</span><small id="schedule-detail-rule-kind">—</small></div><div class="schedule-rule-card" id="schedule-detail-rule">等待计划数据…</div></div>
<div class="detail-block"><div class="detail-block-heading"><span>最近触发记录</span><small id="schedule-occurrences-count">加载中</small></div><div class="detail-list" id="schedule-occurrences"><div class="detail-loading">正在读取触发记录…</div></div></div>
<div class="drawer-actions" id="schedule-actions" hidden><button class="quiet-button" id="schedule-control-button" type="button">暂停计划</button></div>
<p class="drawer-note" id="schedule-action-note">计划控制需要 schedules:manage 权限;暂停只停止未来触发,已经创建的任务继续执行。</p>
<form class="action-form" id="schedule-action-form" hidden>
<div class="action-form-heading"><span class="panel-kicker">SCHEDULE CONTROL</span><h3 id="schedule-action-title">暂停计划</h3></div>
<p id="schedule-action-description">暂停后不会再创建新的任务。</p>
<label class="field-label" for="schedule-action-reason">操作原因</label><textarea id="schedule-action-reason" rows="3" maxlength="1024" placeholder="说明本次计划控制的原因"></textarea>
<div class="action-form-buttons"><button class="quiet-button" id="schedule-action-cancel" type="button">返回</button><button class="primary-button compact" id="schedule-action-submit" type="submit">提交控制 →</button></div>
<div class="action-error" id="schedule-action-error" role="alert"></div>
</form>
</aside>
</div>
<div class="drawer-backdrop" id="workflow-drawer-backdrop" hidden>
<aside class="task-drawer workflow-drawer" role="dialog" aria-modal="true" aria-labelledby="workflow-detail-title">
<div class="drawer-header">
<div><span class="panel-kicker">WEAVE / WORKFLOW DETAIL</span><h2 id="workflow-detail-title">流程实例</h2><small class="drawer-id" id="workflow-detail-id">—</small></div>
<button class="icon-button" id="close-workflow-drawer" type="button" aria-label="关闭流程详情">×</button>
</div>
<div class="drawer-status-line"><span class="state-pill" id="workflow-detail-state">—</span><span id="workflow-detail-updated">—</span></div>
<div class="detail-grid">
<div><span>定义</span><b id="workflow-detail-definition">—</b></div>
<div><span>固定版本</span><b id="workflow-detail-version">—</b></div>
<div><span>实例修订</span><b id="workflow-detail-revision">—</b></div>
<div><span>控制修订</span><b id="workflow-detail-control-revision">—</b></div>
<div><span>业务键</span><b id="workflow-detail-business-key">—</b></div>
<div><span>总截止时间</span><b id="workflow-detail-deadline">—</b></div>
</div>
<div class="detail-block"><div class="detail-block-heading"><span>步骤状态</span><small id="workflow-steps-count">加载中</small></div><div class="detail-list" id="workflow-steps"><div class="detail-loading">正在读取步骤…</div></div></div>
<div class="detail-block"><div class="detail-block-heading"><span>事件时间线</span><small id="workflow-events-count">加载中</small></div><div class="detail-list" id="workflow-events"><div class="detail-loading">正在读取事件…</div></div></div>
<div class="detail-block" id="workflow-output-block" hidden><div class="detail-block-heading"><span>流程输出</span><small>只读快照</small></div><pre id="workflow-output"></pre></div>
<div class="detail-block recovery-block" id="workflow-recovery-block" hidden>
<div class="detail-block-heading"><span>人工核查与恢复</span><small id="workflow-recovery-hint">需要 workflows:recover</small></div>
<p class="recovery-intro">只在 NEEDS_REVIEW 状态显示。每个决定都要引用外部证据,并使用当前流程、步骤和激活修订;服务端会再次校验所有门控。</p>
<div class="recovery-action-grid" id="workflow-recovery-actions"></div>
</div>
<div class="drawer-actions" id="workflow-actions" hidden><button class="quiet-button" id="workflow-control-button" type="button">暂停流程</button><button class="quiet-button danger-button" id="workflow-cancel-button" type="button">取消流程</button></div>
<p class="drawer-note" id="workflow-detail-note">流程详情只读取当前权威视图;事件审计需要 workflows:audit:read 权限,所有控制操作仍由服务端权限和并发版本校验。</p>
<form class="action-form" id="workflow-action-form" hidden>
<div class="action-form-heading"><span class="panel-kicker">WEAVE CONTROL</span><h3 id="workflow-action-title">流程控制</h3></div>
<p id="workflow-action-description">流程控制会写入不可变审计,并使用当前控制修订进行并发校验。</p>
<label class="field-label" for="workflow-action-reason">操作原因</label><textarea id="workflow-action-reason" rows="3" maxlength="1024" placeholder="说明本次流程控制的原因"></textarea>
<div class="action-form-buttons"><button class="quiet-button" id="workflow-action-cancel" type="button">返回</button><button class="primary-button compact" id="workflow-action-submit" type="submit">提交控制 →</button></div>
<div class="action-error" id="workflow-action-error" role="alert"></div>
</form>
<form class="action-form recovery-form" id="workflow-recovery-form" hidden>
<div class="action-form-heading"><span class="panel-kicker">WEAVE RECOVERY</span><h3 id="workflow-recovery-title">人工恢复</h3></div>
<p id="workflow-recovery-description">提交后会写入流程审计,并按当前版本重新读取实例。</p>
<div class="recovery-snapshot" id="workflow-recovery-snapshot">当前流程修订 — · 当前步骤 —</div>
<label class="field-label" for="workflow-recovery-reason">核查原因</label><textarea id="workflow-recovery-reason" rows="3" maxlength="1024" placeholder="说明你核实了什么事实,以及为什么可以执行该决定"></textarea>
<label class="field-label" for="workflow-recovery-evidence">证据引用</label><input id="workflow-recovery-evidence" type="text" maxlength="512" placeholder="例如 evidence:query-001(不能含空格)">
<div id="workflow-recovery-step-fields" hidden>
<label class="field-label" for="workflow-recovery-step-key">步骤键</label><input id="workflow-recovery-step-key" type="text" maxlength="64" placeholder="当前步骤 key">
<label class="field-label" for="workflow-recovery-activation-id">激活 ID</label><input id="workflow-recovery-activation-id" type="text" maxlength="32" placeholder="当前激活代次 ID">
<label class="field-label" for="workflow-recovery-step-revision">步骤修订</label><input id="workflow-recovery-step-revision" type="number" min="1" step="1" placeholder="当前步骤 revision">
</div>
<div id="workflow-recovery-task-fields" hidden>
<label class="field-label" for="workflow-recovery-task-id">任务 ID</label><input id="workflow-recovery-task-id" type="text" maxlength="32" placeholder="待核查任务 ID">
<label class="field-label" for="workflow-recovery-task-revision">任务修订</label><input id="workflow-recovery-task-revision" type="number" min="1" step="1" placeholder="当前任务 revision">
</div>
<div class="recovery-inline-fields" id="workflow-recovery-outcome-fields" hidden>
<div><label class="field-label" for="workflow-recovery-outcome">结论</label><select id="workflow-recovery-outcome"><option value="SUCCEEDED">SUCCEEDED · 成功</option><option value="FAILED">FAILED · 失败</option></select></div>
<div id="workflow-recovery-result-wrap"><label class="field-label" for="workflow-recovery-result">结果 JSON</label><textarea id="workflow-recovery-result" rows="3" placeholder="例如 {&quot;status&quot;:&quot;DONE&quot;};TIMER 成功可填 null"></textarea></div>
</div>
<label class="check-row" id="workflow-recovery-confirm-row"><input id="workflow-recovery-confirm" type="checkbox"><span id="workflow-recovery-confirm-label">我确认已核实当前事项,可以提交这个恢复决定。</span></label>
<div class="action-form-buttons"><button class="quiet-button" id="workflow-recovery-cancel" type="button">返回</button><button class="primary-button compact" id="workflow-recovery-submit" type="submit">提交恢复 →</button></div>
<div class="action-error" id="workflow-recovery-error" role="alert"></div>
</form>
</aside>
</div>
<div class="drawer-backdrop" id="subscription-drawer-backdrop" hidden>
<aside class="task-drawer subscription-drawer" role="dialog" aria-modal="true" aria-labelledby="subscription-detail-title">
<div class="drawer-header">
<div><span class="panel-kicker">EVENTS / SUBSCRIPTION DETAIL</span><h2 id="subscription-detail-title">结果订阅</h2><small class="drawer-id" id="subscription-detail-id">—</small></div>
<button class="icon-button" id="close-subscription-drawer" type="button" aria-label="关闭订阅详情">×</button>
</div>
<div class="drawer-status-line"><span class="state-pill" id="subscription-detail-state">—</span><span id="subscription-detail-updated">—</span></div>
<div class="detail-grid">
<div><span>订阅名称</span><b id="subscription-detail-name">—</b></div>
<div><span>队列</span><b id="subscription-detail-queue">—</b></div>
<div><span>配置修订</span><b id="subscription-detail-revision">—</b></div>
<div><span>待确认交付</span><b id="subscription-detail-pending">—</b></div>
<div><span>未确认上限</span><b id="subscription-detail-max-pending">—</b></div>
<div><span>单条次数预算</span><b id="subscription-detail-max-attempts">—</b></div>
<div><span>游标序号</span><b id="subscription-detail-cursor">—</b></div>
<div><span>事件类型</span><b id="subscription-detail-types">—</b></div>
</div>
<div class="detail-block"><div class="detail-block-heading"><span>最近交付</span><small id="subscription-deliveries-count">加载中</small></div><div class="detail-list" id="subscription-deliveries"><div class="detail-loading">正在读取交付历史…</div></div></div>
<div class="drawer-actions" id="subscription-actions" hidden><button class="quiet-button" id="subscription-control-button" type="button">暂停订阅</button></div>
<p class="drawer-note" id="subscription-detail-note">交付详情不展示租约秘密;结果确认与人工重试必须通过受保护的消费或管理接口完成。</p>
<form class="action-form" id="subscription-action-form" hidden>
<div class="action-form-heading"><span class="panel-kicker">EVENTS CONTROL</span><h3 id="subscription-action-title">订阅控制</h3></div>
<p id="subscription-action-description">订阅控制会保留已有交付和审计记录。</p>
<label class="field-label" for="subscription-action-reason">操作原因</label><textarea id="subscription-action-reason" rows="3" maxlength="1024" placeholder="说明本次订阅控制的原因"></textarea>
<div class="action-form-buttons"><button class="quiet-button" id="subscription-action-cancel" type="button">返回</button><button class="primary-button compact" id="subscription-action-submit" type="submit">提交控制 →</button></div>
<div class="action-error" id="subscription-action-error" role="alert"></div>
</form>
<form class="action-form" id="subscription-retry-form" hidden>
<div class="action-form-heading"><span class="panel-kicker">EVENTS RECOVERY</span><h3>重试过期交付</h3></div>
<p>只允许对 EXPIRED 交付追加次数预算;原交付身份、已用次数和事件不会重置。</p>
<label class="field-label" for="subscription-retry-reason">操作原因</label><textarea id="subscription-retry-reason" rows="3" maxlength="1024" placeholder="说明接收方已修复的原因"></textarea>
<label class="field-label" for="subscription-retry-attempts">追加次数(1–100)</label><input id="subscription-retry-attempts" type="number" min="1" max="100" step="1" value="1">
<div class="action-form-buttons"><button class="quiet-button" id="subscription-retry-cancel" type="button">返回</button><button class="primary-button compact" id="subscription-retry-submit" type="submit">追加预算并重试 →</button></div>
<div class="action-error" id="subscription-retry-error" role="alert"></div>
</form>
</aside>
</div>
<div class="toast" id="toast" role="status"></div>
<script src="/console/app.js"></script>
</body>
</html>