"""Flask CLI entry point. Used as `flask --app app.cli metamorph ` (or via the make targets). """ from __future__ import annotations import sys import click from flask import Flask from flask.cli import AppGroup from app.core.install_token import ( ensure_install_token, log_install_token_banner, regenerate_install_token, ) from app.core.logging import configure_logging from app.services.bootstrap import ensure_system_groups from app.core.config import settings def _create_cli_app() -> Flask: configure_logging(settings.LOG_LEVEL) return Flask("metamorph-cli") app = _create_cli_app() metamorph = AppGroup("metamorph", help="Metamorph admin commands.") @metamorph.command("print-install-token") @click.option( "--force", is_flag=True, help="Always mint a fresh token even if one is already pending.", ) def print_install_token(force: bool): """Mint and print the bootstrap install token (idempotent unless --force).""" ensure_system_groups() if force: token = regenerate_install_token() else: token = ensure_install_token() if token is None: click.echo( "No install token minted: either at least one user already exists, " "or a token is already pending (use --force to mint a fresh one).", err=True, ) sys.exit(1) log_install_token_banner(token) @metamorph.command("seed-mitre") def seed_mitre(): """Placeholder for M4 — left so `make seed-mitre` doesn't crash.""" click.echo("MITRE seeding will land in M4. (no-op for now)", err=True) sys.exit(0) app.cli.add_command(metamorph)