Split MCP and approval agent keys
This commit is contained in:
@@ -148,11 +148,14 @@ pub async fn apply_postgres(pool: &PgPool) -> Result<(), sqlx::Error> {
|
||||
name text not null,
|
||||
prefix text not null,
|
||||
secret_hash text not null,
|
||||
key_kind text not null default 'mcp_client',
|
||||
scopes_json jsonb not null,
|
||||
status text not null,
|
||||
created_at timestamptz not null,
|
||||
last_used_at timestamptz null,
|
||||
revoked_at timestamptz null
|
||||
revoked_at timestamptz null,
|
||||
expires_at timestamptz null,
|
||||
allowed_origins_json jsonb not null default '[]'::jsonb
|
||||
)",
|
||||
)
|
||||
.execute(pool)
|
||||
@@ -166,6 +169,19 @@ pub async fn apply_postgres(pool: &PgPool) -> Result<(), sqlx::Error> {
|
||||
query("alter table platform_api_keys add column if not exists agent_id text null")
|
||||
.execute(pool)
|
||||
.await?;
|
||||
query(
|
||||
"alter table platform_api_keys add column if not exists key_kind text not null default 'mcp_client'",
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
query("alter table platform_api_keys add column if not exists expires_at timestamptz null")
|
||||
.execute(pool)
|
||||
.await?;
|
||||
query(
|
||||
"alter table platform_api_keys add column if not exists allowed_origins_json jsonb not null default '[]'::jsonb",
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
query(
|
||||
"insert into workspaces (
|
||||
|
||||
@@ -11,12 +11,15 @@ impl PostgresRegistry {
|
||||
id,
|
||||
workspace_id,
|
||||
agent_id,
|
||||
key_kind,
|
||||
name,
|
||||
prefix,
|
||||
scopes_json,
|
||||
status,
|
||||
created_at,
|
||||
last_used_at
|
||||
last_used_at,
|
||||
expires_at,
|
||||
allowed_origins_json
|
||||
from platform_api_keys
|
||||
where workspace_id = $1
|
||||
and agent_id = $2
|
||||
@@ -34,12 +37,20 @@ impl PostgresRegistry {
|
||||
id: PlatformApiKeyId::new(row.get::<String, _>("id")),
|
||||
workspace_id: WorkspaceId::new(row.get::<String, _>("workspace_id")),
|
||||
agent_id: row.get::<Option<String>, _>("agent_id").map(AgentId::new),
|
||||
key_kind: deserialize_enum_text(
|
||||
&row.get::<String, _>("key_kind"),
|
||||
"key_kind",
|
||||
)?,
|
||||
name: row.get("name"),
|
||||
prefix: row.get("prefix"),
|
||||
scopes: deserialize_json_value(row.get::<Value, _>("scopes_json"))?,
|
||||
status: deserialize_enum_text(&row.get::<String, _>("status"), "status")?,
|
||||
created_at: row.get("created_at"),
|
||||
last_used_at: row.get("last_used_at"),
|
||||
expires_at: row.get("expires_at"),
|
||||
allowed_origins: deserialize_json_value(
|
||||
row.get::<Value, _>("allowed_origins_json"),
|
||||
)?,
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -55,12 +66,15 @@ impl PostgresRegistry {
|
||||
id,
|
||||
workspace_id,
|
||||
agent_id,
|
||||
key_kind,
|
||||
name,
|
||||
prefix,
|
||||
scopes_json,
|
||||
status,
|
||||
created_at,
|
||||
last_used_at
|
||||
last_used_at,
|
||||
expires_at,
|
||||
allowed_origins_json
|
||||
from platform_api_keys
|
||||
where workspace_id = $1
|
||||
order by created_at desc",
|
||||
@@ -76,12 +90,20 @@ impl PostgresRegistry {
|
||||
id: PlatformApiKeyId::new(row.get::<String, _>("id")),
|
||||
workspace_id: WorkspaceId::new(row.get::<String, _>("workspace_id")),
|
||||
agent_id: row.get::<Option<String>, _>("agent_id").map(AgentId::new),
|
||||
key_kind: deserialize_enum_text(
|
||||
&row.get::<String, _>("key_kind"),
|
||||
"key_kind",
|
||||
)?,
|
||||
name: row.get("name"),
|
||||
prefix: row.get("prefix"),
|
||||
scopes: deserialize_json_value(row.get::<Value, _>("scopes_json"))?,
|
||||
status: deserialize_enum_text(&row.get::<String, _>("status"), "status")?,
|
||||
created_at: row.get("created_at"),
|
||||
last_used_at: row.get("last_used_at"),
|
||||
expires_at: row.get("expires_at"),
|
||||
allowed_origins: deserialize_json_value(
|
||||
row.get::<Value, _>("allowed_origins_json"),
|
||||
)?,
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -99,19 +121,24 @@ impl PostgresRegistry {
|
||||
k.id,
|
||||
k.workspace_id,
|
||||
k.agent_id,
|
||||
k.key_kind,
|
||||
k.name,
|
||||
k.prefix,
|
||||
k.scopes_json,
|
||||
k.status,
|
||||
k.created_at,
|
||||
k.last_used_at
|
||||
k.last_used_at,
|
||||
k.expires_at,
|
||||
k.allowed_origins_json
|
||||
from platform_api_keys k
|
||||
join workspaces w on w.id = k.workspace_id
|
||||
join agents a on a.id = k.agent_id
|
||||
where w.slug = $1
|
||||
and a.slug = $2
|
||||
and k.secret_hash = $3
|
||||
and k.key_kind = 'mcp_client'
|
||||
and k.status = 'active'
|
||||
and (k.expires_at is null or k.expires_at > now())
|
||||
limit 1",
|
||||
)
|
||||
.bind(workspace_slug)
|
||||
@@ -126,12 +153,17 @@ impl PostgresRegistry {
|
||||
id: PlatformApiKeyId::new(row.get::<String, _>("id")),
|
||||
workspace_id: WorkspaceId::new(row.get::<String, _>("workspace_id")),
|
||||
agent_id: row.get::<Option<String>, _>("agent_id").map(AgentId::new),
|
||||
key_kind: deserialize_enum_text(&row.get::<String, _>("key_kind"), "key_kind")?,
|
||||
name: row.get("name"),
|
||||
prefix: row.get("prefix"),
|
||||
scopes: deserialize_json_value(row.get::<Value, _>("scopes_json"))?,
|
||||
status: deserialize_enum_text(&row.get::<String, _>("status"), "status")?,
|
||||
created_at: row.get("created_at"),
|
||||
last_used_at: row.get("last_used_at"),
|
||||
expires_at: row.get("expires_at"),
|
||||
allowed_origins: deserialize_json_value(
|
||||
row.get::<Value, _>("allowed_origins_json"),
|
||||
)?,
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -150,13 +182,16 @@ impl PostgresRegistry {
|
||||
name,
|
||||
prefix,
|
||||
secret_hash,
|
||||
key_kind,
|
||||
scopes_json,
|
||||
status,
|
||||
created_at,
|
||||
last_used_at,
|
||||
revoked_at
|
||||
revoked_at,
|
||||
expires_at,
|
||||
allowed_origins_json
|
||||
) values (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9::timestamptz, $10::timestamptz, $11::timestamptz
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10::timestamptz, $11::timestamptz, $12::timestamptz, $13::timestamptz, $14
|
||||
)",
|
||||
)
|
||||
.bind(request.api_key.id.as_str())
|
||||
@@ -165,11 +200,14 @@ impl PostgresRegistry {
|
||||
.bind(&request.api_key.name)
|
||||
.bind(&request.api_key.prefix)
|
||||
.bind(request.secret_hash)
|
||||
.bind(serialize_enum_text(&request.api_key.key_kind, "key_kind")?)
|
||||
.bind(Json(serialize_json_value(&request.api_key.scopes)?))
|
||||
.bind(serialize_enum_text(&request.api_key.status, "status")?)
|
||||
.bind(request.api_key.created_at)
|
||||
.bind(request.api_key.last_used_at)
|
||||
.bind(Option::<&str>::None)
|
||||
.bind(request.api_key.expires_at)
|
||||
.bind(Json(serialize_json_value(&request.api_key.allowed_origins)?))
|
||||
.execute(&self.pool)
|
||||
.await;
|
||||
|
||||
|
||||
@@ -8,9 +8,10 @@ use crank_core::{
|
||||
AgentId, AgentOperationBinding, AgentStatus, AgentVersion, ApiKeyHeaderAuthConfig, AuthConfig,
|
||||
AuthKind, AuthProfile, ConfigExport, ExecutionConfig, ExportMode, GeneratedDraft,
|
||||
GeneratedDraftStatus, HttpMethod, InvocationLog, MembershipRole, OperationId,
|
||||
OperationSecurityLevel, OperationStatus, PlatformApiKey, PlatformApiKeyId, PlatformApiKeyScope,
|
||||
PlatformApiKeyStatus, Protocol, RestTarget, RetryPolicy, Samples, SecretId, Target,
|
||||
ToolDescription, ToolExample, User, UserId, UserSessionId, WizardState, Workspace, WorkspaceId,
|
||||
OperationSecurityLevel, OperationStatus, PlatformApiKey, PlatformApiKeyId, PlatformApiKeyKind,
|
||||
PlatformApiKeyScope, PlatformApiKeyStatus, Protocol, RestTarget, RetryPolicy, Samples,
|
||||
SecretId, Target, ToolDescription, ToolExample, User, UserId, UserSessionId, WizardState,
|
||||
Workspace, WorkspaceId,
|
||||
};
|
||||
use crank_mapping::{MappingRule, MappingSet};
|
||||
use crank_schema::{Schema, SchemaKind};
|
||||
@@ -372,12 +373,15 @@ async fn manages_platform_api_key_read_paths() {
|
||||
id: PlatformApiKeyId::new("key_01"),
|
||||
workspace_id: workspace.id.clone(),
|
||||
agent_id: Some(agent.id.clone()),
|
||||
key_kind: PlatformApiKeyKind::McpClient,
|
||||
name: "Primary".to_owned(),
|
||||
prefix: "crk_live".to_owned(),
|
||||
scopes: vec![PlatformApiKeyScope::Read, PlatformApiKeyScope::Write],
|
||||
status: PlatformApiKeyStatus::Active,
|
||||
created_at: timestamp("2026-03-25T12:01:00Z"),
|
||||
last_used_at: None,
|
||||
expires_at: None,
|
||||
allowed_origins: Vec::new(),
|
||||
};
|
||||
let secret_hash = "secret_hash_01";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user