feat(ql3): add secure console cron scheduling

This commit is contained in:
whyour
2026-08-29 17:13:09 +08:00
parent 951de26ffd
commit b970e2aede
30 changed files with 1916 additions and 31 deletions
@@ -43,6 +43,8 @@ export type LocalProfileStorageBootstrapResult =
readonly taskStartRepository: LocalSqliteRuntimeDatabase['taskStartRepository'];
readonly taskDefinitions: LocalSqliteRuntimeDatabase['taskDefinitions'];
readonly taskDefinitionAdministrationForCredential: LocalSqliteRuntimeDatabase['taskDefinitionAdministrationForCredential'];
readonly triggers: LocalSqliteRuntimeDatabase['triggers'];
readonly triggerAdministrationForCredential: LocalSqliteRuntimeDatabase['triggerAdministrationForCredential'];
readonly schedules: LocalSqliteRuntimeDatabase['schedules'];
readonly dispatch: LocalSqliteRuntimeDatabase['localDispatch'];
readonly executionControl: LocalSqliteRuntimeDatabase['executionControl'];
@@ -141,6 +143,9 @@ export async function bootstrapLocalProfileStorage(
taskDefinitions: database.taskDefinitions,
taskDefinitionAdministrationForCredential:
database.taskDefinitionAdministrationForCredential,
triggers: database.triggers,
triggerAdministrationForCredential:
database.triggerAdministrationForCredential,
schedules: database.schedules,
dispatch: database.localDispatch,
executionControl: database.executionControl,
@@ -37,6 +37,7 @@ import type { StepRunRepository } from '@qinglong/runtime-core/step-run';
import type { RunCancellationRepository } from '@qinglong/runtime-core/run-cancellation';
import type { TaskStartRepository } from '@qinglong/runtime-core/task-start';
import type { TaskDefinitionAdministrationRepository } from '@qinglong/runtime-core/task-definition-administration';
import type { TriggerAdministrationRepository } from '@qinglong/runtime-core/trigger-administration';
import type { ToolExecutionCompletionRepository } from '@qinglong/runtime-core/tool-execution-completion';
import type { ToolExecutionFailureCompletionRepository } from '@qinglong/runtime-core/tool-execution-failure-completion';
import type { ToolExecutionStartBarrierRepository } from '@qinglong/runtime-core/tool-execution-start-barrier';
@@ -102,6 +103,9 @@ export interface LocalSqliteRuntimeDatabase {
fence: Readonly<LocalSqliteAuthenticatedUserCredentialFence>,
): Promise<TaskDefinitionAdministrationRepository>;
readonly triggers: LocalSqliteTriggerRepository;
triggerAdministrationForCredential(
fence: Readonly<LocalSqliteAuthenticatedUserCredentialFence>,
): Promise<TriggerAdministrationRepository>;
readonly schedules: LocalSqliteScheduleRepository;
readonly localDispatch: LocalDispatchStore;
readonly executionControl: LocalExecutionControlSource;
@@ -284,6 +288,37 @@ export async function openLocalSqliteRuntimeDatabase(
);
},
triggers,
async triggerAdministrationForCredential(
fence: Readonly<LocalSqliteAuthenticatedUserCredentialFence>,
) {
const [administration, triggerAdministration] = await Promise.all([
import('../administration/packageManagement.js'),
import('../scheduling/triggerAdministration.js'),
]);
const {
confirmLocalSqliteAuthenticatedUserCredentialFence,
LocalSqliteAuthenticatedManagementFenceError,
} = administration;
const { LocalSqliteTriggerAdministrationRepository } =
triggerAdministration;
confirmLocalSqliteAuthenticatedUserCredentialFence(authority, fence);
return new LocalSqliteTriggerAdministrationRepository(
authority,
triggers,
(actor) => {
if (
actor.type !== fence.subjectType ||
actor.id !== fence.subjectId
) {
throw new LocalSqliteAuthenticatedManagementFenceError();
}
confirmLocalSqliteAuthenticatedUserCredentialFence(
authority,
fence,
);
},
);
},
schedules,
localDispatch: runRuntimeCapabilities.dispatch,
executionControl: runRuntimeCapabilities.executionControl,
@@ -97,7 +97,7 @@ function sameCredentialFence(
);
}
class LocalSqliteTriggerAdministrationRepository
export class LocalSqliteTriggerAdministrationRepository
implements TriggerAdministrationRepository
{
constructor(