Browse the docs
Examples
Approvals example
A team approvals tool. Workspace members as approvers, email on submit and decision, and a weekday digest schedule.
bunx @revnu/fuast new approvals --template approvalsAnyone in the workspace submits a request with an amount and a reason. An approver approves or rejects it with an optional note. Both sides get email, and a weekday digest reminds approvers of anything still pending.
What it shows
auth: { requireSignIn: true }for a workspace tool.- Approvers from
ctx.workspace.members(), optionally narrowed byAPPROVER_EMAILSin env. submitemails approvers.decidechecks that the caller is an approver, is not the submitter, and that the request is still pending, then emails the submitter. Email is always the last step.- A
digestschedule at0 9 * * 1-5(09:00 UTC on weekdays), plussendDigestNow, which runs the same helper on demand for testing. - WebMCP tools on
submit,decide,mine, andqueue, so a browser agent can file and decide requests. submitterIdanddeciderIddeclared asuserId(), and names stored as snapshots.
Workspace members as approvers
async function approvers(ctx: TeamContext): Promise<Member[]> {
const members = await ctx.workspace.members();
const allowed = parseEmailList(ctx.env.APPROVER_EMAILS);
if (allowed.length === 0) return members;
return members.filter((m) => allowed.includes(m.email.toLowerCase()));
}The same helper runs in queries (to show the queue), mutations (to authorize decisions), and the schedule (to address the digest). Schedules may call ctx.workspace.members() even though they have no caller.
The digest
schedules: {
digest: schedule("0 9 * * 1-5", async (ctx) => {
await sendDigest(ctx);
})
}sendDigest reads up to 100 pending requests through the by_status index and emails each approver once. It never calls ctx.auth guards, because schedules run as the system. See schedules.
Configure
# .env.fuast.server
APPROVER_EMAILS=finance@acme.com,cto@acme.comWithout it, every workspace member can decide anyone else's request. For the hosted app, set it in the dashboard Env tab or deploy the file.
Try it
bunx @revnu/fuast devSubmit as dev, approve as ?fuast_user=alice, and read the emails with bunx @revnu/fuast logs --port 3000. Click "Email digest now" to test the digest. Then:
bunx @revnu/fuast deploy
bunx @revnu/fuast share --visibility workspace