refactor(quota): secure managed provider credentials (#2160)

- add shared owner-only credential storage for OpenCode Go, Ollama Cloud, and Cursor
- validate credentials before atomic writes using 0700 directories and 0600 files
- replace provider-specific credential routes with an allowlisted lifecycle API
- stop automatically reading Ollama's legacy cookie file
- stop reading or modifying Cursor's database during regular quota requests
- add explicit one-time Cursor credential import without mutating Cursor storage
- persist refreshed Cursor credentials only in OpenChamber-managed storage
- add Ollama Cloud and Cursor credential controls to provider settings
- preserve OpenCode Go tracking through the shared credential flow
- add VS Code credential management and Cursor quota parity
- reject authentication redirects, enforce request timeouts, and fail on unparseable usage pages
- mask stored secrets in API responses and extend quota security coverage
- update quota provider documentation
This commit is contained in:
Bohdan Triapitsyn
2026-07-12 16:21:38 +03:00
committed by GitHub
parent 3b92d97795
commit b09614fd68
20 changed files with 431 additions and 368 deletions
@@ -1,26 +1,11 @@
import { homedir } from 'os';
import { readFileSync, existsSync } from 'fs';
import { join } from 'path';
import { buildResult, toUsageWindow, toNumber } from '../utils/index.js';
const COOKIE_PATH = join(homedir(), '.config', 'ollama-quota', 'cookie');
import { readManagedCredential } from '../credentials/providers.js';
export const providerId = 'ollama-cloud';
export const providerName = 'Ollama Cloud';
const aliases = ['ollama-cloud', 'ollamacloud'];
const readCookieFile = () => {
try {
if (!existsSync(COOKIE_PATH)) return null;
const content = readFileSync(COOKIE_PATH, 'utf-8');
const trimmed = content.trim();
return trimmed || null;
} catch {
return null;
}
};
const parseOllamaSettingsHtml = (html) => {
export const parseOllamaSettingsHtml = (html) => {
const windows = {};
const sessionMatch = html.match(/Session\s+usage[^0-9]*([0-9.]+)%/i);
if (sessionMatch) {
@@ -54,14 +39,29 @@ const parseOllamaSettingsHtml = (html) => {
};
export const isConfigured = () => {
const cookie = readCookieFile();
return Boolean(cookie);
return Boolean(readManagedCredential(providerId));
};
export const fetchOllamaCloudUsage = async (credential, fetchImpl = fetch) => {
const response = await fetchImpl('https://ollama.com/settings', {
method: 'GET',
headers: { Cookie: credential.cookie, 'User-Agent': 'OpenChamber quota provider' },
redirect: 'manual',
signal: AbortSignal.timeout(15_000),
});
if (response.status === 401 || response.status === 403 || (response.status >= 300 && response.status < 400)) {
throw new Error('Ollama Cloud authentication failed');
}
if (!response.ok) throw new Error(`Ollama Cloud returned HTTP ${response.status}`);
const windows = parseOllamaSettingsHtml(await response.text());
if (Object.keys(windows).length === 0) throw new Error('Ollama Cloud usage data could not be parsed');
return windows;
};
export const fetchQuota = async () => {
const cookie = readCookieFile();
const credential = readManagedCredential(providerId);
if (!cookie) {
if (!credential) {
return buildResult({
providerId,
providerName,
@@ -72,26 +72,7 @@ export const fetchQuota = async () => {
}
try {
const response = await fetch('https://ollama.com/settings', {
method: 'GET',
headers: {
Cookie: cookie,
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
}
});
if (!response.ok) {
return buildResult({
providerId,
providerName,
ok: false,
configured: true,
error: `API error: ${response.status}`
});
}
const html = await response.text();
const windows = parseOllamaSettingsHtml(html);
const windows = await fetchOllamaCloudUsage(credential);
return buildResult({
providerId,
@@ -109,4 +90,4 @@ export const fetchQuota = async () => {
error: error instanceof Error ? error.message : 'Request failed'
});
}
};
};