//! Internal API endpoints for service-to-service communication. //! //! These endpoints are protected by `ServiceAuth` (Bearer token) and are //! called by the CLI SSH server running on the same host. mod cli_features; mod content; mod creators; mod git; mod items; mod uploads; pub(super) use git::restart_status; use axum::routing::get; use crate::{ csrf::{delete_csrf_skip, post_csrf_skip, put_csrf_skip, with_csrf_skip, CsrfRouter}, AppState, }; /// All routes in this file are HMAC-bearer authed via `ServiceAuth` (no /// session); CSRF is not applicable. Each registration carries the same /// `Skip` reason so the posture is visible at the call site. const INTERNAL_SKIP: &str = "internal API: HMAC bearer auth, no session"; /// Internal service-to-service routes (ServiceAuth, no rate limit). pub(super) fn internal_routes() -> CsrfRouter { CsrfRouter::new() .route_get("/api/internal/ssh-key-lookup", get(git::ssh_key_lookup)) .route("/api/internal/creator/projects", with_csrf_skip(INTERNAL_SKIP, get(creators::creator_projects).post(cli_features::create_project))) .route_get("/api/internal/creator/projects/{id}/items", get(creators::creator_project_items)) .route_get("/api/internal/creator/stats", get(creators::creator_stats)) .route("/api/internal/creator/items", post_csrf_skip(INTERNAL_SKIP, items::create_item)) .route("/api/internal/upload/presign", post_csrf_skip(INTERNAL_SKIP, uploads::presign_upload)) .route("/api/internal/upload/confirm", post_csrf_skip(INTERNAL_SKIP, uploads::confirm_upload)) .route_get("/api/internal/creator/storage", get(uploads::creator_storage)) .route_get("/api/internal/creator/items/{id}", get(items::get_item)) .route("/api/internal/creator/items/{id}", put_csrf_skip(INTERNAL_SKIP, items::update_item)) .route("/api/internal/creator/items/{id}", delete_csrf_skip(INTERNAL_SKIP, items::delete_item)) .route("/api/internal/creator/items/{id}/publish", post_csrf_skip(INTERNAL_SKIP, items::publish_item)) .route("/api/internal/creator/items/{id}/unpublish", post_csrf_skip(INTERNAL_SKIP, items::unpublish_item)) .route_get("/api/internal/creator/items/{id}/versions", get(items::item_versions)) // Blog posts .route_get("/api/internal/creator/projects/{id}/blog", get(content::list_blog_posts)) .route("/api/internal/creator/blog", post_csrf_skip(INTERNAL_SKIP, content::create_blog_post)) .route("/api/internal/creator/blog/{id}", delete_csrf_skip(INTERNAL_SKIP, content::delete_blog_post)) // Promo codes .route("/api/internal/creator/promo-codes", with_csrf_skip(INTERNAL_SKIP, get(content::list_promo_codes).post(content::create_promo_code))) .route("/api/internal/creator/promo-codes/{id}", delete_csrf_skip(INTERNAL_SKIP, content::delete_promo_code)) // License keys .route("/api/internal/creator/items/{id}/keys", with_csrf_skip(INTERNAL_SKIP, get(content::list_license_keys).post(content::generate_license_key))) .route("/api/internal/creator/keys/{id}/revoke", post_csrf_skip(INTERNAL_SKIP, content::revoke_license_key)) // Analytics + export .route_get("/api/internal/creator/analytics", get(creators::creator_analytics)) .route_get("/api/internal/creator/transactions", get(creators::creator_transactions)) .route_get("/api/internal/creator/export/sales", get(creators::export_sales)) // Settings .route_get("/api/internal/creator/ssh-keys", get(git::list_ssh_keys)) // Git authorization .route("/api/internal/git/authorize", post_csrf_skip(INTERNAL_SKIP, git::git_authorize)) .route("/api/internal/restart-warning", post_csrf_skip(INTERNAL_SKIP, git::set_restart_warning)) // CLI features: tags .route_get("/api/internal/creator/items/{id}/tags", get(cli_features::list_item_tags)) .route("/api/internal/creator/items/tags", post_csrf_skip(INTERNAL_SKIP, cli_features::add_item_tag)) .route("/api/internal/creator/items/tags/remove", post_csrf_skip(INTERNAL_SKIP, cli_features::remove_item_tag)) .route_get("/api/internal/tags/search", get(cli_features::search_tags)) // CLI features: broadcast .route("/api/internal/creator/broadcast", post_csrf_skip(INTERNAL_SKIP, cli_features::send_broadcast)) // CLI features: tiers .route_get("/api/internal/creator/projects/{id}/tiers", get(cli_features::list_tiers)) // CLI features: collections .route("/api/internal/creator/collections", with_csrf_skip(INTERNAL_SKIP, get(cli_features::list_collections).post(cli_features::create_collection))) .route("/api/internal/creator/collections/{id}", delete_csrf_skip(INTERNAL_SKIP, cli_features::delete_collection)) // CLI features: custom domains .route("/api/internal/creator/domain", with_csrf_skip(INTERNAL_SKIP, get(cli_features::get_domain).post(cli_features::add_domain).delete(cli_features::remove_domain))) .route("/api/internal/creator/domain/verify", post_csrf_skip(INTERNAL_SKIP, cli_features::verify_domain)) }