attest
uses Buffer
tcm lib attest: write a review, an advisory or (a release's author's) a yank, about what, to the signed-in
account's repository.
import { atprotoSession } from "#codebase/tcmts/atproto"; import { ANNOUNCE_SCOPE } from "#codebase/tcmts/cli/announce"; import { attestationSubject, writeAttestation } from "#codebase/tcmts/cli/attest"; import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { bold, dim, green } from "#codebase/tcmts/cli/style"; import { UsageError } from "#codebase/tcmts/cli/ui"; import { shortHash } from "#codebase/tcmts/core/hash"; import { ATTESTATION_KINDS, SEVERITIES } from "#codebase/tcmts/records"; import type { AttestationKind } from "#codebase/tcmts/records"; export async function attest( cb: Codebase, m: { what: string; kind: string; message: string | undefined; severity: string | undefined; "fixed-in": string | undefined; as: string | undefined; }, ): Promise<void> { if (!(m.kind in ATTESTATION_KINDS)) throw new UsageError(`'${m.kind}' isn't a kind of attestation: review, advisory or yank`); const kind = m.kind as AttestationKind; const severity = SEVERITIES.find((s) => s === m.severity); if (kind === "advisory" && !severity) throw new UsageError(`an advisory says how bad it is: --severity ${SEVERITIES.join("|")}`); if (kind !== "advisory" && (m.severity || m["fixed-in"])) throw new UsageError("--severity and --fixed-in are an advisory's"); if (kind !== "review" && !m.message?.trim()) throw new UsageError( `a${kind === "advisory" ? "n advisory" : " yank"} says what it's about: -m <text>`, ); // (as its lexicon says) if (Buffer.byteLength(m.message?.trim() ?? "") > 30000) throw new UsageError("-m: an attestation says at most 30000 bytes"); if ((m["fixed-in"]?.length ?? 0) > 64) throw new UsageError("--fixed-in: a version, at most 64 characters"); const subject = await attestationSubject(cb, m.what); const session = await atprotoSession({ who: m.as, scope: ANNOUNCE_SCOPE, why: `attesting writes a record to your AT Protocol repository`, }); if (kind === "yank" && subject.author && subject.author !== session.did) throw new UsageError( `only its author can yank ${subject.release ?? "a release"}: they're ${subject.author}, and you're signed in as ${session.handle ? `@${session.handle}` : session.did} (an advisory says what's wrong with it)`, ); const uri = await writeAttestation(session, { kind, subject: kind === "yank" && !subject.author ? { ...subject, author: session.did } : subject, body: m.message?.trim() ?? "", ...(severity ? { severity } : {}), ...(m["fixed-in"] ? { fixedIn: m["fixed-in"] } : {}), createdAt: new Date().toISOString(), }); const verb = { review: "reviewed", advisory: "wrote an advisory about", yank: "yanked" }[kind]; console.log( `${green(verb)} ${bold(subject.release ?? shortHash(subject.namespace))} ${dim(`(${shortHash(subject.namespace)})`)} as ${session.handle ? `@${session.handle}` : session.did}: ${uri}`, ); }
uses
- tcmts.atproto.atprotoSession
- tcmts.cli.announce.ANNOUNCE_SCOPE
- tcmts.cli.attest.attestationSubject
- tcmts.cli.attest.writeAttestation
- tcmts.cli.codebase.Codebase
- tcmts.cli.style.bold
- tcmts.cli.style.dim
- tcmts.cli.style.green
- tcmts.cli.ui.UsageError
- tcmts.core.hash.shortHash
- tcmts.records.ATTESTATION_KINDS
- tcmts.records.AttestationKind
- tcmts.records.SEVERITIES