feat(pipeline): register 3-stage ops-audit pipeline definitions and wire super-cli prune command
This commit is contained in:
@@ -1866,6 +1866,76 @@ def cmd_web_sync(args):
|
|||||||
print_table(headers, rows)
|
print_table(headers, rows)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Domain: CRED (Credentials & Onboarding Client)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
def cmd_cred_initiate(args):
|
||||||
|
import cred_client
|
||||||
|
client = cred_client.CredClient()
|
||||||
|
res = client.initiate(args.node, args.email, service=getattr(args, "service", "muse"), account_name=getattr(args, "account_name", None))
|
||||||
|
if getattr(args, "json", False):
|
||||||
|
print(json.dumps(res, indent=2))
|
||||||
|
else:
|
||||||
|
st = res.get("status")
|
||||||
|
if st == "awaiting_otp":
|
||||||
|
print("\n" + c_warn(f"[APPROVAL_NEEDED] Code sent to {args.email} for node '{args.node}'.") + "\n")
|
||||||
|
print(f" Submit OTP with: super cred submit-otp --node {args.node} --otp <code>\n")
|
||||||
|
sys.exit(2)
|
||||||
|
elif st == "active":
|
||||||
|
print("\n" + c_ok(f"[SUCCESS] Node '{args.node}' is already authenticated and active.") + "\n")
|
||||||
|
else:
|
||||||
|
print(f"[{st.upper()}] {res.get('message') or res.get('detail')}")
|
||||||
|
sys.exit(res.get("code", 1))
|
||||||
|
|
||||||
|
def cmd_cred_submit_otp(args):
|
||||||
|
import cred_client
|
||||||
|
client = cred_client.CredClient()
|
||||||
|
res = client.submit_otp(args.node, args.otp, email=getattr(args, "email", None))
|
||||||
|
if getattr(args, "json", False):
|
||||||
|
print(json.dumps(res, indent=2))
|
||||||
|
else:
|
||||||
|
st = res.get("status")
|
||||||
|
if st == "active":
|
||||||
|
print("\n" + c_ok(f"[SUCCESS] Node '{args.node}' successfully signed in!") + "\n")
|
||||||
|
else:
|
||||||
|
print(f"[{st.upper()}] {res.get('message') or res.get('detail')}")
|
||||||
|
sys.exit(res.get("code", 1))
|
||||||
|
|
||||||
|
def cmd_cred_status(args):
|
||||||
|
import cred_client
|
||||||
|
client = cred_client.CredClient()
|
||||||
|
res = client.status(args.node)
|
||||||
|
if getattr(args, "json", False):
|
||||||
|
print(json.dumps(res, indent=2))
|
||||||
|
else:
|
||||||
|
print("\n" + c_bold(f"=== CRED STATUS: {args.node} ===") + "\n")
|
||||||
|
print(f" Node : {c_bold(res['node'])}")
|
||||||
|
print(f" Email : {res['email']}")
|
||||||
|
print(f" Status : {res['status']}")
|
||||||
|
print(f" CDP Port : {res['cdp_port'] or '-'}")
|
||||||
|
alive_b = badge_ok("YES") if res['session_alive'] else badge_warn("NO")
|
||||||
|
print(f" Session Alive: {alive_b}")
|
||||||
|
if res["detail"]:
|
||||||
|
print(f" Detail : {c_dim(res['detail'])}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
def cmd_cred_list(args):
|
||||||
|
import cred_client
|
||||||
|
client = cred_client.CredClient()
|
||||||
|
items = client.list_all()
|
||||||
|
if getattr(args, "json", False):
|
||||||
|
print(json.dumps(items, indent=2))
|
||||||
|
else:
|
||||||
|
print("\n" + c_bold("=== FLEET CREDENTIAL & ONBOARDING STATUS ===") + "\n")
|
||||||
|
headers = ["NODE", "STATUS", "CDP", "ALIVE", "EMAIL"]
|
||||||
|
rows = []
|
||||||
|
for it in items:
|
||||||
|
alive_b = badge_ok("YES") if it["session_alive"] else badge_warn("NO")
|
||||||
|
rows.append([c_bold(it['node']), it['status'], str(it['cdp_port'] or '-'), alive_b, it['email']])
|
||||||
|
print_table(headers, rows)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Domain: HARVEST (Response & Readback Harvester)
|
# Domain: HARVEST (Response & Readback Harvester)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -2929,6 +2999,26 @@ def build_parser():
|
|||||||
web_sub.add_parser("test-auth", parents=[common], help="Verify operator auth gating on the VM")
|
web_sub.add_parser("test-auth", parents=[common], help="Verify operator auth gating on the VM")
|
||||||
web_sub.add_parser("sync", parents=[common], help="Check local log size and sync integrity")
|
web_sub.add_parser("sync", parents=[common], help="Check local log size and sync integrity")
|
||||||
|
|
||||||
|
# Domain: CRED
|
||||||
|
p_cred = subparsers.add_parser("cred", parents=[common], help="Credential console API & client onboarding")
|
||||||
|
cred_sub = p_cred.add_subparsers(dest="action")
|
||||||
|
|
||||||
|
p_c_init = cred_sub.add_parser("initiate", parents=[common], help="Initiate onboarding flow for a node")
|
||||||
|
p_c_init.add_argument("--node", required=True, help="Node label (e.g. opm, pip, 646)")
|
||||||
|
p_c_init.add_argument("--email", required=True, help="Client login email")
|
||||||
|
p_c_init.add_argument("--service", default="muse", help="Service name (default: muse)")
|
||||||
|
p_c_init.add_argument("--account-name", default=None, help="Display name hint for multi-account selector")
|
||||||
|
|
||||||
|
p_c_otp = cred_sub.add_parser("submit-otp", parents=[common], help="Submit transient OTP verification code")
|
||||||
|
p_c_otp.add_argument("--node", required=True, help="Node label")
|
||||||
|
p_c_otp.add_argument("--otp", required=True, help="6-digit verification code")
|
||||||
|
p_c_otp.add_argument("--email", default=None, help="Client email (optional)")
|
||||||
|
|
||||||
|
p_c_stat = cred_sub.add_parser("status", parents=[common], help="Query onboarding & vitality status for a node")
|
||||||
|
p_c_stat.add_argument("--node", required=True, help="Node label")
|
||||||
|
|
||||||
|
cred_sub.add_parser("list", parents=[common], help="List all registered nodes and vitality statuses")
|
||||||
|
|
||||||
# Domain: HARVEST
|
# Domain: HARVEST
|
||||||
p_harvest = subparsers.add_parser("harvest", parents=[common], help="Readback & response harvesting engine")
|
p_harvest = subparsers.add_parser("harvest", parents=[common], help="Readback & response harvesting engine")
|
||||||
harvest_sub = p_harvest.add_subparsers(dest="action")
|
harvest_sub = p_harvest.add_subparsers(dest="action")
|
||||||
@@ -3191,6 +3281,18 @@ def main():
|
|||||||
cmd_web_sync(args)
|
cmd_web_sync(args)
|
||||||
else:
|
else:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
elif args.domain == "cred":
|
||||||
|
act = getattr(args, "action", None)
|
||||||
|
if not act or act == "list":
|
||||||
|
cmd_cred_list(args)
|
||||||
|
elif act == "initiate":
|
||||||
|
cmd_cred_initiate(args)
|
||||||
|
elif act == "submit-otp":
|
||||||
|
cmd_cred_submit_otp(args)
|
||||||
|
elif act == "status":
|
||||||
|
cmd_cred_status(args)
|
||||||
|
else:
|
||||||
|
parser.print_help()
|
||||||
elif args.domain == "harvest":
|
elif args.domain == "harvest":
|
||||||
act = getattr(args, "action", None)
|
act = getattr(args, "action", None)
|
||||||
if not act or act == "status":
|
if not act or act == "status":
|
||||||
|
|||||||
+6
-1
@@ -41,6 +41,11 @@
|
|||||||
"pipe-1b4579": {
|
"pipe-1b4579": {
|
||||||
"thread_uuid": "bf7bf3e1-3ee8-4816-9b66-b77b34387986",
|
"thread_uuid": "bf7bf3e1-3ee8-4816-9b66-b77b34387986",
|
||||||
"agent": "opm",
|
"agent": "opm",
|
||||||
"created_at": "2026-10-04T16:53:54.998468+00:00"
|
"created_at": "2026-10-04T16:58:33.951216+00:00"
|
||||||
|
},
|
||||||
|
"pipe-fe170d": {
|
||||||
|
"thread_uuid": "fbc37533-3908-460e-bb82-58a7edbe5f30",
|
||||||
|
"agent": "opm",
|
||||||
|
"created_at": "2026-10-04T17:17:48.449687+00:00"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "ops-audit-step1",
|
||||||
|
"description": "Step 1 of Fleet Operational Audit Pipeline: opm checks Box Web endpoints",
|
||||||
|
"agent": "opm",
|
||||||
|
"schedule": "manual",
|
||||||
|
"timeout": 300,
|
||||||
|
"on_success": "ops-audit-step2",
|
||||||
|
"on_failure": "ops-audit-alert",
|
||||||
|
"step_delay": 5,
|
||||||
|
"followup": {
|
||||||
|
"expect_reply": true,
|
||||||
|
"timeout": "15m",
|
||||||
|
"nudges": 2,
|
||||||
|
"escalate": "opm"
|
||||||
|
},
|
||||||
|
"prompt_template": "Operational Audit Step 1: Probe Box HTTP endpoints (Front-Door Console and live API surfaces). Summarize probe status in 1 sentence.\n\nWhen finished, end your response with:\n[RESULT {job_id}] OK: Box HTTP endpoints verified responsive"
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "ops-audit-step2",
|
||||||
|
"description": "Step 2 of Fleet Operational Audit Pipeline: 646 checks VM services and disk state",
|
||||||
|
"agent": "646",
|
||||||
|
"schedule": "manual",
|
||||||
|
"timeout": 300,
|
||||||
|
"on_success": "ops-audit-step3",
|
||||||
|
"on_failure": "ops-audit-alert",
|
||||||
|
"step_delay": 5,
|
||||||
|
"followup": {
|
||||||
|
"expect_reply": true,
|
||||||
|
"timeout": "15m",
|
||||||
|
"nudges": 2,
|
||||||
|
"escalate": "opm"
|
||||||
|
},
|
||||||
|
"prompt_template": "Operational Audit Step 2: Upstream report from {prev_job_id}:\n\"{prev_result}\"\n\nVerify VM backend services (board, caddy, timers) and confirm storage integrity.\n\nWhen finished, end your response with:\n[RESULT {job_id}] OK: VM services and storage verified healthy"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "ops-audit-step3",
|
||||||
|
"description": "Step 3 of Fleet Operational Audit Pipeline: pip conducts final fleet sign-off",
|
||||||
|
"agent": "pip",
|
||||||
|
"schedule": "manual",
|
||||||
|
"timeout": 300,
|
||||||
|
"followup": {
|
||||||
|
"expect_reply": true,
|
||||||
|
"timeout": "15m",
|
||||||
|
"nudges": 2,
|
||||||
|
"escalate": "opm"
|
||||||
|
},
|
||||||
|
"prompt_template": "Operational Audit Step 3: Upstream audit report from {prev_job_id}:\n\"{prev_result}\"\n\nReview the combined operational findings across Web and VM systems. Formulate final audit approval.\n\nWhen finished, end your response with:\n[RESULT {job_id}] OK: Operational audit verified and approved by pip"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user