← Public packages
@charlesmatte/granola
Search and read Granola meeting notes, summaries and transcripts from any agent; manage webhooks and legal holds safely.
src/legal-holds/release.ts
38 lines · 2.1 KB · TypeScriptimport { mutationSpec, parseWithAccount } from '../lib/api.ts'
import { granolaRequest } from '../lib/client.ts'
import { echo, mutationMode, preview } from '../lib/guard.ts'
import { getHold } from '../lib/holds.ts'
import { HOLD_ID_PATTERN } from '../lib/validate.ts'
/**
* Release a legal hold (`DELETE /v1/legal-holds/{hold_id}`). TERMINAL: there is no un-release
* (a reopened matter needs a new hold); once no active hold covers a person, Granola's normal
* deletion rules apply to their notes again. Releasing twice returns the original `released_at`.
* WRITE: previews unless `confirm: true` (the preview shows the hold being released).
*
* @param input.account - Account whose secret holds a Legal hold API key. Required. @param input.secretName - Secret override.
* @param input.holdId - `lgh_…` id. Required.
* @param input.dryRun - Preview only. @param input.confirm - `true` to release.
* @returns Preview `{ dryRun: true, current, request }`, or `{ executed: true, result: { id, released: true, released_at } }`
*
* @example
* import releaseHold from 'kody:@charlesmatte/granola/legal-holds/release'
*
* const preview = await releaseHold({ account: 'work-legal', holdId: 'lgh_Abc123XyZ456Dq' })
*/
export default async function releaseGranolaLegalHold(input: unknown) {
const p = parseWithAccount<{ holdId: string; dryRun?: boolean; confirm?: boolean }>(
input,
{ holdId: { type: 'string', required: true, pattern: HOLD_ID_PATTERN }, ...mutationSpec },
'legal-holds/release',
)
const mode = mutationMode(p)
const path = `/v1/legal-holds/${p.holdId}`
const target = `legal hold ${p.holdId} (terminal release)`
if (!mode.execute) {
const current = await getHold(p.acct, p.holdId).catch((e) => `lookup failed: ${String(e?.message ?? e).slice(0, 200)}`)
return preview(p.acct, 'legal-holds/release', target, mode, { method: 'DELETE', path }, { current, warning: 'Release is permanent; there is no un-release.' })
}
const res = await granolaRequest(p.acct, { method: 'DELETE', path, retries: 1 })
return { dryRun: false, executed: true, echo: echo(p.acct, 'legal-holds/release', target, mode), result: res.data }
}