#![deny(clippy::all)]
#![warn(clippy::pedantic)]
use clap::Parser;
use parlov::demo;
#[derive(Debug, Parser)]
struct Args {
#[arg(long, default_value_t = 8080)]
port: u16,
}
#[tokio::main]
async fn main() {
let args = Args::parse();
let addr = demo::spawn_on(args.port).await;
println!("parlov demo server listening on http://{addr}");
println!();
println!("Routes:");
println!(" PATCH/PUT /state/{{id}} → 409/404 (state-transition-elicit)");
println!(" POST/PUT /unique/{{id}} → 409/404 (uniqueness-elicit)");
println!(" DELETE /dependent/{{id}} → 409/404 (dependency-delete-elicit)");
println!(" GET/HEAD /ratelimited/{{id}} → 429/404 (rate-limit-burst-elicit)");
println!(" GET/HEAD /headered/{{id}} → 200+hdrs/404 (rate-limit-headers-elicit)");
println!(" GET/HEAD /forbidden/{{id}} → 403/404 (low-privilege-elicit)");
println!(" GET/HEAD /scoped/{{id}} → 200/403/404 (scope-manipulation-elicit)");
println!();
println!("Known IDs: {}", demo::KNOWN_IDS.join(", "));
println!();
println!("Example:");
println!(" parlov scan --target \"http://{addr}/state/{{id}}\" \\");
println!(" --baseline-id 42 --probe-id 9999 \\");
println!(" --risk method-destructive \\");
println!(" --state-field \"status=invalid_state\"");
tokio::signal::ctrl_c()
.await
.expect("failed to listen for ctrl-c");
println!("\nshutting down.");
}