Root cause of the recurring 401: a revoked key was hardcoded in startup-recovery.ts and onboarding-service.ts and reseeded into composio_settings on every launch, and the interim fix shipped cred.txt as a visible file under resources/. - electron.vite.config.ts reads the gitignored cred.txt at build time and injects the key into the main-process bundle as __COMPOSIO_API_KEY__; no credential file is packaged and the key is not user-visible or configurable. The renderer bundle never sees it. - Delete both hardcoded-key seeders; migration 046 purges stored api_key and never-read toolkits rows while keeping entity_id and auth_config state. - Stop shipping composio_settings in the renderer snapshot.
40 lines
1.7 KiB
TypeScript
40 lines
1.7 KiB
TypeScript
import type { DatabaseSync } from "node:sqlite";
|
|
import { AuditService } from "../services/audit-service";
|
|
|
|
const INTERRUPTED_MESSAGE = "Interrupted by application shutdown before completion.";
|
|
|
|
/**
|
|
* A single app instance executes runs in-process, so any task_run still
|
|
* `running` at boot was interrupted by a previous shutdown and has no
|
|
* executor. The run returns to the queue — interruption is not failure, so
|
|
* the work continues without spending the task's retry budget — and the
|
|
* queue worker claims it within one tick. In-flight provider requests from
|
|
* the dead process cannot be resumed: foreground ones fail, and background
|
|
* ones fail only when they never received the external response id the
|
|
* provider background worker needs to resume them.
|
|
*/
|
|
export function recoverInterruptedWork(db: DatabaseSync): void {
|
|
const now = new Date().toISOString();
|
|
const audit = new AuditService(db);
|
|
const runs = db.prepare("select id, org_id, task_id from task_runs where state = 'running'")
|
|
.all() as Array<{ id: string; org_id: string; task_id: string }>;
|
|
for (const run of runs) {
|
|
db.prepare("update task_runs set state = 'queued', started_at = null where id = ?").run(run.id);
|
|
audit.record({
|
|
orgId: run.org_id,
|
|
entityType: "task_run",
|
|
entityId: run.id,
|
|
actorType: "system",
|
|
actorId: null,
|
|
action: "requeued",
|
|
payload: { taskId: run.task_id, reason: "interrupted_by_shutdown" },
|
|
});
|
|
}
|
|
db.prepare(`
|
|
update provider_requests
|
|
set state = 'failed', completed_at = ?, error_message = ?
|
|
where state in ('pending', 'streaming')
|
|
and (execution_mode = 'foreground' or external_response_id is null)
|
|
`).run(now, INTERRUPTED_MESSAGE);
|
|
}
|