Split MCP and approval agent keys

This commit is contained in:
github-ops
2026-06-24 10:31:52 +00:00
parent d739f17393
commit 5922aea68f
16 changed files with 471 additions and 56 deletions
+17 -1
View File
@@ -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 (
+43 -5
View File
@@ -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;