Skip to main content

systemprompt_cli/session/
api.rs

1//! Local session and JWT minting for CLI commands.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use anyhow::{Context, Result};
7use chrono::Duration;
8use systemprompt_analytics::{CreateSessionParams, SessionRepository};
9use systemprompt_database::DbPool;
10use systemprompt_identifiers::{SessionId, SessionSource, UserId};
11use uuid::Uuid;
12
13// Why: the public `POST /oauth/session` endpoint must not accept a
14// caller-supplied `user_id` — doing so allows arbitrary admin-JWT issuance
15// against any known user UUID on a public route. The CLI is colocated with
16// the database and holds the JWT signing secret, so it mints session rows
17// (and the JWTs above) locally instead of round-tripping through the public
18// HTTP endpoint.
19pub async fn create_local_session_row(db_pool: &DbPool, user: &UserId) -> Result<SessionId> {
20    let session_repo =
21        SessionRepository::new(db_pool).context("Failed to construct session repository")?;
22
23    let session_id = SessionId::new(format!("sess_{}", Uuid::new_v4()));
24    let expires_at = chrono::Utc::now() + Duration::hours(24);
25
26    let params = CreateSessionParams {
27        session_id: &session_id,
28        user_id: Some(user),
29        session_source: SessionSource::Cli,
30        fingerprint_hash: None,
31        ip_address: None,
32        user_agent: None,
33        device_type: None,
34        browser: None,
35        os: None,
36        country: None,
37        region: None,
38        city: None,
39        preferred_locale: None,
40        referrer_source: None,
41        referrer_url: None,
42        landing_page: None,
43        entry_url: None,
44        utm_source: None,
45        utm_medium: None,
46        utm_campaign: None,
47        utm_content: None,
48        utm_term: None,
49        is_bot: false,
50        is_ai_crawler: false,
51        expires_at,
52    };
53
54    session_repo
55        .create_session(&params)
56        .await
57        .context("Failed to insert CLI session row")?;
58
59    Ok(session_id)
60}