fix: improve MCP page setup UX and remove automation credit quotas (#821)
* Remove MCP credit quotas and improve MCP setup page - Always show client setup snippets with placeholder keys - Add View Docs link to MCP page header - Remove monthly automation credit enforcement and UI - Update plan feature text to reflect free MCP access Co-authored-by: Rotimi Best <[email protected]> * fix: address PR review feedback for MCP page changes - Clear generatedSecret when revoking MCP keys - Use Button link mode for View Docs with rel noopener noreferrer - Update all dashboard locale files for MCP translations - Make MCP rate-limit admission atomic with transactional reservations - Wrap MCP route handlers with withMcpAutomationUsage helper Co-authored-by: Rotimi Best <[email protected]> * revert: remove atomic MCP rate-limit reservations The transactional advisory-lock reservation was unnecessary complexity for our MCP usage model. Restore the simpler check-then-record flow. Also only clear generatedSecret when revoking the key it belongs to. Co-authored-by: Rotimi Best <[email protected]> * fix: address remaining MCP page bot review feedback - Add blank lines after confirm guards in key handlers - Skip showing rotated secret if key was revoked during rotation - Fix vi keys_title and de rate_limits_title translations Co-authored-by: Rotimi Best <[email protected]> * fix: prevent late key rotation from un-revoking or exposing secrets - Rotate only when revoked_at IS NULL at update time (DB) - Reject rotate requests for already-revoked keys (API) - Ignore stale rotate responses in automation client state - Guard MCP UI against showing secrets for revoked keys Co-authored-by: Rotimi Best <[email protected]> ---------
This commit is contained in:
co-authored by
Rotimi Best
parent
1cb752d229
commit
9fb75e11d2
@@ -119,3 +119,33 @@ export const updateOrganizationApiKey = async (
|
||||
throw new Error('Failed to update organization API key');
|
||||
}
|
||||
};
|
||||
|
||||
export const rotateOrganizationApiKeyIfActive = async (
|
||||
organizationId: string,
|
||||
keyId: string,
|
||||
data: Pick<TOrganizationApiKey, 'secretPrefix' | 'secretHash'>
|
||||
): Promise<TOrganizationApiKey | null> => {
|
||||
try {
|
||||
const [row] = await db
|
||||
.update(schema.organizationApiKey)
|
||||
.set({
|
||||
secretPrefix: data.secretPrefix,
|
||||
secretHash: data.secretHash,
|
||||
lastUsedAt: null,
|
||||
updatedAt: new Date().toISOString()
|
||||
})
|
||||
.where(
|
||||
and(
|
||||
eq(schema.organizationApiKey.organizationId, organizationId),
|
||||
eq(schema.organizationApiKey.id, keyId),
|
||||
isNull(schema.organizationApiKey.revokedAt)
|
||||
)
|
||||
)
|
||||
.returning();
|
||||
|
||||
return row || null;
|
||||
} catch (error) {
|
||||
console.error('rotateOrganizationApiKeyIfActive error:', error);
|
||||
throw new Error('Failed to rotate organization API key');
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user