coffer
Available
Owner-run donor records and giving for a US nonprofit: donors and households, an immutable gift ledger with pledges and soft credits, Stripe card and monthly gifts, emailed receipts, letters and year-end statements, and a checked Little Green Light move-in.
coffer is available as MIT-licensed source for self-hosting. See its public source and release documents for setup. Run Edit Run installation and hosted service are not offered for this project.
Run coffer on your own computer with one line:
npx -y @runeditrun/rer dev just-every/run-coffer
It clones the public source, installs it, sets up a local owner and starts the app; nothing is deployed. To set up without starting, run npx -y @runeditrun/rer setup just-every/run-coffer. Without Node 22 or later, run curl -fsSL https://runeditrun.com/install.sh | sh -s -- dev just-every/run-coffer.
For HappyToHelp: Assisted is in early access; Managed is waitlist only.
- Category
- status
- Licence
- MIT
- Version
0.1.0- Requirements
- 9 clauses
- Release signature
- Signed by just-every · key
rer-ed25519-5a42fb9c9c4f8acb2b32386e9e40461c· statement - Target release
- v0.1.0 · published
- Publisher’s stage
- first release; independently gated on a computer and a hosted Cloudflare Worker on 18 October 2026
Outside services
The services the project declares it sends data to, each with its reason.
cloudflare- Worker hosting
Scope and limits
What it will not do
- US bank (ACH) checkout, PayPal, Venmo and text-to-give
- Sending notes to the family for tribute gifts
- A live QuickBooks Online connection
- Native phone apps
- Prospect research, grants and planned giving
- Tax advice or non-cash gift valuation
Declared limits
- Status
- unmeasured
Requirements
All 9 clauses of coffer’s CONTRACT.md. They say what the project must do; the handover and verification records say what is built and tested.
HTTP-001Private app boundary Hono serves/healthand owns/api; native owner/operator sessions protect/appand/api/coffer. Every handler checks the actor's role, the exact host and, for cookie changes, the sameOrigin. Each write batch re-checks the session or key inside the same D1 transaction, so a revoked session, role change or revoked key stops a request in flight. Unknown paths return real 404s. Public donor-facing pages added by the target (GIVE-001,GIVE-005,CAMP-002) live outside/appunder their own rules and never widen this boundary. Acceptance: The role-boundary test signs in as owner, member and agent, sends cross-origin writes, revokes a key and deactivates a member, and every refused request returns 401 or 403. Status: done. Evidence:tests/coffer.test.mjs,src/coffer/auth.ts.DONOR-001Donors and households A donor has an email (or none) that no unrelated record shares. A household is found by name or created. Several emails, phones and postal addresses per constituent with one primary of each, and an email shared by members of one household, areDONOR-013; a person's name parts, salutations and envelope name areDONOR-014. Members, admins and the owner add and edit donors; edits are versioned, and a stale version is refused rather than overwritten. Acceptance: A member adds donors through HTTP and the browser journey adds, edits and opens donors; the donor page lists household members. Status: done. Evidence:src/coffer/donors.ts,tests/coffer.test.mjs,tests/browser-journey.mjs.GIFT-001Immutable ledger A gift is an integer-cent line with its date, method, fund, optional pledge and goods-or-services answer. Database triggers refuse changes to amounts, dates, donors or references; a correction is a reversal line of the opposite amount, once per gift. Dollar input is parsed exactly; the API takes<field>Centsfor exact integers. Every later gift kind in this contract (online, recurring, split, soft-credited, in-kind, refunded) is written as lines in this one ledger. Acceptance: The ledger test records exact-cent gifts, refuses sub-cent, future-dated and duplicate-reference gifts, reverses one once and reads the lifetime and per-year totals back. Status: done. Evidence:src/coffer/gifts.ts,migrations/core/0016_coffer.sql,tests/coffer.test.mjs.CONSENT-001Consent history Consent is append-only per donor and channel with method, evidence, capture date and who recorded it; the newest row is the current answer. Rows are removed only by erasure. The target adds SMS and phone channels, donor self-service changes and sender-synced unsubscribes as further rows of this same history (COMM-001). Acceptance: The appeal test records grants and withdrawals for several donors and channels and the donor history shows the newest answer per channel. Status: done. Evidence:src/coffer/donors.ts,tests/coffer.test.mjs.ACK-001Acknowledgement letters Gifts at or over the threshold (default $250) without a live letter are due within the target days (default 14). No letter is prepared until a person has saved the settings; the letter must state donor name, amount, gift date, organization and the goods-or-services statement. A batch freezes its letters and content hash. A person approves the exact hash; export, then a recorded sent date. Imported gifts with an unknown goods answer wait for a person's answer.RCPT-011and the importers widen this: an imported gift takes its goods answer from the source's non-deductible amount (MOVE-001toMOVE-006), so only a gift whose source holds no answer waits; and a gift is due only while its acknowledgement status is "not acknowledged", so a gift acknowledged in Coffer or in the incumbent before the move, marked do not acknowledge, or received before the acknowledge-from date (MOVE-007) is never due or overdue, and recording a batch's sent date marks each of its gifts acknowledged by letter with the batch linked. This is the reviewed letter path for printed and hand-mailed acknowledgements; delivering the same approved letters by email isRCPT-002, print layouts areRCPT-003and one letter per household isRCPT-009. Acceptance: The acknowledgement test has an agent prepare a batch, refuses preparation before settings are reviewed, lets only a person approve, exports the CSV with the exact letter text and records the sent date. Status: done. Evidence:src/coffer/acknowledgements.ts,src/coffer/settings.ts,tests/coffer.test.mjs.APPEAL-001Consent-checked appeals An audience includes only donors whose newest consent for the channel is yes and who have the needed address; exclusions are counted by reason. Each recipient is frozen with the exact consent row; approval, export and sending refuse if any of those rows is no longer current. Sending the approved audience through Mango or Mailchimp isCOMM-002; this clause is the consent gate every send passes. Excluding inactive and deceased constituents isDONOR-012; excluding constituents with a solicitation restriction under the reason "do not solicit", and deliberately including one in a run, isDONOR-015; and one piece per household isRCPT-009. Acceptance: The appeal test prepares an audience, counts exclusions by reason, refuses approval after a withdrawal and exports only consenting recipients. Status: done. Evidence:src/coffer/appeals.ts,tests/coffer.test.mjs.AGENT-001Prepare, then a person decides An expiring, revocable bearer key reads records and runs onlyack.prepareandappeal.prepare. Approvals keep the preparer's and approver's identity and role with the content hash. Wider, separately granted agent work isDEV-012; no agent key gains an action this clause does not name unless that grant says so. Acceptance: The role-boundary and acknowledgement tests create a key, prepare with it, are refused every other command, record agent and owner roles on the approval and stop working on revocation. Status: done. Evidence:src/coffer/commands.ts,src/coffer/auth.ts,tests/coffer.test.mjs.IMPORT-001Reviewed Stripe move-in Saved Stripe customer and charge list pages go through Base's import kit. Preview writes nothing; apply needs the exact reviewed fingerprint; the journal retains the original pages; undo stops at anything a person has since built on. Failed, refunded, non-USD, duplicate and already-imported objects are skipped with reasons and never enter the plan. This saved-page path stays for history a live connection (PAY-001) is not granted, and for nonprofits that never give Coffer API access. Acceptance: The move-in test previews 15 gifts with every skip reason, refuses a wrong fingerprint, applies, reads the journal and undoes; a second test proves undo stops at a donor a person has since changed. Status: done. Evidence:src/coffer/imports/service.ts,src/coffer/imports/snapshots.ts,tests/coffer.test.mjs.DATA-001Custody and erasure Base portability backs up product records, approvals and import custody, excluding identity and credentials, and restores only into an empty installation. A hosted Coffer backs up and restores the same archive withrer run backup:hosted, authenticated by the owner's session; its restore goes only into a newly deployed, empty environment and keeps that environment's own owner. The owner erases a donor with explicitERASE: personal data, consent, letter text, gift notes and affected Stripe originals go; gifts move to an anonymous placeholder; hashed suppression stops re-import; a later journal fences older archives. Every record the target adds (interactions, tasks, opportunities, receipts, provider events) joins the same backup and the same erasure. Acceptance: The backup test restores into a fresh installation and compares donor histories and approvals; the hosted-restore test backs up through the command, restores into a fresh installation with large retained originals, keeps the destination owner and refuses a second restore; the erasure tests remove personal data, keep anonymous gifts, refuse re-import and fence an older archive. Status: done. Evidence:src/coffer/archive-policy.mjs,src/coffer/imports/erasure.ts,scripts/backup-hosted.mjs,tests/coffer.test.mjs,tests/hosted-restore.test.mjs.
View as agent
Everything on this page is in these files, copied unmodified from the release. An agent evaluating coffer can read them instead of the page.
seed.json- The manifest: capabilities, outside services, extension points, limits, operating cost and deployment needs.
CONTRACT.md- The requirements on this page, in source form.
AGENTS.md- Instructions for the coding agent that maintains an installation.
README.md- Source setup, available commands and implementation status.
OPERATIONS.md- How the project is set up, operated and deployed.
ACCEPTANCE.md- What the publisher accepts as a finished release.
Every project, with its availability, is in /agents/catalogue.json; the agents page describes the machine-readable files.