mirror of
https://github.com/hansjone/dsh-ops-cron.git
synced 2026-10-09 03:03:18 +08:00
Isolate IM cron tools and trust-gate read APIs.
Scope list/pause/delete to the calling chat, bind IM delivery to that peer, ignore client job ids, require trusted Host for GETs, and wrap mirrored summaries as system reminders. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
29d946f3dd
commit
67238d746e
7 changed files with 222 additions and 29 deletions
18
lib/host.js
18
lib/host.js
|
|
@ -178,9 +178,11 @@ export function createHostService(options = {}) {
|
|||
|
||||
async function createJob(input) {
|
||||
const t = now()
|
||||
// Ignore client-supplied ids on create — otherwise POST/tools can overwrite.
|
||||
const { id: _ignoredId, ...safeInput } = input && typeof input === 'object' ? input : {}
|
||||
let created
|
||||
await withState((current) => {
|
||||
created = createJobRecord(input, current, t)
|
||||
created = createJobRecord(safeInput, current, t)
|
||||
return upsertJob(current, created)
|
||||
})
|
||||
return jobView(created)
|
||||
|
|
@ -389,6 +391,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/settings` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const state = await snapshot()
|
||||
write(200, { ok: true, settings: state.settings })
|
||||
return
|
||||
|
|
@ -403,6 +406,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/models` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const catalog = typeof sessionPort?.listModels === 'function'
|
||||
? await sessionPort.listModels()
|
||||
: { groups: [], current: null }
|
||||
|
|
@ -411,6 +415,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/presets` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const catalog = typeof sessionPort?.listPresets === 'function'
|
||||
? await sessionPort.listPresets()
|
||||
: { items: [], current: null }
|
||||
|
|
@ -419,6 +424,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/workspaces` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const workspaces = typeof sessionPort?.listWorkspaces === 'function'
|
||||
? await sessionPort.listWorkspaces()
|
||||
: []
|
||||
|
|
@ -427,6 +433,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/im-catalog` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const dshIm = getDshIm()
|
||||
if (!dshIm || typeof dshIm.listDeliveryCatalog !== 'function') {
|
||||
write(200, {
|
||||
|
|
@ -456,6 +463,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/jobs` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const state = await snapshot()
|
||||
write(200, { ok: true, jobs: listJobs(state).map(jobView) })
|
||||
return
|
||||
|
|
@ -474,6 +482,7 @@ export function createHostService(options = {}) {
|
|||
const jobId = decodeURIComponent(jobMatch[1])
|
||||
const rest = jobMatch[2] || ''
|
||||
if (method === 'GET' && !rest) {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const state = await snapshot()
|
||||
const job = getJob(state, jobId)
|
||||
if (!job) return write(404, { ok: false, error: 'job not found' })
|
||||
|
|
@ -545,6 +554,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/history` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const state = await snapshot()
|
||||
const jobId = url.searchParams.get('jobId') || undefined
|
||||
write(200, { ok: true, runs: listHistory(state, jobId).map(runView) })
|
||||
|
|
@ -552,6 +562,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/preview` && method === 'POST') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const body = await readJsonBody(req)
|
||||
const settings = (await snapshot()).settings
|
||||
const schedule = validateSchedule(body.schedule || body, body.timezone || settings.timezone)
|
||||
|
|
@ -561,6 +572,7 @@ export function createHostService(options = {}) {
|
|||
}
|
||||
|
||||
if (path === `${API_PREFIX}/workspace-visible` && method === 'GET') {
|
||||
if (!isTrustedApiRequest(req)) return write(403, { ok: false, error: 'forbidden' })
|
||||
const state = await snapshot()
|
||||
const listed = url.searchParams.getAll('id')
|
||||
write(200, {
|
||||
|
|
@ -601,6 +613,10 @@ export function createHostService(options = {}) {
|
|||
async listJobs() {
|
||||
return listJobs(await snapshot()).map(jobView)
|
||||
},
|
||||
async getJob(jobId) {
|
||||
const job = getJob(await snapshot(), jobId)
|
||||
return job ? jobView(job) : null
|
||||
},
|
||||
async listHistory(jobId) {
|
||||
return listHistory(await snapshot(), jobId).map(runView)
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue