关于 Charitology public research
Charitology public research 是检索已发布慈善研究、非营利组织福利及其来源的服务。它展示审核状态和权利信息,不对具名慈善机构评级,也不声称影响已获验证。
主要功能
- 01搜索已发布的慈善研究
- 02查找非营利组织福利
- 03查看来源引用
- 04查看审核状态与权利
适用场景
- 01使用已发布来源研究慈善相关问题
- 02核查条目的审核状态和权利信息
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://os.charitology.org/mcpclaude mcp add --transport http theguysaccount-charitology https://os.charitology.org/mcp{"mcpServers":{"theguysaccount-charitology":{"type":"http","url":"https://os.charitology.org/mcp"}}}在 Cursor 中打开{"servers":{"theguysaccount-charitology":{"type":"http","url":"https://os.charitology.org/mcp"}}}在 VS Code 中打开{"mcpServers":{"theguysaccount-charitology":{"type":"http","url":"https://os.charitology.org/mcp"}}}{"mcpServers":{"theguysaccount-charitology":{"serverUrl":"https://os.charitology.org/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
Shared Charity OS
一个用于协调慈善工作的组织工作区,与公开的 Astro 网站和本地浏览器工作区相互独立,作为单独的服务构建。它整合了类型化记录、责任明确的负责人、关联工作流、独立审核和私密恢复工具。慈善学研究引导慷慨行为的系统;它不对具名慈善机构评分,也不评判人们所做的善事。项目的可选深度值是对作用机制的一种假设,而不是评分。
这是一个基于 Node 24 ESM 的服务,配有纯 JavaScript 浏览器客户端、Postgres 数据库和 Better Auth 魔法链接会话。依赖项已在 package.json 和 package-lock.json 中锁定。详细的领域规则见 MODULES.md;源代码和回归审核见 BACKEND_REVIEW.md。
服务功能
全部 26 个模块共用类型化表单、关联记录、表格/看板视图、适用的日历视图、所有权、修订、评论和工作流。注册表目前包含 339 个字段。字段定义和验证规则位于 modules.mjs 中,而不是采用可互换的自由文本表单。
| 领域 | 模块 ID |
|---|---|
| 基金会 | organization、integrations、administration |
| 项目与学习 | programs、projects、outcomes、feedback、evaluation |
| 资金与财务 | grant-seeking、grant-delivery、finance、accounting、fundraising |
| 人员与参与 | contacts、memberships、volunteers、events、communications、forms |
| 受限协调 | casework、safeguarding |
| 治理与记录 | reporting、governance、documents |
| 运营 | assets、resources |
规则涵盖依赖循环、分配和拨款上限、限制代码、货币匹配、志愿者/活动容量、轮班重叠、证据单位和分母、外部来源身份及资格条件。未知值保持为 null,与零和 false 明确区分。金额使用整数最小货币单位,并明确指定货币和精度。预定时间点必须包含书面 UTC 时差,并与指定时区相匹配。
会计和薪资记录用于保存外部引用、汇总对账和控制结果。它们不会记账、运行薪资、转移资金或开具税务收据。个案工作和安全保障支持不透明代码、状态及专业系统引用;它们不接受受益人经历、个案记录、指控或医疗叙述。表单记录用于描述运营定义和汇总回复批次。下方单独的公开受理工作流仅接受最低限度的运营请求;它不是敏感服务受理后端。资源和福利记录不会为组织办理服务提供商注册。
公开的 AI Charitologist 仍是一个来源检索工具。本服务不会引入自主推荐模型,也不会声称影响经过独立验证。
Resources 目录源内容审核
公开的 Tools/Benefits 目录和托管的 Resources 索引支持明确选择保留的源内容 → 检查 → 预览 → 复制未批准的 Resource。复查会显示确切的源版本、字段变更、所属组织备注和可选的注明日期的声明。Resources 仍在组织范围内,包括针对项目范围的写入者;UI 会在复制前说明这一界限。不会添加项目字段、提供方连接、资格审批、注册、提醒或任务。所有 31 条保留条目仍是编辑草稿,检查日期为 2026 年 10 月 25 日。
当前会话/成员关系、源内容/版本、记录修订版本和确切的原始提案都会在组织锁定期间重新绑定。重试、键值变更和移入回收站后,仍只有一个主绑定。常规工作流验证和独立审批仍适用;重新检查会清除审批,并保留现有的冻结读取者快照。完整的组织 JSON 会保留完整源历史;所选证据和 CSV 则不完整。恢复后,历史记录仍处于非活动状态,直到授权成员明确采用它。
运行时 02cc6cfc3ee45c4c7f5427c56e4f2d86bca6bac2 通过了 408 项完整的 OS 单元/浏览器模型测试、116 项实际隔离的 PostgreSQL 测试、546 页构建/检查,以及两次针对完全相同提交的 CI 运行。最终的虚构 Better Auth/Chrome 测试覆盖了 25 个有版本记录的旅程和 8 种精简的浅色/深色布局,包括实际保存的完整备份选择器/恢复/采用流程。增量迁移保留了原有的全部 31 张表/60 行/ACL,并将强制 RLS 租户表从 24 张增至 25 张。受保护的暂存部署 dpl_F2ACtEYm5CLHDUwwyKQQCJBfJxdE 通过了 43 项 HTTP 检查和 13 个完全匹配的资源。最终文档 670f132fdfcd7e0d36d95388fa6ead8b2776a547 通过了两次针对完全相同提交的 CI 运行;PR #28 已合并为 c0d509a0e132e91b7f5d6b764eabce421015b125,Pages 40584685952 运行成功。经过 44 项规范检查/13 个完全匹配的资源后,已部署经测试的确切暂存版本;所有 31 张旧表/60 行/ACL 均保持不变。所有 62 个已选公开文件和 31 个源片段均匹配,包括 favicon/OG 媒体资源。Chrome 实时测试确认了无需签名的精确片段交接。未来的常规 Git 自动分配仍已启用。验收记录区分了确切版本、测试夹具辅助、已修复的 bug/测试框架问题,以及剩余的运维工作。
手动定期任务草稿
Projects 任务支持明确预览 → 生成一个每周、每月或每季度的后续任务。预览会保留原始日历锚点,遇到重复的本地时间时要求选择一个具体时刻,并会拒绝缺失的本地时间。新任务初始状态为计划中且未获批准,负责人为执行操作的成员。不会复制源审批、连接身份、文件、评论和提醒。不会按计划自动生成任务,也不会发送消息。
一个源任务在重试和后续编辑后仍只有一个已保存的后续任务。活动系列会将类型、项目和计划固定,直到另行确认结束;取消/删除也会终止生成,但不会取消子任务。系统会重新检查当前的组织/项目权限。备份会将重复规则作为非活动历史记录恢复。验收记录记录了确切限制、真实的虚构用户登录后浏览器检查、309 项单元测试和 90 项隔离的 PostgreSQL 测试。PR #26/发布版本提交 b542f13f3ceec9960b358e816afa589584e36252 通过了两次针对完全相同提交的 CI 运行。运行时 ffdbf7af612985492dd415bd7b0af4ffdaf7b398 在通过 34 项暂存检查/35 项规范检查和十个完全匹配的资源后,已部署为 dpl_CyAHQVAiZ4zqwQD4yVQQob3f4Cq9。增量迁移保留了全部 60 条旧记录/列/ACL,并检查了 24 张强制 RLS 表。有关验证时间和未来常规自动分配的限制,请参阅该记录。
资助期报告
新的有界资助报告实现会选择一项协议、一个明确的项目和一个包含起止日期的期间。它会将奖励和承诺与所选外部收款、有日期的现金支出参考资料及规划背景分开处理。金额未知时,标题总额仍标为未知,同时显示已知小计和缺失参考资料的数量;空选择不会被报告为零活动。每项观察都会保留各自的单位、期间、分母、证据和局限,不会汇总数据或推断因果关系。
获授权的贡献者会根据已保存的 Reporting 清单准备来源,通过常规修订工作流明确保存来源摘要,然后由另一位获授权的贡献者审批。最终的已批准预览会在十分钟后过期。冻结时会重新计算当前来源、审批和成员资格权限,并追加一个不可变版本。之后如需更正,必须更改清单数据、重新准备并审批,同时说明原因;旧数据保持不变。若命令执行中断,可以恢复原始报告,而不会重复创建已批准版本。
员工访问需要当前的来源读取/导出权限和适用范围。符合条件的董事会读者只能收到面向董事会受众清单的独立校验和白名单投影;他们无法获取私人应用上下文、联系人、外部来源标识/URL、操作人元数据或原始来源记录。外部审阅者不在授权范围内。作者仍需检查已批准的摘要/局限中是否包含个人信息。报告不会自动发布、邮寄或提交给资助方,软件审批也不代表会计认证或影响核验。
GRANT_REPORTS.md 记录了确切的工作流、API、限制和证据。资助报告版本将运行时 c9750a92f0ac6d5f2b717875f5e0a85f08e98edb 提升为 dpl_6FZTpTgrSCfiJcsPazysjGdNfW5D。精确 CI 通过了 244 项 OS 单元/浏览器模型检查和 69 项实际 OS PostgreSQL 检查,以及邮件和静态检查。通过受控的实际 Chrome 和合成 Better Auth 账户,验证了准备、独立账户 API 审批、冻结、下载 JSON/校验和、打印预览、董事会隐私、过期来源拒绝和注销。所有 29 项暂存/30 项公共源检查及生产环境强制 RLS 检查均已通过。窄屏浏览器验收、独立审查和真实报告周期试点仍待完成。现有通用模块快照报告仍保持原有行为。
公开运营请求
已部署的服务提供无需账户的联系、活动意向和志愿者意向表单。该接收功能最初随运行时版本 98ebea527b6a5b382d5e143acf207205eccd172b、部署 dpl_1yFKcLN8m2x8QkXs4Sf1sZbeBdYd 首次上线;下方的参与者后续流程扩展了该服务。PUBLIC_PARTICIPATION.md 记录了确切的 CI、生产环境 RLS 和受控合成浏览器证据。浏览器测试环境使用了隔离的实际数据库和明确虚构的管理员身份验证;这并不能证明存在真实人员审批、参与者采用情况或已发布的生产表单。SHARED_OS_RELEASE.md 保留了完整的发布历史和未完成的关卡。
所有者或管理员可以发布当前准确且已独立批准、处于已发布工作流状态的 Forms 修订版,也可以选择关联同样为当前版本且已获批准的活动场次或志愿者班次。源或目标经过编辑、删除、关闭或撤回,或者保留期限审核日期已过,都会停止接受新请求和进行转换。公共页面仅显示组织名称,以及特意发布的标题、用途、问题、同意声明和审核日期。发布者必须检查相关措辞;关键词筛查无法保证提示词或自愿提交的答案不包含敏感信息。
明确同意提交的请求会进入单独的所有者/管理员队列。必须先执行单独的审核操作,才能进行转换;转换会创建未经批准的联系人/注册/分配草稿,或关联明确选定的现有联系人。该操作会检查实时容量和日程规则,但不会预留名额。它不会验证身份、订阅新闻简报、预约活动、分配志愿者、发送通知或转移资金。
系统会返回一个随机生成的 32 字节回执,且只存储其哈希值。回执的私有 URL 使用片段标识符。同源 JSON POST 可以读取状态,或主动撤回请求,但不会泄露答案或地址;系统会拒绝查询令牌和跨源更改。保持不变的请求标识符可用于去重重试,但不会再次披露原始回执。如果首次接受请求的响应丢失且未保存回执,请通过其他方式联系组织。取消会撤回请求;已提交的答案和单独准备的记录仍会保留,等待组织进行保留期限审核。
单独的擦除操作会检查修订版本,然后清除队列答案和 IP/负载哈希,同时保留擦除时间戳及最少的状态/回执/幂等性来源信息,并关闭待处理或已审核的项目。该操作不会擦除单独创建的联系人或草稿、不可变报告、较早的源档案、外部恢复副本或已下载的备份。保留日期会在审核日期之后关闭数据收集;这并不代表自动删除。管理员必须主动管理保留期限。即使普通审计容量已满,仍可执行擦除、取消和撤回发布操作,具体通过下文所述的紧急预留容量机制实现。
服务器将表单限制为最多 30 个问题/12,000 字节的架构定义,将提交总量限制为 16,384 字节,将每个组织每天(UTC)的新请求限制为 100 个,并将待处理/已审核队列限制为 1,000 行/8 MiB 的实测行数据。一般文本答案上限为 300 个字符;保留联系字段的限制更严格。基于 IP 的持久限制为每小时 20 次提交和 60 次回执操作。完整工作区导出的预算也适用。确切的验证规则请参阅 intake.mjs,恢复方式请参阅 intake-backup.mjs。
参与者自助服务
运行时 a6202f32a7fa7b9ac610bfc5676717530c1ba5ee / dpl_39nM5eZuamArw2rLYv5DyogcFkxF 已部署至 https://os.charitology.org/participant。针对精确提交版本的 CI 已通过 132 项服务测试和 31 项实际 OS Postgres 测试;受保护阶段/公开检查以及一次受控的真实所有者收件箱登录也已通过。这些仍是范围有限的工程检查,并不代表参与者已实际采用。
/participant 是一个独立的个人请求门户。必须具备当前已验证的 Better Auth 账户、不可猜测的回执、明确的关联同意,以及与提交时预留邮箱完全匹配(去除首尾空格并转换为小写)。仅登录不会发现任何请求,也不会获得任何组织成员资格。登录邮件仅包含登录令牌和固定的门户目标地址;回执会留在原始标签页中,直到用户主动认领,之后才会从片段和内存中清除。
该门户每页显示 20 项个人请求,仅展示已提交的回答/公开架构/状态,并允许在请求处于待处理状态且其已批准的发布仍为当前版本时,进行经过版本校验的更正。更正需要重新同意相应用途,且不能更改最初验证过的邮箱。撤回、删除回答和永久解除账户关联分别需要确认,并会产生不同后果。这些操作不会删除单独保存的联系人信息或较早的备份。解除关联后,其他账户无法认领此请求,也无法使用同一回执重新关联。
强制启用的个人用户 RLS 索引提供跨组织导航;收集和发布表仍保留严格的租户策略。关联数量上限为每个账户 100 个、每个组织 1,000 个,包含已撤销的关联,并在组织锁之后获取用户锁。持久化限制涵盖认领、读取和写入。私有导出不会恢复任何账户授权,现有的发布/回执恢复功能仍处于停用状态。实施前计划和验收记录区分了实际身份验证、模拟前端检查、受控浏览器证据和部署状态。下方范围有限的预约功能及单独设门控的交付控制扩展了此门户。
已确认的参与和候补名单
运行时 e6c880d6bb2f89b4ca2fa507372d25cb964c4f69 / dpl_4Zs32Y794voSwEkcPnEbrMgygJCG 已部署至 https://os.charitology.org。[验收记录](../../docs/PARTICIPATION_BOOKINGS.md)记载了精确 CI(159 项服务测试/44 项实际 OS Postgres 检查)、强制 RLS 迁移、暂存环境/线上 HTTP 检查以及受控的虚构 Chrome 证据。不声称生产环境中的参与者已实际采用。
Participation 控制台管理一个人的名额,可用于整个活动场次或志愿者班次。启用某个场次前,管理员会审核并接受一份精确且经哈希处理的清单,其中列出所有现有的有效类型化报名或分配。未知的旧同意状态仍保持未知。重复、时间重叠或超出容量的旧占用会阻止启用。
具有指定范围写入权限的人员可将类型化报名或分配草稿与联系人关联,并在适用时关联到其转换后的收集请求。关联不会预留容量。参与者可通过自己关联的请求,确认当前已独立批准的用途、说明、日程安排和组织者联系方式。工作人员也可以改为记录具体的线下确认,并注明确认方式和证据参考。收集同意和意向请求本身并不授权参与。
工作人员会明确确认参与请求,或将其列入已获同意的候补名单。候补晋升由人工操作;控制台会建议当前符合条件且等待时间最长的请求,若跳过该请求,则必须提供操作原因。确认操作要求当前来源和候选者均已独立批准、版本完全匹配、容量充足,并通过组织事务中的志愿者时间重叠检查。没有团体分配、名额保留、自动资格判定或自动晋升。 已确认的名额具有独立的履约历史;通用编辑将记录重置为待审核状态时,这些名额会保留已冻结的条款。通用编辑、状态转换、导入、删除和垃圾箱恢复均无法绕过分配规则。取消只会释放一次名额,且不会自动递补其他人员。即使源记录关闭、审批状态变更或常规存储已满,仍可取消。已取消的候选人会保留在历史记录中;重新申请需要创建新的、类型明确的候选人。
自助申请门户仅显示该参与者关联的状态和公开条款。具体同意、电子邮件偏好设置和取消是彼此独立的操作。撤回原始申请或删除其回答,不会取消已确认的参与。永久解除关联会移除自助服务访问权限,并取消尚未发送的、发往账户地址的通知;门户会提醒参与者先取消,或保留经批准的组织者联系方式。不能通过新的同意表单,在未明确告知的情况下重新安排已确认的条款。
旧版预订电子邮件复选框仍仅用于设置偏好。新的发送工作流要求已验证且自行关联的参与者重新授予 participation-email-v1 同意,然后由管理员准确审核 1–20 条当前确认记录。两项服务默认关闭参与通知发送并启用受控收件人模式;组织策略也默认禁用。启用后会创建新的快照发送意图;之后符合条件的候补名单、确认或取消变更可根据该策略排入更新。保存同意不会发送欢迎邮件,旧的暂停历史记录也不会变成待处理队列。PARTICIPATION_DELIVERY.md 记录了已实施的控制措施和发布证据;计划保留了设计。登录、邀请和个人提醒行为,以及新闻简报同意,均单独处理。
受管理的目标最多为 500 行/2 MiB,参与历史最多为 2,000 行/8 MiB,保留的发件箱历史最多为 8,000 行/8 MiB,均包含已取消记录和历史记录。每个有效发送意图会为有界的结果元数据预留 8 KiB;核算时采用实际行字节数与该预留值中的较大者。每个组织最多保留 4 项临时发送审核,10 分钟后过期;私有绑定的上限为 64 KiB。保守的工作区导出预算也适用。存储已满时,取消和关闭偏好设置可能不会生成新的通知事件,以免名额被占用;响应会明确说明这一缺口。命令使用随机意图密钥和预期修订版本。仅可重放与最新命令完全一致的重试;遇到结果不明确的故障后,应重新加载,而不要臆造新的尝试。
备份会保留有界的履约来源记录,但不会保留有效权限或恢复参与者访问权限。恢复的目标仍处于暂停和阻止状态;同意操作无法分配名额;必须先由管理员通过精确采纳核对先前确认的占用情况,之后才能分配新名额。若先前已确认的历史记录缺少引用,则会被拒绝。历史审批记录、操作者和时间戳仅用于追溯来源,不能证明已进行新的审核。请参阅实施前约定和发布记录。
架构与访问
- api/index.mjs 将经过身份验证的请求处理器连接到数据库和邮件中继。public/ 包含浏览器客户端和本地字体。
- auth.mjs 配置 Better Auth。登录链接 10 分钟后过期,使用经过哈希处理的验证令牌,并要求通过明确的确认 POST 完成操作。通过 GET 打开邮件链接不会创建会话。会话 Cookie 为 HttpOnly,且在 HTTPS 来源中使用安全传输。
- database.mjs 在每个事务中设置组织/用户上下文。租户表启用并强制执行行级安全策略。变更操作按组织串行处理;替换记录或成员关系时,必须提供预期版本。应用使用无法绕过 RLS 的独立角色;迁移所有者不是运行时角色。
- access.mjs 检查当前成员关系、模块权限和项目范围。关联目标也必须可读。成员关系变更会在后续请求中生效,并在发送提醒时重新检查提醒访问权限。
- jobs.mjs 存储邀请和个人提醒任务。mail.mjs 调用独立且用途受限的新闻邮件服务中继。没有任何操作系统邮件操作会创建新闻邮件订阅者、Contact、Topic、Segment 或 Broadcast。
- integrations.mjs 支持 CiviCRM、OpenProject 和 Kobo 的只读预览,以及本地 CSV 行。凭据在服务器端加密。HTTPS 主机必须解析到公共地址;系统会固定使用经过检查的地址,并拒绝重定向。导入是明确的预览/提交操作,而非无人值守的双向同步。
- participation.mjs 将已确认的参与状态和同意状态与通用审核状态分开管理。中央写入保护可防止通用变更操作,恢复则会还原非活动来源信息。
- participation-delivery.mjs 添加经验证的版本化电子邮件同意、精确的管理员激活、安全且限定范围的状态、设有上限的租约,以及仅通过状态恢复不确定的尝试。发送恢复会还原已禁用的策略,且不会授予收件人权限。
- grant-report-model.mjs 生成确定性的单项资助周期报告。grant-reports.mjs绑定当前权限、临时预览、不可变的冻结/重放,以及由服务器选择的董事会视图。
- intake.mjs 仅通过固定的匿名路由公开明确的发布架构和持有令牌者可查看的回执状态。私人答案存放在单独设定范围且强制执行 RLS 的所有者/管理员表中。intake-backup.mjs会省略访问能力,并将发布状态恢复为关闭。
角色为 owner、admin、program_lead、grants_lead、finance_reviewer、contributor、board_reader 和 external_reviewer。所有者和管理员可管理整个组织的访问权限。其他角色获得特定模块的权限;可选的项目分配会进一步限制关联工作。所有者字段用于分配责任,不能授予访问权限。组织资料记录不能更改成员关系。
董事会和外部读者只能查看获准的已批准快照,不能查看之后的工作字段、评论或历史记录。当前和历史项目范围都必须允许访问。已批准的附件按 ID/校验和冻结;之后上传的内容不属于该快照。受限模块应用各自的角色列表。模块注册表是唯一的权限来源。 审批会将已持久化的修订版本与原因及独立审核者绑定。最后一位编辑者不能批准该修订版本。编辑已批准或冻结的内容,或附加文件,都会清除当前审批,并将工作记录退回审核状态或初始状态,同时保留其历史快照。推进审批阶段需要当前审批。冻结报告会保留来源 ID、修订版本及其校验和。导入的审批和行为主体声明不会成为新的可信审批或成员资格授权。
本地设置
在仓库根目录运行:
cd services/charity-os
npm ci
cp -n .env.example .env.local
使用专用的开发数据库。在 .env.local 中私下设置这些值;该文件已被 Git 忽略。构建连接 URL 时,请对数据库凭据进行 URL 编码。
| 变量 | 用途 |
|---|---|
DATABASE_URL | 迁移/测试用所有者连接。用于创建表、函数和隔离的测试架构。 |
OS_DATABASE_URL | 独立的应用连接,具有 NOSUPERUSER 和 NOBYPASSRLS 权限。生产环境必需。 |
BETTER_AUTH_URL | 准确的公开源;使用 http://localhost:4344 连接随附的本地服务器。 |
BETTER_AUTH_SECRET | 独立的随机密钥,至少 32 个字符。 |
OS_ENCRYPTION_KEY | 用于存储集成凭据的独立随机密钥。请妥善保管以便重新连接,或有意轮换凭据。 |
OS_MAIL_RELAY_URL | 用途受限的邮件端点,通常为 https://mail.charitology.org/api/system/os-mail。 |
OS_MAIL_RELAY_SECRET | 专用的共享 bearer 密钥,需与中继配置匹配。切勿在浏览器中暴露。 |
CRON_SECRET | 用于维护任务的独立 bearer 密钥。 |
使用加密安全的生成器生成独立密钥值,例如 openssl rand -base64 48。替换所有示例值。开发环境中的邮件功能请使用单独配置的本地中继或传输测试;生产中继只接受其配置的 OS 源。单元测试和数据库测试会模拟邮件,无需真实的服务提供商凭据。
通过数据库所有者的管理连接创建一次应用角色。例如,在 psql 中运行:
CREATE ROLE charitology_os_app LOGIN
NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOBYPASSRLS;
\password charitology_os_app
将该角色的连接 URL 用作 OS_DATABASE_URL。在迁移期间,将所有者连接保留在 DATABASE_URL 中,然后运行:
npm run migrate
npm run dev
迁移会创建 Better Auth 和 OS 表,并授予已配置的应用角色使用架构、访问数据和访问序列的权限。它会撤销对实时审计事件和冻结报告的更新/删除权限;追加写入触发器也会保护这些表。迁移不会发送邮件。如果数据库提供商要求通过其控制平面创建角色,请在迁移前在那里创建同样受限的角色。
在处理真实请求之前,直接确认运行时连接:
SELECT current_user, rolsuper, rolbypassrls
FROM pg_roles WHERE rolname = current_user;
两个权限标志都必须为 false。管理和迁移时使用所有者凭据;处理请求时使用 OS_DATABASE_URL。切勿通过削弱 RLS 来解决权限错误。架构更改后,重新运行迁移并验证应用授权,包括新创建的表。
测试与 CI
npm test
node --test test/*.test.mjs public/*.test.js
npm run test:db
npm test 会运行服务器、域名、注册表以及浏览器 API/模型回归测试;显式的 Node 命令与之等效。test:db 会读取私有的 .env.local,要求同时提供所有者 URL 和受限应用 URL,并使用 Better Auth 测试实际的 Postgres。其测试夹具会创建一个随机临时架构,在其中应用迁移,授予应用角色访问该架构的权限,断言该角色无法绕过 RLS,使用搭配模拟邮件程序的合成收件人,并在 finally 中删除该架构。请使用所有者能够创建/删除架构的专用测试数据库;不要将其指向生产数据库。
charity-os-check.yml 会在相关拉取请求和主分支变更时运行,可由其他工作流调用,也支持手动触发。它会安装锁定的依赖项、检查浏览器入口的语法、运行服务器和浏览器模型测试,并针对临时 Postgres 17 服务运行实际数据库测试夹具。CI 会创建一个独立的 os_test_app 登录角色,不具备超级用户、创建角色、创建数据库、继承或绕过 RLS 的权限。它不使用任何服务提供商或部署密钥,也不会发送邮件。CI 会直接调用数据库测试,因此不会加载私有的本地环境文件。
测试命令和工作流配置并不能证明托管部署或收件箱投递已通过。请单独记录这些结果。BACKEND_REVIEW.md 说明了独立源码/回归审查的范围和局限。
Directory Resource 版本的完整测试套件通过了 408 项单元/浏览器模型测试和 116 项实际隔离的 PostgreSQL 测试。重点回归测试涵盖来源身份、提案的精确绑定、排队会话的撤销/过期、常规审批/快照规则、PostgreSQL 配额核算、非活跃状态下的恢复/接管,以及严格的精确文件准入。验收记录记载了独立审查、准确的 CI 结果,以及单独进行的受控浏览器/受保护阶段证据;虚构账户无法证明有人类审查或试点。
当前投递实现通过了 188 项本地服务/浏览器模型检查,以及完整的 60 项实际 PostgreSQL 测试,其中包括 16 项投递检查。传输层采用注入方式;单独的托管 CI、受控 Chrome 和实际自有收件箱证据记录在投递记录中。
新增的 grant-report 切片单独通过了 33 项重点模型/服务测试和 9 项隔离的实际 Postgres 测试,其中包括 8 个工作流组及其父级。测试涵盖当前来源审批、合成的历史提交产物、重放/并发、董事会隐私、配额和非活跃状态下的恢复。测试使用注入的服务器身份,并未声称存在真实登录或人类审查。随后,准确的版本 CI 通过了 244 项 OS 单元/浏览器模型检查和 69 项实际 PostgreSQL 检查,以及邮件和静态检查;29 项受保护阶段/30 项公共来源检查和生产隔离检查也通过了。此外,实际 Chrome 使用虚构的 Better Auth 账户测试了已认证的报告流程、下载 JSON/校验和、董事会隐私、过期来源和注销。十页打印预览已取消;不声称进行过实体打印或保存 PDF。窄屏验收、独立的人类/会计师审查,以及经同意的报告周期试点仍未完成。具体证据和限制请参阅报告验收记录。
API 概述
已认证的浏览器变更请求会发送同源 Cookie、精确的 Origin、Content-Type: application/json,以及 /api/session 返回的 X-CSRF-Token。无需账户的提交变更请求使用精确来源的 JSON,并附带明确的收集许可或私密回执承载令牌;它们不需要会话,也不会授予一般组织访问权限。令牌确认和独立的 cron 承载令牌各自有专用且范围有限的身份验证路径。请勿直接调用 Better Auth 会消耗令牌的验证 GET;该接口不会公开分发。
以下所有组织路径均以 /api/orgs/:orgId 开头。每次请求都会检查当前成员身份和权限。
| 方法/路径 | 行为 |
|---|---|
POST /api/auth/request-link | 请求登录链接;地址/IP 限制适用。 |
GET, POST /auth/confirm | 扫描器安全页面,然后由用户主动确认令牌。 |
GET /api/session、POST /api/auth/logout | 读取当前用户、组织和 CSRF 值;撤销会话。 |
GET /api/modules | 获取带类型的模块、货币和角色元数据。 |
POST /api/orgs | 创建组织及其首位所有者。 |
GET, PATCH / | 读取/更新 API 允许的组织设置。 |
GET /dashboard、GET /audit | 限定范围的概览;管理员审计历史。 |
GET /modules/:module/records、POST .../records | 列出可访问的记录,或创建带类型的草稿。 |
GET, PATCH, DELETE .../records/:id | 读取、按预期修订版本替换,或软删除。现有链接和保留期限限制会阻止不安全的删除。 |
POST .../records/:id/approve、/transition | 独立批准某个修订版本,或在提供原因后推进允许的工作流。 |
POST .../records/:id/comments、/reminder、/files | 添加评论、安排个人提醒,或附加允许的文档文件。 |
GET /files/:id、GET .../records/:id/files | 访问获准的附件字节数据/元数据,并遵守冻结快照。 |
GET /modules/:module/trash、POST .../records/:id/restore | 查看并恢复符合条件的软删除记录。 |
GET /modules/:module/export?format=csv | 限定范围的模块导出;默认格式为 JSON。 |
GET, POST /reports、GET /reports/:id | 列出获准的冻结报告、创建报告,或读取其冻结载荷。 |
POST /grant-reports/prepare、/preview、/freeze | 准备选定的已批准来源,缓存经审核的证明,或使用与正文绑定的命令密钥冻结一个不可变的单次授权版本。 |
GET /grant-reports、GET /grant-reports/:id | 分页显示限定范围的数据,每页 20 行;返回由当前权限选定的员工载荷或董事会视图。 |
GET /members、PATCH, DELETE /members/:userId | 查看团队,或以管理员身份更改/撤销访问权限。 |
POST /invitations、DELETE /invitations/:id | 发出或撤销邀请。接受邀请时使用 POST /api/invitations/accept 和受邀者已验证的邮箱。 |
GET, POST /integrations | 查看连接或创建连接。 |
PATCH, DELETE /integrations/:id | 按预期修订版本替换/移除凭据,或停用连接。 |
POST /integrations/:id/test、/preview、/import | 测试只读访问、审核映射后的行,然后提交已存储的预览。 |
GET /export、POST /import/upload、/import/preview、/import/commit | 下载备份,或上传、预览并提交恢复文件。 |
GET /backups/imports、GET /backups/imports/:id | 管理员访问已提交导入的原始存档。 |
GET /directory-resources/records/:id | 当前获准的资源/来源历史,支持有界游标分页。 |
POST /directory-resources/preview、/commit | 查看复制/重新检查/采用计划,然后主动提交其精确的仅驻留内存证明和命令。 |
GET /directory-resources/records/:id/export | 获准导出的部分选定资源证据;不是完整恢复文件。 |
GET, POST /intake/publications、POST /intake/publications/:id/withdraw | 管理员发布已批准的当前表单版本,查看列表/状态或撤回发布。 |
GET /intake/submissions、GET /intake/submissions/:id | 仅管理员可访问的私密队列、筛选条件、游标分页和详情。 |
POST /intake/submissions/:id/review | 按预期修订版本进行审核、驳回、转换为草稿或擦除回答。 |
GET /participation-targets、GET /participation-targets/:id | 限定范围的写入者可查看场次列表和采用预览。 |
POST /participation-targets/:id/adopt | 管理员接受精确哈希的旧版占用记录。 |
GET, POST /participation-targets/:id/participations | 限定范围的写入者可查看名册分页,或主动关联带类型的候选人。 |
POST /participation-targets/:id/participations/:participationId/:action | 按预期修订版本执行 consent、waitlist、confirm、promote 或 cancel。 |
GET /participation-delivery、GET /participation-delivery/outbox | 限定范围的写入者可查看候选人/状态分页;不包含地址或收件人绑定信息。 |
POST /participation-delivery/preview、/activate、/disable | 管理员审核、精确原子激活或按策略停用。 |
经过身份验证的目录路径为 GET /api/directory-resources/catalogs 和 GET /api/directory-resources/catalogs/:captureId/:catalogKind/:listingId。它们仅公开捆绑保留的来源投影。任何请求都不会获取提供方 URL 或发现远程目录。 |
公开路径为 GET /api/public/intake/:orgId/:publicationId、POST .../submissions 和 POST .../receipt。独立页面使用 /p/:orgId.:publicationId 和 /p/receipt#orgId.publicationId.privateToken。GET 不会取消请求。公开端点不会返回私有队列答案、联系地址、审批身份或回执哈希。
本人预约路径为 GET /api/participant/orgs/:orgId/requests/:intakeId/participations 和 POST .../participations/:participationId/consent、/cancel 或 /preferences。新投递使用 GET .../participations/:participationId/delivery 和 POST .../delivery-preference,并需提供预期的参与和受理修订版本、当前同意文案版本、已启用的选项以及随机命令键。这些路径要求经过验证的会话以及现有的本人有效请求链接;不会公开名册、工作人员的私有原因或联系标识符。经过验证的收件人由服务器选择;客户端不能提交收件人。
替换记录、审批、状态转换或删除记录时,需提供预期的整数 revision。修订版本过期时返回 409。领域验证失败时返回 422,并附带字段问题。连接中断或变更过程中断都不能证明写入失败;决定是否重试之前,请重新加载已保存的状态。导入会提交存储在服务器上的预览,并拒绝已过期、已提交或工作区已更改的预览。导入不会信任客户端提供的预览记录。
恢复、文件和限制
迁移或交接前,请下载组织 JSON 备份。备份包含私有记录、当前文件、评论、来源历史记录、报告、垃圾箱元数据、trashFiles 中已删除文档的字节内容以及连接配置;请按照组织的访问规则妥善存储。备份不包含身份验证会话、新闻订阅同意记录、有效邀请/作业令牌以及连接器凭据。模块 CSV 会对类似公式的单元格进行中和处理,但恢复时应使用 JSON 格式。大型 JSON 和 CSV 响应会以流式方式传输。
备份还包含刻意发布的架构以及私有受理答案/状态,包括擦除墓碑,但不包含回执、幂等性、负载和 IP 哈希。恢复的发布内容会撤回,旧回执权限仍保持禁用状态,先前的工作人员审核也不会授权转换。已擦除的有效请求会以关闭状态恢复,不包含答案。请发布新审批通过的表单以接收新请求,并手动处理恢复的请求。历史来源存档和先前下载的备份仍可能包含后来从有效队列中擦除的答案。
投递备份会保留策略/结果来源信息,包括先前的发件箱状态,但恢复时会创建全新的禁用策略、取消旧版意图,并且不保留投递同意、收件人/中继绑定或账户授权。历史上的已接受/未知结果永远不会授权重新发送。擦除答案和解除关联会禁用当前投递同意,并取消尚未尝试的任务,但不会取消出席状态,也不会撤回已尝试发送的电子邮件。
目录历史备份会保留完整的来源核心及精确的事件链,包括恢复来源/仅存档来源信息。它们不包含有效回执、命令/证明/会话权限或账户授权。恢复的历史记录会保持非活动状态;获授权的成员必须检查当前可读取的资源,并明确采纳。选定的资源证据文件并不完整,不能用作完整的组织备份。 恢复到一个没有记录(包括回收站中的记录)且没有现有连接的组织中。预览会验证校验和、架构和关联记录;提交时会在事务中重新检查目标状态。活动记录保留其稳定 ID,但会从模块的初始工作流状态开始,所有者设为执行恢复的成员,并重置审批和快照。原始审计历史、评论、报告、回收站内容和已删除文件的字节数据,会作为源数据溯源信息保存在私有的已提交导入归档中;它们不会成为新的可信决策或账户权限。实时恢复审计会记录归档 ID、校验和及数量,而不是将所有源历史复制到另一条事件中。
请通过恢复页面/API 单独下载原始的已提交导入归档,并将其与当前工作区备份一同保存。归档负载不会递归嵌入到之后的每次工作区导出中。请将原始源文件保留为独立的恢复副本;仅有当前工作区备份无法替代这些较早的归档。
原生源身份和连接 ID 会在恢复后保留。连接会恢复为未配置状态,不包含已保存的凭据。请使用新凭据重新连接恢复后的连接,以便未更改的源 ID 保持幂等;创建不同的连接会建立不同的源身份。更改过的源行需要显式协调。远程预览只会读取最多 100 条记录中的第一页(须为受支持的页面);CSV 预览最多接受 1,000 行;二者都不代表完整的外部系统迁移。
当前的存储和请求上限定义在代码中:
- 备份导入最多为 64 MiB。浏览器会在解析前对用户选定的字节进行验证,包括严格 UTF-8 检查、解码后键名重复检查和非有限数值检查;服务器在直接和分块接收时也会重复严格准入检查。较大的文件需使用经过身份验证的分块上传,然后生成一次预览。完整备份不受目录命令的小型深度和字节数限制。分块上传和预览会在 30 分钟后过期。原始已提交导入归档会作为管理员专用恢复记录保留。
- 待处理预览单独受限:每个组织最多 4 个预览,Postgres 中保留的 JSON 文本总量最多为 128 MiB。已提交的备份归档和集成导入日志另有单独限制:最多 32 个已提交预览,总量最多为 128 MiB。服务器使用 Postgres
octet_length(payload::text)测量两者,并计入 JSON 表示形式的开销,而不依赖文件大小。创建预览时,服务器会在组织锁定期间检查待处理预览容量和最终已提交容量;提交时会再次检查保留量限制。创建新预览时,可以清除已过期但未提交的预览。即使原预览已过期,已提交的源归档仍会保留。 - 每个文件最多为 2 MiB;工作区文件配额为 25 MiB 和 1,000 个文件。允许的类型包括 PDF、UTF-8 文本/CSV、PNG 和 JPEG;适用时会检查文件签名。文件下载使用附件处置方式和严格限制性标头。
- 结构化记录数据的工作区配额为 16 MiB,每条规范化领域记录最多为 64,000 字节。中央保存路径将工作区限制为 2,000 条活动记录,批量调用方也受此限制。连接创建和恢复最多为 30 个连接。
- 当前工作区导出的保守预算为 60 MiB,涵盖记录、历史记录、评论、报告、连接、发布/接收行、参与历史记录/发件箱、交付策略/审核以及 Base64 文件数据。普通变更会在超出此预算前停止,从而为 64 MiB 的恢复上限留出空间。原始导入归档和临时上传与此预计导出预算分开存储。
- 资助报告最多允许选择 100 个源,依赖闭包中最多包含 250 条记录,规范化后的最终 JSON 最多为 2 MiB。4 个有效报告预览共用 8 MiB 的已测量行数据,预览会在 10 分钟后过期;它们计入普通工作区预算,而非已提交源归档配额。命令最多为 16 KiB;每个账户的限制分别为每小时 120 次读取,以及每小时 60 次准备/预览/冻结命令。报告恢复仅在专用源归档中保留历史载荷,不提供活动报告、预览或审批权限。
- 目录历史记录最多允许 250 个主绑定、1,000 条捕获/事件行,每个绑定最多 32 个事件。每行的已测量 PostgreSQL JSON 载荷最多为 32 KiB,另预留 4 KiB 恢复空间;总量不得超过 4 MiB 的功能上限及整个工作区预算。专用命令最多流式传输 32,768 字节;10 分钟有效的证明保留在内存中。读取和命令分别受每个账户每小时 120 次和 60 次的限制。这些限制不授权自动重新检查或资格判定。
- 另设 1 MiB 的审计预留空间,用于在普通预算已满后记录最低限度的访问控制变更。即使预留空间耗尽,撤销、访问权限变更、禁用连接、取消公开请求、撤回发布、删除答案、取消参与、更改为关闭偏好设置以及禁用交付策略仍必须完成。在这种紧急情况下,服务会发出已删减信息的运行警告,而不会承诺生成另一条持久审计事件。达到预算上限后仍可导出;请保留恢复副本,并在继续普通工作前解决存储问题。
- 会话和组织访问与这些存储控制相互独立。规划记录中提及的成本上限不会配置服务,也不会强制执行提供商的计费限制。 如果达到预览/归档上限,服务会在保留新的预览或提交导入之前返回 422。现有源归档仍可通过管理员恢复 API 下载。下载当前工作区及其原始源归档,并保留这些副本;后续恢复/导入操作请使用新的空工作区。服务不会删除已提交的归档,也不保证提供归档删除控件。待处理的预览并不预留未来的归档容量;在应用该预览之前,另一次提交可能会占用剩余空间。
迁移.mjs 中的 W1 适配器通过相同的身份验证预览/提交工作流,接受较早的本地浏览器导出格式 charitology.charity-os 第 1 版。它会将项目、资助、任务和成果定义转换为相互关联的共享草稿,并提供确定性的 ID 映射和结构化审核警告。源数据中的所有者标签不会创建账户或权限;状态和证据断言也不代表已获批准。可准确表示的金额会保留其源货币和精度,不进行货币兑换。无法表示的金额会保留在私有源归档中,并转换为未知活动值。没有具体时刻/时区的日期和不受支持的备注也会保留在归档中。观测测量值(包括 0 和 null)会保留在归档中,直到提供真实的测量周期以及任何必需的分母。
完整的源 JSON 会私密地保存在已提交的迁移归档中,包括不受支持的字段;警告不会包含其私有字段值。本地源归档的大小上限为 8 MiB,生成的共享记录必须符合共享工作区限制。确认之前,请审核转换计数和警告。请将原始本地文件与共享备份及单独下载的源归档一并保留;参见 MODULES.md。
邮件与运维
随附的托管计划每天 07:00 UTC 通过经过身份验证的 /api/cron/maintenance 调用运行。提醒和参与状态更新会在到期后由该调度器运行时处理;这并不保证在确切时间发送通知。创建邀请后,也会尝试处理已排队的工作。现有的邀请和提醒任务优先运行;维护任务会在这些任务和参与通知发送之间,最多共享 20 项选定的工作/状态操作和 45 秒的预算。取消和延期也会占用工作预算。任务保留稳定的身份标识,租户按最近访问时间从早到晚轮换,有界租约则会阻止并发重复处理。成员资格已移除、记录无法访问、邀请已过期/撤销或记录已删除时,会停止相关的现有任务发送;参与通知会重新检查其已验证链接和同意授权。
中继使用已配置的 Charitology 发件人发送事务性邮件,并使用专用的 OS_MAIL_RELAY_SECRET。登录链接使用 /auth/confirm,邀请使用 /invite,提醒使用 /app,固定的通用参与通知仅使用干净的 /participant。通知中不包含事件、组织、回答或回执详情。邮件服务必须单独迁移/配置;请参阅 newsletter README。发件人验证、关闭跟踪检查、收件人抑制、原生服务商幂等性和持久化中继意图仍然有效。OS 邮件不会让任何人订阅 The Charitology Letter。
任务已接受,表示服务商/中继已接受请求;这并不能证明邮件已送达收件箱。对于结果不明的尝试,不要使用新身份标识盲目重发。请先检查管理任务摘要和服务商送达证据,再决定如何恢复。请私下妥善保管账户访问权限、中继密钥和集成加密材料。数据库恢复不会恢复外部服务商订阅,也不会撤销已排队的邮件。
参与通知中状态未知/已过期的尝试租约,即使原生幂等性已过期,也会通过仅限服务端的状态查询来协调同一个键;缺少状态信息不代表可以重发。只有经证实发生在尝试前的中继延期,才可重试同一不可变意图。已知的接受/送达证据会在状态服务中断期间保留。已送达历史仍符合每日协调条件,以便后续经验证的投诉或退信能够抑制未来的有效同意。关闭、删除回答、取消关联和停用策略会取消尚未尝试的工作,且绝不会创建新的隐私操作邮件。终止参与通知可通过保留的特定同意发送,无需重新开放已关闭的来源。
使用 vercel.json 将此目录作为独立服务提供,或在开发时使用随附的本地 Node 服务器。生产环境请使用 HTTPS、受限的运行时数据库角色、独立的 cron 和中继密钥,以及已配置的精确来源。/api/health 返回成功表示配置存在,并不能证明发件人已就绪、数据库已隔离或邮件已送达收件箱。在将部署视为可投入运行之前,请运行检查,并进行一次向自有收件人的受控送达测试。
实现、审查和文档编写使用了 AI 辅助。不声称获得任何法律、会计、保障或安全认证。
公共研究 MCP
隔离的 /mcp 函数仅提供 charitology.org 上现有的已发布研究 JSON。它不导入任何账户、数据库或邮件模块,不转发任何传入的身份验证信息,并支持三种有界的只读研究工具。请参阅 public/mcp.html。私有 OS 记录和所有写入工作流均不在此端点的范围内。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。