变更记录
什么是新的。
平台的每一个改进,随着它的出货。
· SecurityService
记录线索读取并拒绝不可读取的导出
HIPAA §164.312(b) for SecurityService. The platform records every lead CHANGE (LeadHistory) and every login (SystemAccessLog) and records no READ at all, so "who looked at this borrower" — the first question a §164.402 breach assessment asks — was unanswerable. PhiAccessAuditor builds events from the OTK/*** session map the endpoint already resolved, so the identity in the audit row is the same identity that authorised the request. Client IP comes from X-Forwarded-For; behind Traefik, remoteAddr records the ingress pod and is worthless for detection. Denials are recorded too — probing is what detection looks for — and a sessionless caller lands on a sentinel org rather than being dropped. Reads: single lead fetch = VIEW, grid = one LIST event per lead actually shipped (taken from the projected DTOs, so a lead filtered out by VIEW_UNASSIGNED_LEADS never appears as one that was read). 401/403/404 all record a denial. Exports fail closed — access-log CSV, HMDA LAR, the QC training corpus and the platform-wide extraction corpus. Each records one event per record BEFORE the file is built, and a failed audit write returns 503: "we handed out the data but lost the record" is the one answer that cannot be walked back. The platform-wide corpus crosses every tenant, so each record is attributed to the org that owns it, not the operator's. Only identifiers are logged, never content. **************** memberId) is gone: an export now has to hold its rows to record who was in them.
· kamo-signer-monorepo
在/{locale}/q/{token}的公众品牌引用/估计文档
The customer-facing surface for the commerce quote system. Server-rendered so the org's branding is in the first paint — an unbranded flash on a commercial document is exactly what this must not do, and it is why the page emits brand custom properties inline via QuoteBrandVars rather than swapping them after hydration. Lives in kamo-signer because that app already has the HostRegexp ingress, autocert coverage, DNS aliases and the theme package with hostnameOverride — and because quote -> accept -> e-sign is then one hop, since EsignGenericEnvelope binds any record via (context_type, context_id). Reusing it was only viable once the /{locale}/ i18n work landed; all 31 strings are translation keys sourced from the dictionary. Money and dates format through next-intl using the quote's own currency and the server-resolved timezone (recipient member -> org -> UTC), never the viewer's device. An expiry rendered in the wrong zone can name a date on which the offer is already dead. Adds the platform's first real @media print block. "Print Invoice" in kamo-internal has always printed the whole app chrome because no @media print rule existed anywhere; here the same markup prints as a clean Letter document with the brand accent preserved (print-color-adjust: exact — a colourless quote reads as a draft), the action bar suppressed, and page-break-inside: avoid on rows and totals. Terminal states are deliberately asymmetric: EXPIRED gets an honest branded page naming the date and the org's contact details, safe because the caller already proved possession of a 256-bit token; unknown/revoked/wrong-org all collapse to one generic page so the surface cannot be probed. The client whitelists the reason before rendering. The token never travels onward in a URL — the server-side resolve posts it in a body, and the BFF forwards the real client IP explicitly because APIService stamps X-Forwarded-For from its own inbound request, which would otherwise put every viewer in one rate-limit bucket keyed to the pod IP. Adds SECURITYSERVICE_URL to the configmap (verified: kamowssecurity-service exists in the kamo namespace).
· SecurityService
引文REST地表——工作人员管理和公众共享链接
工作人员在/api/安保/商业/报价的终点和一个未经认证的解决者 在/api/安全/公共/引文。 引用控制器扩展 BaseLos 控制器而不是复制 POS 控制器 序言:呼叫者会议解决方案接受 X-OTK 属性, X-***-托肯 标题和 *** 饼干,其中 POS 主计长的私人获取 OrgId 只读 OTK属性. 每个管理人员都享有权利。 大多数 商业表面只是会话——任何经认证的龟类成员都可以变异 命令——故意不在此重复,因为引文规定 在顾客面前价钱 引用 Public Captain 不需要安全配置 : Spring 链条是 任何请求 (. permitall () ) 和 OTKPreAuthFilter 仅在 X- OTK 标题上行事,该标题 在电子邮件链接之后的浏览器不会发送 。 设计点 : - 信使到达了 POST 机体, 从来没有一个 URL. APIApp. forward() 日志请求 在一个路径上的无记名证书 将会落到这些日志中 - 不是点名词:未知、被撤销和Org-mism相配的符号 返回一个无法区分的通用失败。 只有ExPIRED得到一个具体的, 诚实的回答,这是安全的,因为打电话者已经证明拥有 256位符号. - 请求主机生成的ORG与请求主机上的ORG进行交叉核对。 链接行。 没有它,在Org B主机下打开的Org A的有效链接将 使得A的定价 穿着B的品牌 —— 一个钓鱼的原始。 - 无商店/参考文件政策:无参考文件 / X-Robots-Tag:无索引 反应。 页面从主题加载了标识 。 <org>,一个参考人将携带 标志非原产地。 PublicLinkRateLimiter是Redis支持的,因为SecurityService是多版本的- 程序内计数器将只是名下的一个限制器。 很明显,这是DOS和 log-hygiene protection, Not the anti-guessing control: 有256个位元的 en. 失败的计算远比成功更严厉,因为有一个办事处开设了一个办事处。 转发引文50次是正常的,50次没有。 它没有打开,所以 a Redis 断电不能将引文页取下。 引文EmailClient重用电子邮件Service交易路径(X-Internal-Auth, QUOTE SENT 模板),并且只发送标题图加链接——从不发送 逐项定价,所以转发的电子邮件本身不是披露。 先前存在的试验故障,没有因这一行为而改变(通过储存这项工作加以核实) 并重新运行在干净的头上: **************** 无效的 NPE 实体管理器和遗留的 com.retval 安全服务应用测试缺失 a @斯春博特配置. 需要在这些结束点工作之前运行的 KamoInitializer Service: 引用表 新的和ddl -auto不在这里, 所以服务靴正常,只有引文 在 KI 运行前, 结尾点为 500 .
· kamo-shared-library
引文/估计域名-实体,定价引擎,共享链接
在现有商业脊柱外加一等引文。 先前存在的 "服务引文"是一个意向加一个JSON blob, 上面有一份礼物和一个平面 金额,没有收件人,没有过期,也没有UI;它不是一个基础。 扩展 意图也遭到直接拒绝:商业 意图由LOAN APPLSION分享, RERTAL request, substitution SIGNUP and PUCHASE request, 因此引用了 ~25 列 将永久NULLs设置在抵押和租赁的道路上。 实体 **************** 引文使用链接, 版本, 有效 直至 + 有效 天数 引文Line 项目快照名称/ sku/ 价格, 所以发送的引文不会重新定价 引用ShareLink无记名证书,SHA-256休止,撤销/过期/查看记录 引用 LinkView 的开放式审计( ip, 用户代理) 引用 Event 附录中仅包含的生命周期线索 总计为服务器授权. 引用Totals是每一笔钱的独家作者 字段和请求的 DTO 完全不包含总和 — 有意与 创建《零售令》,它需要小计/税/全逐字记录,并可以交给 人口顺序,总数=0. 在引号级别之前适用行折扣 折价,折价永远不能超过基数,中间数学停留在 4级,只有货币小单位的总和。 共享令牌:32字节的安全Random为43个base64url字符(256位). 一样 Entropy 作为电子签名签名符, 但短于 21 个字符, 保留电子邮件的 URL 在76Char的平面文字包装限制下。 只有SHA-256是坚持不变的. 税务是诚实的而不是发明的:平台没有税务引擎(TaxClass/) TaxZone/TaxRate可编写且没有计算读取),所以ENGINE模式 而不是在商业文件中编造一个数字。 引文使用过时参数coauthors (帮助) QuoteLine Project.taxClassId为UUID,匹配TaxClass的真实PK——提供.taxClassId 是对UUID键表的长并结构上无法解决。 此外:权利178-180(VIEW/MANAGE/SENDQUOTES)和QUOTE SENT教义电子邮件 模板,注册于CANONICAL KEYS(缺下表示永久404). 35次测试涉及定价引擎和象征性卫生. 整个套房:896路经. Schema 注:这些是新的表格。 服务员必须先跑 警卫 服务为引用端点服务——ddl-auto没有,所以 服务靴很好, 结尾点500 在缺失的关系,直到它做.
· KlusterServices
作为 CiliumNetwork 政策的Avatar 解析器的 Egress 封存
恢复到8f6c672的状态, 以唯一实际工作的形式。 之前的尝试失败, 因为一个简单的网络政策无法表达 集群的地貌。 保安处的四大关键依赖中的三个 节点,不在吊舱网络中——蟑螂db-0和nats-k1m1-0运行主机Network, 而MinIO是一个主机进程——因此一个cockSelector永远无法匹配它们. 这个 非明显部分,以及第一次补丁尝试也失败的原因,是 节点子网的 ipBlock 也不修正它: Cilium 将节点分类为 保留主机/远程节点身份,而 CIDR 规则故意不匹配 保留身份。 实体是唯一表达它的构造。 两种失败模式都是在写之前用一个被丢弃的金丝雀舱复制的 这,而不是反对生产。 金丝雀背负着同样的规则 一个鲜明的标签, 即 ipBlock 版本是如何被无声地屏蔽的 。 CockroachDB,NATS和MINIO同时看起来很合理. 在金丝雀上验证,然后在SecurityService上确认,没有重启,也没有 连接出错 : ALLOW dns, crdb:26257, nats:4222, mio:9000, redis:6379, 兄弟姐妹:80, 世界:443 BLOCK节点:22,节点:443,kube-api:443, redis-via-node:6379,169.254.169.254,回放:9000 最后四个是重点:解决器中的SSRF现在无处可去。 这个 密码中的警卫仍然是主要控制——这是唯一了解 DNS重新约束——这是背后的防御. 头带金丝雀程序。 任何改变这一点的人 应该重新运行它 Cilium的身份模式没有平庸的表现 网络政策直觉显示,没有中间环境.
· kamo-internal
显示组合对话的相片
上面有五个人的线条 由一个专横的面孔代表 读作一个人的留言。 最多3名与会者现在重叠,所以 "几个人"一看就看得出来,不需要解析出名字行. 3:过去,圆圈缩小到可识别性以下和行 改为纹理而不是信息,其余内容已在 旁边的"和N其他人"文字 读者被从自己的线程列表中过滤出,对方领导—— 脸部从左到右读取,所以主要通讯员必须是最左边的 还有那个背着未读的徽章的人 每张脸都有一个戒指 背景颜色; 没有它, 一叠类似相片会合并为一个形状。 决议现在涵盖第一批参与者,而不仅仅是牵头者, 否则,第二和第三个面孔会永远坐成一团.
· SecurityService
输入链条、接收过期的条目、记录披露
此特性中的每个失败模式都沉默. 一个断路器,一个工人 队列丢弃每个任务, 一个开始返回 HTML 的提供者—— 每个外观 就像"这个记者没有照片"一样, 这也是正确的 行为看起来像。 工作与工作之间不存在用户可见的差异 完全死亡,所以必须测量。 度量衡( Prometheus 已被接通, 所以这主要是命名): 缓存被击中 比例,按回答的级别标出链条持续时间,每位提供者被击中/遗漏, 工人队列深度, 以及丢弃的任务总数 。 上次用的那个 放弃政策,它通过设计默不作声地下降;它现在增加了一个计数器, 由于字段初始化器运行在 源头命令和依靠懒惰的捕捉会破坏无害的再秩序. 披露会到他们自己的记录器。 只有身份等级是个人的 披露——域级传送地址的右侧。 在电话之前而不是之后记录,所以 线索即使请求失败也存在。 地址是满文和 故意的:关键是回答"这个人的数据是和谁分享的". 和大麻不能回答这一点。 收割者关闭了一条漏道:删除在存在之前的过期而无所取名,所以 发件人 身份永久地增长. 一个忙碌的邮箱 触摸了成千上万的记者 每个都留下一行负数 测试覆盖取取器与真正的套接字, 因为有趣的是 所有提供者行为而非逻辑: 404 具有有效图像 (DuckDuckGo),一个服务于HTML的软-404,一个来源被低估的内容-Length, a 1x1分机, 和方向转向 瞄准到吊舱网络。 制作客户端不能 指向回回转测试服务器 — 它的 DNS 针拒绝解决任何问题 私人的,这是整个问题—— 所以那些跑对一个放松的客户和 针是分开主张的.
· kamo-internal
将摄入的 LLPA 矩阵推广到控制台的调整中
摄取面板只能发布一个收取率表. 用于 LLPA MATRIX 来源 文档它现在显示一个“促进作为 LLPA 调整”的卡: 选择现有的 利率表版本 LLPAs 调整(+ 一个可选的组),每个被批准 FICO/LTV桶成为有条件的价格调整. 结果名称如何 老实说,有多少行被跳过 因为一个桶 无法安全阅读 或已经存在。 Api. 促进调整 给新的网关中继器.
· SecurityService
将 LLPA 矩阵推广到有条件调整的网关中继
======================================================================================= 促销- 速率表中继: 符合上帝资格的门, 组织 Id 服务器被挂上 下游 4xx 中继 让一个管家转身 审查了LLPA矩阵,从控制台将价格按实际情况进行实际调整.
· VOIPService
录音、语音信箱和录音记录
记录回放没有留下痕迹 。 有记录的呼叫是最密集的PHI 平台商店——未编辑的对话——并"谁听了这个 无法回答,这是第一个问题 §164.402 评估要求。 向每个显示其内容的读取器提供记录: - 获取/录制/{id}/音频呼叫- 重播/下载 - 上车吧 呼叫中/下楼 - 获取/录制/{id}呼叫-重唱+TRANSCRIPT/VIEW - 上车吧 呼叫中/下楼 - 获得/通知/{id}/语音信箱TRANSCRIPT/List,每行 笔录为所藏. 这不是媒体下载,而是骑车 在元数据 JSON 和每个语音信箱行内, 这是相同的 PHI作为音频的形式是grep. 它有自己的活动,因为 披露的核算按资源汇总。 字节服务失败关闭, 因此 PhiAuditAvailabilityAdvice 变成不可注册 读为503而不是500——请求是好的,我们解码为: 服务PHI 我们无法解释。 拒绝也记录在案; 检测到的是什么 还关闭了在布线时发现的授权缺口: POST 记录/查看从请求中取出一个实例,从未 检查了打电话者的Org拥有它, 所以它解决了另一个租户的供货商 给他们录入的身份证打电话 中其他实例的终点 服务已经通过查找ByIdAndOrgId;这个现在也是。 记录回放的授权保留在原地并记录在原地: org 所有权是唯一的检查,因此任何成员都可以在 他们的鸟类。 缩小意味着决定“所有扩展”是否是 边界和哪一个权利解除了它——这是一个产品决定,而不是一个 猜到这里,每个访问至少现在都记录下来了.
· AIService
在存储的 AI 对话历史的每个读取记录 PHI 访问
将共享的 第164.312(b)条脊椎线接入读取的路径 和完成情况。 助理是评估遵守情况的单元 外出边界——在没有BAA和BAA的情况下,向外部供应商发出风扇。 然后被无限期地保存——所以,阅读该商店是披露最多的 他们没有线索 审计:会话列表和历史搜索(每次对话一次,不) (每个请求一个),单一对话的元数据及其信息,公众 部件读取它自己的笔录 和交割捆绑。 拒绝是 也记录下来了——探测出另一只猩猩的沟渠就是探测到的——而且 未经认证的尝试 归结于哨兵 而不是掉落, 因为记录者拒绝它不能描述的东西 而这是最伟大的事件 值得保留。 手提包是DISCLOSE,不是VIEW:它携带一个访客的 与AIService的谈话 在另一个产品的人类面前 那个 类型失败了,所以丢失的记录 现在扣留记录和答案 503 而不是它无法统计的数据。 仅指名. 永远不要信息机构、标题或搜索名词——成员 搜索他们的助手历史 将借款人的名字输入其中,并且 复制提示的审计线索 只会把PHI移入 日志流。 完成d428ee3,同时举行的届会将中期变化:审计员 缺少记录 Denied InternalView 和 PublicAiChat Captain的新记录 建筑师的论点没有达到标准.
· MediaService
记录聊天消息读取返回正文的端点
发送消息留下一行;读出一行没有留下任何东西. 每次聊天,支持和 平台上的社交线条 是从这里的几个端点产生的 没有 他们录了什么,所以"谁读这个谈话" 没有任何答案—— 第一个问题是164.402号违约评估。 ChatMessage AccessAuditor 发布一个来自 5 的 PhiAccessEvent(CHAT MESSAGE) 发送呼叫器消息文本的路径 : 获取QQ 名单 获取/api/媒体/会议/聊天列表 后 . 视频 获取QQ 名单 后 . 视频 每个消息一个事件,而不是每个请求一个事件. "他们打开了线"不是 回答"是否透露了这个人的讯息",而消息的ID是 因此,一个请求形状的行将是一个 选择而不是限制。 线程读取记录了哑弹过滤器之后, 因此,一行意味着一个尸体 呼叫者被实际移交。 聊天列表属于范围,因为每行最多可包含140个字符 线程的最后一条信息——即内容,而不是元数据. 带有空预览的行 记录什么。 故意不记录:未读计数、存在、最后查看、打字、读取 收据、会议成员名单、哑巴、票务细节(元数据加状况) 报告总数。 一条线索只有在 划行意味着有人看到了内容;划行代表了无所事事的将那些做活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活 拒绝也记录在线条guid上——在 拒绝的点, 和反复拒绝对线盖德是形状 调查有。 未经认证的读者 被归结于一个哨兵 而不是 已删除: 记录器拒绝无法解析的事件, 这是最简单的 这条线索可以举办有趣的活动。 客户端 IP 来自于 X- Forwarded-For, 远程添加器为倒置—— 一切 通过Traefik到达, 所以远程Addr独自记录了入侵舱。 公开聊天 通过 APIService 跳出第二回, APIService 设置 X- Forwarded- For给访客 地址和移动浏览器的用户代理到 X - 原始用户代理,所以 审计师更喜欢该标题;该hop上的字面用户代理是APIService的 拥有HTTP客户端,并识别无人. 访问者读取的都是Org 从X-Public-Chat-Org-Id,无成员身份号码:访客无成员身份 他们自己的,但Org拥有记录, 所以读取保留归属。 只有识别器,从不发短信。 复制消息的审计线索 它的审计刚刚把 PHI 复制到日志流。 也完成了eed3817,它扫描了 这项工作在中版并离开了媒体主计长 导入前参考 PhiAccessKind —— 该修订没有 编译. 这个是:mvn -o测试为16/16绿色.
· DocsService
在四个没有记录的文档路径上记录字节访问
/ 下载已登录通过 QQ 而它是 平台唯一的字节访问注入网站。 兄弟会的终点 完全相同的字节——/stream,/bulk-download,模板已转换-PDF和 模板页面缩略图 — 没有记录, 所以需要文档字节的人 没有留下痕迹,只需选择不同的URL。 所有四人现在都放出一个PhiAccessEvent在点 访问已经核实, 字节即将送达 。 大量下载每个文档发出一个事件,而不是每个请求一次。 "他们 输出400个文件"不是回答"是这个人的记录吗? 6年后,每行文件 才有答案 第164.528节。 客户端 IP 来自 X- Forwarded-For, 远程添加器为倒置: 每个请求 通过Traefik到达, 所以远程Addr独自将记录 入侵舱为 每一次访问都没用 未经证实的企图是被归因于哨兵组织而不是 已删除 —— 记录器拒绝无法解析的事件, 以及文件请求 没有会话的字节正是值得保留的事件. 这与现有的 ImgLogDown 列相邻, 而不是替换它们 : 这些是成像领域记录 这是跨地表的线索 记录 信息披露从中汇总。 注意 ImgLogService, 读这些行, 仍然 月台上任何地方都没有呼叫者.
· KlusterServices
控制从avatar 解析器出入境;注意Redis 驱逐池
Security Service 现在运行一个获取器,其目标 URL 被一个不信任者选中 Party——BIMI唱片是DNS内容,由拥有发送域的人发布, 任何人都会成为发送域 通过电子邮件租户。 本组没有 在这种请求可能发生的情况下受到限制: 9000上的MinIO,有根证书,26257上的CockroachDB和节点元数据 结束点可以从任何舱得到。 解决者在代码中执行自己的控制 那些保持主 因为它们是唯一能理解 DNS 重新绑定的层。 这是 第二个,所以一个错误仍然无法到达一个私人地址。 故意允许 - 而不是允许 - 名单。 这些服务可以合法地达到 主机,所以列出的目的地将无法维护,并且会中断 安静 相反,它允许公共互联网 每一个私人范围除外, 然后重新许可实际需要的特定集群内端口。 范围到舱 执行不信任的取来——应用它全名空间将切断 从未接受过审计的服务。 Redis的改变是评论和数据库的凸起,而不是行为改变. 这个 记录发件人- avatar 缓存为何只存储短元字符串: 最大 2gb的全键-lru驱逐 整个案例, DB 0 持有每个活 会话,所以这里的大块字节缓存会在压力下随机签出用户 并被误诊数日.
· kamo-internal
显示发件人和收件人的照片
邮箱给每个人做了一个 共享梯度的单个字母,所以 每行看起来都一样 圆圈没有信息 现在显示 通讯员的真相,当知道一个, 当两个字母单格 没有。 一个发信人Avatar取代了七个手卷起的首字母圈. 这很重要 不止于一致性:每个人都有自己如何分割地址的想法,以及 变形符缓存被键于此分割, 因此列表和 读取面板会默默地将命中率减半,并显示同一人两个 一个屏幕上不同的方式。 解析器现在是唯一一个 RFC 5322 的地方 地址被拆散。 列表和线程视图也停止打印原始信头 如"Jane Doe <jane@acme.com>"并显示名字. 身份住在自己的商店里,按地址键,永远不要在信件对象上. 每30多岁和每封网络通讯通知, 替换其信件阵列批发——任何合并到信件上的东西都将是: 一分钟擦了两次,所以一个闲的收件箱会把相片闪到单格和回放 永远 用地址按键也意味着迟到的答案无法被画入 错误的行,因为行不是它所按键。 请求已合并 每个屏幕分为一批: 50行独立询问为 50 请求,并且由于每一次调用 服务薄荷先是一次性的密钥, 其实是一百个。 45后再次询问出错, 因为服务器侧 解析是两阶段的,一个未知地址只有在以后的呼声中才能回答。 对话 ListView 现已虚拟化. 它取出50行一页, 并重发 所有在动画界的人 都会在每一次民意测验中错开一个指数 每个都加了一幅相片,使它成为了邮箱中最重的表面. 无复制和邮件守护程序发送者获得中性标记而不是单克——a 一张弹出通知旁边的相貌会让人产生误解 照片是装饰性的 (alt=""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""",""""""""",""""","""",""","",",",""",",","","",""",",""",",""""",",",""",",",""","",""","",""",""""","",""""","""""""""","""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" correrpolicy="no-referrer",所以线程标识符永远无法到达图像主机. 每个阿凡达都来自我们自己 第三方的图像被取出 经验证和重新托管的服务器侧面——这是允许每个请求新增的 igg -src政策 继续固定在租户自己的领域。 这项政策是建立在 代理而不是下一个。 配置, 因为此平台带有白色标签: a 静态政策需要指定一个租户,并打破其余的图像。 也关闭了自"接触"以来已经存在的存储跟踪-像素向量. 摄影机 是一个直接在多个“img src”中渲染的自由文本 URL。 下一个/图像不再接受远程 SVG 。 这是可以接受的风险 当唯一的 SVG是我们自己的主题标志;现在不是平台摄入标记的时候。 在第三方DNS中发布. 联系人将硬码的 ORG ID = 1 和 orgId 查询参数, 匹配会话产生的后端变化.
· EmailService
Avatar endpoints; fix unauthenticated reachability and contact tenancy
Adds the mailbox side of sender avatars, and fixes three pre-existing holes this work would otherwise have built on top of. AUTHENTICATION. OTKPreAuthFilter used to reject a *bad* OTK but treat *no* OTK as anonymous-and-allowed, falling straight through to the filter chain — and the Spring Security chain here is anyRequest().permitAll(). Every mailbox, contact and calendar endpoint was therefore readable by anything that could reach the ClusterIP. Protected prefixes now fail closed. The fix lives in the filter rather than in the security chain deliberately: reshaping the chain would touch thirty unrelated surfaces at once, including two servlets and the DAV endpoints. The exempt list is the complete set of genuinely session-less entry points — the CAN-SPAM opt-out link, the OAuth redirect target where the tenant rides in the signed state parameter, and the server-to-server surfaces that authenticate with X-Internal-Auth. CONTACT TENANCY. Every contacts endpoint took orgId as a query parameter, or reached a book by id with no ownership check at all, so changing a number in the URL read another tenant's contacts — names, addresses, phone numbers, notes. The org now comes from the session and every book- or group-scoped operation proves the target belongs to it. Absent targets return 404 rather than 403 so an id in another tenant is not confirmed to exist. orgId is still accepted on the two list endpoints and ignored, so clients do not break mid-deploy. That change also fixes a silent bug: searchContacts derived orgId from bookId and passed null when no book was selected, into a query whose first predicate is contactBook.organization.id = :orgId. Book-less search therefore always returned nothing — which is exactly how the mail recipient autocomplete calls it. EMAILLOGOSERVICE. It fetched an operator-supplied URL with no scheme or address check, and transcoded the result on a Batik that resolves external references by default. A logo SVG containing <image **************** would have been dereferenced from inside the cluster. Now guarded on both ends. MESSAGEINDEXER. resolveMemberIdFromEmail pulled the entire members table into heap and filtered it in Java, once per indexed message, on a 1Gi pod — the code said so in a TODO. Same semantics, one indexed query. The avatar surface is one batched endpoint rather than a field on the message DTOs. Both list views poll every 30s and replace their message array wholesale, so an avatar carried on a message would be wiped twice a minute and the UI would flicker forever; and EmailMessage is shared by the folder list, reading pane, thread view and search, so changing its shape would touch all of them at once. The directory-photo endpoint is server-to-server only — exposed to a browser it would be a directory-enumeration oracle for the tenant.
· SecurityService
Sender-avatar resolution chain for the mailbox
Resolves a correspondent's email address to a picture, working outward from what Kamo already knows: member photo, then a photo someone attached to a contact, then the tenant's connected Microsoft/Google directory, then the sender domain's BIMI mark, then its favicon, then Gravatar. Anything unresolved renders a monogram, so the chain always terminates locally. The directory tier is worth calling out: the connect flows here already request admin.directory.user (Google) and User.ReadWrite.All + Directory.Read.All (Microsoft) alongside the mail scopes, so for Workspace and 365 tenants this returns authoritative photos with no re-consent and no third party involved. It should beat anything on the public internet and usually will. Two phases, never one. A request reads cache only; unknowns go to a bounded worker with DiscardPolicy — running an overflowed task on the caller would hand a request thread to a third-party host, and a discarded resolve costs nothing because the next poll asks again. A full-miss chain is DNS plus four HTTP calls, and a page carries dozens of addresses; nothing about opening a folder may depend on third-party availability. Decoupling also keeps resolution from correlating with a human opening a message, which would make it a read receipt — the exact behaviour the mailbox already blocks by default for remote images. This is the platform's first fetcher whose target URL is chosen by an untrusted party: a BIMI record is DNS content published by whoever owns a sending domain, and anyone becomes a sending domain by emailing a tenant. There is no egress NetworkPolicy and no forward proxy, so the controls are in code. SafeImageFetcher pins DNS — a custom resolver hands OkHttp only the addresses that passed PublicHostGuard, closing the rebinding window that defeats a naive pre-flight check — refuses redirects, caps bytes as they stream rather than trusting Content-Length, and requires an image content-type. SvgSanitizer parses and re-serializes against an allowlist instead of rasterizing. Batik 1.17 resolves external resources by default, so handing it a hostile SVG would dereference <image **************** from inside the cluster after the URL check already passed. The Tiny PS profile forbidding that is a statement about conforming files, not about bytes fetched from an attacker's URL. Provider miss semantics are all different and all cache-poisoning if treated as hits: Gravatar is asked with d=404 because every other default returns 200 with a placeholder; Google's no-match is a 404 carrying a byte-identical globe, so it is rejected by content hash; DuckDuckGo returns 404 with a real image body, so status decides. Bytes are re-hosted under a random name — never one derived from the address, which would let anyone probe whether a given person corresponds with this platform — and served through an authenticated route. Redis holds metadata only. That instance is 2GB with allkeys-lru on an emptyDir, sharing a keyspace with every live session; caching image bytes there would evict sessions and sign users out at random.
· kamo-shared-library
发送者身份模式 + org- scoped 批量电子邮件查看
后置商店和查询邮件发送-avatar链. 发件人身份实体(SenderIdentity Entity)是可复制缓存的可持久级. org id 属于 自然密钥而非装饰 : USERS. EMAIL 只有每个安全器才独一无二 。 因此,从租户数据得到的答案不能被另一个人看到 租户. 外部层面的答案(BIMI/favicon/Gravatar)确实是全球性的,而且 所以每个房客都分享命中率 误差为 排行,而不是缺行——没有这些,每个无法解决的发送者都会重新运行整个 每次收件箱民意调查的供应商链 OrgAvatarSettings Entity将链条由实际离开的建筑物分出. 身份等级默认关闭,因为它披露了通讯员的文摘 致第三方的完整地址,关于借贷客户关系管理的决定是: 借款人标识符而非显示偏好. 储存库的添加之所以存在,是因为在此之前这些都无法达到: - 联系人电子邮件存储器完全没有地址查询 - 只有子字符串像 自动完成 —— 因此无法解决有相片的联系人 。 a 发件人:信头。 - 成员/用户批次检查为Org范围,并采用预小写输入。 LOWER( ) 仅适用于所存储的一栏; 电子邮件用逐字记录粘贴 (EmbEmail没有常态化) CockroachDB 平等是大小写敏感. - 假象式预测是故意返回标识而不是实体。 两者 成员. 交易外的呼叫者会得到Lazy Initialization Exception, 以及里面的一个 获得一个从不缩小到 AvatarPhoto 的基础类型代理, 将文件放入 需要扩展来构建无法到达的 URL 。 - **************** 替换查找 All () 每一个索引信息运行一次的全表扫描。 PublicHostGuard是共享而不是重复的,因为它是一种担保 控制:它决定地址是否在某个地方,我们将发出一个请求: 一个不信任的政党选择了。 测试过真实的绕行技术—— IPv4- 映射 IPv6,6to4,NAT64,CGNAT和链接-局部元数据. 右177门 披露决定.
· kamo-shared-library
Audit spine for PHI access — §164.312(b)
The Security Rule requires recording access to ePHI, which means reads. The platform records changes well — LeadHistory, SystemAccessLog, UserHistory, LoanAuditEvent — and reads almost nowhere, which is why "who viewed this record" is currently unanswerable. That is also the first question a §164.402 breach assessment asks, so this one gap blocks both the audit control and the four-factor analysis. Capture layer only; no schema. The durable store sits behind PhiAccessLogWriter so call sites can be wired now and the sink can evolve — plain table, then append-only with a hash chain, then a signed export to object-locked storage — without rippling back through hundreds of call sites. Two properties carry the weight: - Failure handling belongs to the access kind, not the caller. EXPORT, DOWNLOAD and DISCLOSE fail closed: an unlogged bulk export is exactly the event you cannot reconstruct afterwards, and "we served the data but lost the record" is the worst answer to give an investigator. VIEW, LIST and SEARCH fail open and log loudly, because losing one line is not worth taking the product down. That asymmetry is deliberate and wants signing off rather than assuming. Callers under pressure resolve policy questions in whichever direction unblocks them, so the policy is not at the call site. - A denied read is still a read. Refused attempts are recorded, because the access pattern of someone probing records they cannot reach is what detection needs and is invisible if only successes are logged. Startup safety, which nearly went wrong: PhiAccessRecorder is a @Component and every service component-scans com.kamo, so a hard dependency on a writer bean would have failed context startup across ~40 services at once — a whole-platform outage from a feature nothing had called. The first fix, a @Configuration with @ConditionalOnMissingBean, does not work: component-scanned configuration is processed alongside user configuration rather than after it, so both writers register and injection fails on ambiguity. PhiAuditContextWiringTest caught that. The fallback now lives in the recorder via ObjectProvider.getIfUnique, where no ordering question exists, and ambiguous writers degrade to the default rather than failing startup. The default Slf4j writer is a starting point, not the destination — log lines are not tamper-evident and retention is 14 days against a six-year obligation. It exists so call-site wiring does not wait on the store. Identifiers are logged, content never is: an audit trail that reproduces the record it audits has just moved the PHI into the log stream.
· SecurityService
403个而不是500个在遵守边界拒绝时
两处调用网站的地物Service.enableFeature 现在了解HIPAA边界: - PhiModule NotPercentException的可使用地图403载有理由, 反射其上方的应用模型异常处理。 无 因此,下面的广泛渔获将蓄意的政策拒绝变为500起。 - 上市路径中可自动启用的回路,预先检查是PhiPerucent和 跳过。 它贯穿了每一个完成的 ServiceType 而仅仅 * 列出 * a 所以在第一个被封锁的模块上 PHI 租户可以卸取的特性,而不是隐藏一个条目。 今天的惰性——每个组织都是处理Phi=虚假的.
· kamo-shared-library
在特性切换时执行遵守边界
电线 PhiTenantGuard 进入 Feature Service, 单一的阻塞点, 一个通过 为一个组织打开模块。 这就是边界停止的地方 政策对象并开始强制执行。 两分之一,因为要么单独留下一个缺口: - 允许Feature扔出 PhiModule NotPerdicentExcuse, 所以PHI租户不能 切换模块 Kamo不能作为商务助理站后。 - 是FeatureEnabled(组织、服务Type)报告一个模块在何时禁用 租户处理PHI,单元在边界之外,无论 鸟兽行说. 该行可以合法地说活动——它是被允许的 在租户成为PHI租户之前,Feature不再运行 那个过渡。 是PhiPercentind是给远方的呼叫者的不扔放形式。 特性控制器 * 列出 * 时每个完成的特性自动启用, 所以对第一个 被屏蔽的模块会失败整个特性页面而不是跳过一个条目 。 PhiServiceTypeMapping 将 ServiceType 绑定为 PhiModule , 并且是总计, 有测试 以未映射的值创建失败 。 测试是先得的 运行:它捕捉到ServiceType.STORAGE, 一个肽的grep丢失,然后 AI CHAT,DOC MANAGER,DOCS EDITOR和DOC CLASSIFIER. 没有它,五个服务 类型在边界之外会默默无声——同样的遗漏失败 PhiMudule的构造器关闭, 重新增加了一层。 用于以前未映射的服务类型的新模块,每个模块都有明确的 处理: 对象存储、文档编辑器和分类器、 支持票、 HR、 内部有库存、法律、计算器和活动饲料;俱乐部和游戏是 以未经评估为理由, 阻止而不是假设 今天每个组织都处理Phi=假冒 所以这改变不了 生产。 当第一个租户被标注时,它就会充满负载.
· kamo-shared-library
在应用程序创建时自动指定一个与 MERS 兼容的贷款号码
LoanFile.loan Number在创建上是无效的(空白创建和铅促进) 并且只有在一个机长打入一个—— 硬锁的 MERS MIN 时才设定 薄荷(MIN的10位数部分是贷款号码)和下游的每个部分 无头贷款的标识符。 AppMortgage Service 现在在两个创建站点分配一个贷款号码: 一个干净的 10位数 (MinMinter 脱去非数字并需要一个 QQ-10 位数段, 因此,一个纯数字是唯一的安全形状,每个矿石通过 (org id,出借 数字) 索引有限定重试. 它会打开一个无效的 相撞相撞或无法取回的相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相撞相 行为而不是永远打破 应用程序创建。 贷款人提供 数字仍然通过借出文件补丁路径覆盖。 计划不变 列已经存在,已索引.
· kamo-signer-monorepo
发件人解析时区中的发件人签名日期
签署会议收益(IANA id) 从接收者的成员区,然后是Org的,然后是UTC. 欢迎史克林 因此,失效日期取决于 查看器的设备设置或提供者的UTC默认值. 创造土地 需要而不是可选地夹住一个字段的施工现场 (preview.ts)在编译时间. 还: - 调用设置 片段而不是只依靠中间软件头 - 在Docker文件中断言,信息/在 " turbo prune " 和文档中幸存 .dockerignore 为何必须让.gitignore 远离建设背景;没有这个背景 组合 prune 丢弃翻译和图像船生成原始密钥 在签名器打开文档前, 没有失败
· ESigService
解析符号显示来自成员的时间区, 然后 Org
在客户端默认的区域内, 指定了签名日期, 所以 信封已到期 2026-08-03T05:00Z 可以读作“ Aug 3 ” 到太平洋签名器 8月2日晚上 联系已经断了 签名会议现在带有服务器解析的 IANA 时间Zone: 收件人的 拥有会员. timezone 当他们成为会员 并设置了一个, 或者发送 组织.timezone,其他UTC. 签字人Zone是一个纯净的解决者,有测试, 包括一个将每个时区Type的地图 enum值不能发送客户端 RangeError 。 还修正了发射enum名称的签名会话. locale(西班牙语) 而不是签名的 URL 地块中使用的 BCP-47 代码 ("es") .
· InitializerService
在 Orgs 上创建 HANDLES PHI 和 PHI 有效日期
以 OrgBranding Fields 迁移方式镜像两个新的组织字段 因此,栏目可以复制到任何环境中,而不仅仅是 正在运行 ddl -auto 通道。 Handles Phi不是NULL DEAULT FALSE 所以现在的租户明显在外面 遵守边界。 PHI 有效日期是TimestAMPTZ,而不是TimestAMPTZ, 因为实体字段是本地时间。 测试是一个漂移的后卫,而不是一个重述:它读取了列名,而不是 当一个实体字段没有 ALTER 时,通过反射实体并失败构建。 那个 这是公约的实际失败模式——有人添加了字段,忘记了 迁移,和ddl-auto: 没有任何服务 它表面作为一种生产 查询错误而不是构建时间 。 经变异校正:去除 PHI 有效日期 换句话说,它与可操作的信息失败,恢复它 绿色去。 两列都已经出现在集群中;这些“替代物”是一元的.
· kamo-shared-library
持久性处理 Phi 和 Phi 有效组织
后滇特南卫以正栏. (掌声) {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}所以现在的每个房客 明确在遵守边界之外,而不是默默地在边界内。 PHI 有效日期包括违约评估和保留义务 右窗口——"从"何时起"是"什么被曝光"后问到的第一个问题. 用 QQ 转换为策略 警卫 自己远离实体,所以只持有会话标记的呼叫者 不需要装入一行。 安全可推:集群中已经存在两栏,每栏12个 组织错误地解读。 登陆前根据信息验证... handles phi 布尔 NOT NULL DEFAULT 假想, phi 有效的 日期时间戳 NULL 。 关于可再生产的形式,请参看 " Kamo Initializer " 迁移.
· kamo-shared-library
PhiTenantGuard 和模块合规边界
HIPAA遵守边界的关键:租户可能到达的模块, 鉴于房客是否负责保护健康信息。 所有的东西 其下游键——其中的整合被禁用,无论外交部是否强制, 审计脊椎必须涵盖的内容。 没有计划依赖。 之前的一次尝试 把它挂在一个新的 Organization.handlesPhi一栏,必须恢复:服务CI克隆 KamoInitializer在建设时使用手操作的共享图书馆主机,所以 主机上的实体列断开下一个服务部署,直到有人迁移。 将政策与实体脱钩意味着它登陆,现在可以强制执行, 而柱子成为独立的一步。 设计有三个属性: - 失败者关闭。 PhiModule的建筑师需要PhiDisposition和理由, 因此一个后来添加的模块不能通过省略而继承权限——它不会 未经决定而编译,除PERMITTED以外的任何内容均否认. 这是 一个遵守边界必须生存的失败模式:一个模块船,没有人 想想PHI,一个诊所开始使用它。 - 未解决的房客不是安全的房客。 警卫要三等舱 PhiTenant Statistics 而不是布尔,所以"我不能装填组织"。 不能像"这个组织不是PHI"那样拼写. 与一个 布尔,错误路径是 perunition (false,.) —— 很容易到达, 无法在审查中发现。 不明世界否认一切 - 没什么好提拔的 决定是(状态,模块)的纯函数,没有 调用器, 会话, 右侧或神模式参数 。 "我们的支援人员可以打开它" 关闭"的答案是 被覆盖实体的审查失败。 处置遵循卡莫内部范围分析 **************** 允许:客户关系管理、联系人、文件库、 自办电子邮件、电子签名、笔记、任务、日历、内部聊天、集群 (原始内容存档于2013-10-12) (英语). Trightion/ translation sack, MLOS. 无法获取的BAA:社交 通讯 Canva 电子商务同步 MCP网关. 被屏蔽待命名的工作: AI路由器,RAG搜索,会议录音,VOIP录音,营销活动, 分析导出。 还没有人叫警卫,所以这是惰性的 直到窃听.
· InitializerService
在 Orgs 上创建 HANDLES PHI 和 PHI 有效日期
在 kamo- share- library 中映射本组织实体的两个新字段, 遵循OrgBranding Felds迁移公约。 (掌声) 因此,所有现有租户显然都不符合规定 而不是默默地在它内部。 PHI 有效日期是时间stamp,不是 TIMESTAMPTZ,因为实体域是"本地时". SEQUENCINCING——这需要在下一个服务部署之前运行. 服务针 Kamo-shared-library 在一个固定版本中重新发布,所以第一个 在库更改开始后重建的服务,以及 使用 ddl-auto: 无法完成的服务, 直到执行此跑者 。 随行的测试是漂移后卫,而不是重述:它读取了列. 以反射方式删除实体名称, 如果实体字段没有, 则构建失败 替代。 这就是整个公约的失败模式——有人增加了一个领域, 忘记了迁移, 它显示为生产查询错误, 而不是在 建立时间。 通过变异验证:去除 PHI FFEEC DATER 使它 以可操作信息失败, 恢复为绿色 .
· ESigService
在签名链接中发送签名器本地端段
提取字节对应字节重复的构建 SignLink 到 SignLinkBuilder 并添加来自Organization.language的本地语段,下降 返回英文,用于四个语言类型值,而不进行翻译。 需要先部署 kamo- signer /{locale}/ 路径 .
· kamo-shared-library
添加手柄 Phi 租户旗和 PhiTenant Guard
HIPAA遵守边界的关键:每个组织加一面旗帜 警卫队决定该组织可能到达的模块。 下游所有的东西 键外键 —— 哪些集成功能被禁用, 外交部是否强制使用, 哪个 课程得到更严格的超时, 审计脊椎必须涵盖的内容。 组织收益 HANDLES PHI(BOOL DEFAULT FALSE)和PHI 有效日期, 遵循现有的QQ模式。 默认虚假, 因此,这是无效的 现有的抵押和客户关系管理簿。 设计有三个属性: - 失败者关闭。 PhiModule的建筑师需要PhiDisposition和理由, 因此一个后来添加的模块不能通过省略而继承权限——它不会 未经决定而编译,除PERMITTED以外的任何内容均否认. 这是 遵守边界必须生存的特定故障模式: 没有人会想到PHI,一个诊所开始使用它。 -不能绕道 该决定是(组织、模块)与 没有呼叫器, 会话, 右或神模式参数, 所以没有什么 提升。 "我们的支援人员可以关掉它" 是失败的答案 实体审查。 - 拒绝是有原因的,因为一个赤裸的"拒绝"不能被支持使用 工程师或顾客 处置遵循卡莫内部范围分析 **************** 今天允许:客户关系管理、联系人、文档 保险库、自动托管电子邮件、电子签名、笔记、任务、日历、内部聊天、 编组中转录/翻译堆栈,和MLOS。 无法获取的屏蔽 BAA:社交信息,Canva,电子商务同步,MCP网关. 已屏蔽待命名 工作:AI路由器、RAG搜索、会议录音、VOIP录音、营销 运动、分析导出。 Schema 注: HANDLES PHI和PHI 有效日期在下一轮实现 Kamo Initializer运行,在CI出版这所共享-图书馆建筑后. 没有读 国旗还没有,所以订单是安全的.
