/** * Org 记忆准入 resolver — server 侧对接 @sema-agent/core@5.13.0 `RunnerDeps.memoryScopeAdmission` seam。 * 授权事实来自「目录」抽象:远程腿 = config-center per-principal caps 响应里的 `orgMemory` 段(形状 * 同源锚 = registry-core `PrincipalOrgMemoryWire`,zod schema 直接 safeParse);单机腿 = env JSON 静态表 * (`MEMORY_ORG_DIRECTORY_JSON`,{@link parseOrgDirectoryStatic} 装载,启动期 fail-loud)。 * * 判别联合 {@link OrgDirectoryLookup} 是本模块的核心裁定(设计 N3/C5):取数成功(granted,含零授权空表 * = 负结果)与瞬时不可用(unavailable)绝不塌成一格——granted 空表是 resolver 可以终局判决的「事实」 * (「这个 principal 没有这个 scope」),unavailable 必须让 core 铸瞬时码 memory.admission_required 重试, * 而不是被误判成「没这个 scope」而永久拒绝。 * * core 侧契约(RunnerDeps.memoryScopeAdmission,core types.d.ts):resolver 返回 {ok:false} ⇒ core 铸终局码 * memory.admission_denied;resolver throw 一个带 `retryAfterMs`(ms)属性的 Error ⇒ core 铸瞬时码 * memory.admission_required 并透传 retryAfterMs;{ok:true}.scopes 只能 ⊆ requested(多给 = resolver fault * 会被 core 整拒)。core 只在「存在 request-origin org scope 且 principal 缺席」时自己先拒——本模块仍防御 * `principal === undefined` 这一支(不能信任「core 一定先拒过」这件事)。 */ import type { MemoryScopeAdmission } from "@sema-agent/core"; /** * 单机腿:装载 `MEMORY_ORG_DIRECTORY_JSON`(`Record>`)。启动期调用, * **fail-loud**——任何非法直接 throw 且消息点名坏在哪个键(响亮拒是正确方向:一张半坏的授权表比拒绝 * 启动更危险)。principal 键复用 {@link assertPrincipalShape}(拒保留哨兵/超长租户名,与所有其它 * principal 入口同一道闸);scope 键必须是 `org:` 前缀、值必须是仅含可选 `write: boolean` 的 plain object。 */ export declare function parseOrgDirectoryStatic(json: string): Map>; /** * 目录条目的判别联合(设计裁定 N3/C5):`granted` 是取数成功——包括零授权空表(负结果,由 resolver * 判终局拒);`unavailable` 是瞬时臂(取数本身失败/形状不可信/LB 陈旧副本),只在这一支才该让 core 重试。 */ export type OrgDirectoryLookup = { kind: "granted"; scopes: Readonly>; } | { kind: "unavailable"; reason: OrgDirectoryUnavailableReason; retryAfterMs: number; }; /** {@link createOrgMemoryDirectory} 的产物 —— 单一 per-principal 查表口。 */ export interface OrgMemoryDirectory { lookup(principal: string): Promise; } export interface OrgMemoryDirectoryOptions { /** 远程腿:返回 caps 响应的 `orgMemory` 段原值(unknown,本模块用 `PrincipalOrgMemoryWire.safeParse` 校验)。 * 返回 undefined = 响应里键整体缺席(旧 center 能力握手)⇒ unavailable("section_absent")。 * throw = fetch 失败 ⇒ unavailable("fetch_failed")。 * 与 `staticTable` 互斥:二者恰好给一个(装配点保证;都给或都缺 = 构造期 throw,fail-loud)。 */ fetchSection?: (principal: string) => Promise; /** 单机腿:{@link parseOrgDirectoryStatic} 的产物。查表恒「取数成功」:缺 principal ⇒ granted 空表。 */ staticTable?: Map>; /** granted(含负结果)缓存 TTL——ms。负结果与正授权同 TTL:未授权 principal 不该比授权 principal 打出 * 更多流量。默认值不在本模块(接线点决定,设计定 60_000)。 */ grantTtlMs: number; /** 一次 unavailable 之后,同 principal 在这个窗口内的 lookup 直接返回 unavailable(不重新 fetch)—— * 防止对一个持续故障/未授权目标反复打 center。默认值不在本模块(接线点决定,设计定 10_000)。 */ unavailableBackoffMs: number; /** 时间注入(测试用);默认 `Date.now`。 */ now?: () => number; } type OrgDirectoryUnavailableReason = "fetch_failed" | "section_absent" | "malformed" | "stale_generation"; /** * 建目录:远程腿(fetchSection,per-principal TTL 缓存 + in-flight 去重 + 退避窗 + gen 高水位)或单机腿 * (staticTable,恒同步成功、无 TTL/退避语义——operator 自证配置面)。两腿互斥,装配点必须恰好给一个。 */ export declare function createOrgMemoryDirectory(opts: OrgMemoryDirectoryOptions): OrgMemoryDirectory; export interface MemoryScopeAdmissionOptions { /** "audit": 判决照算但从不真拒——会拒的结果(终局 ok:false 或瞬时 throw)一律换成全额放行 + 观测记录 * would-deny;真通过的判决(含 write 收窄为 null)照常返回。"enforce": 判决即结果。 */ mode: "audit" | "enforce"; /** 观测 hook。outcome ∈ "ok" | "denied" | "principal_missing" | "directory_absent" | "directory_stale" | * "directory_malformed"。audit 模式下的 would-deny 也走这里,`details.audited === true`。hook 本身绝不 * 允许打断准入判决——一律吞掉它可能抛出的异常。 */ onOutcome?: (outcome: string, details?: Record) => void; } /** core 侧「瞬时不可用,重试」契约的载体:一个带 `retryAfterMs`(ms)属性的真 Error 子类,core 据此铸 * **瞬时**码 memory.admission_required(503,重试可改判——与终局的 memory.admission_denied 恰好相对) * 并透传该值。子类而非事后挂属性——避免任何宽松断言就能拿到正确类型。 */ export declare class OrgMemoryAdmissionRetryError extends Error { readonly retryAfterMs: number; constructor(message: string, retryAfterMs: number); } /** * `RunnerDeps.memoryScopeAdmission` 的 server 实装。deployment-origin 的 requested 项一律放行(operator * 自证——v1 不做中央收窄部署声明);request-origin 项查 `directory.lookup(principal)`:granted 时逐项核 * 对是否在授权集里(任何一项缺席 = 整体终局拒绝,不做部分放行——reason 只点名调用方自己请求过的 scope * 串,不逐 scope 展开「为什么」,避免变成成员探针);unavailable 时 throw 一个带 `retryAfterMs` 的 * {@link OrgMemoryAdmissionRetryError}。write 面独立收窄:deployment-origin 恒授,request-origin 仅当目录 * 条目 `write === true` 才授,否则收窄为 null(即使读侧整体放行)。 */ export declare function createMemoryScopeAdmission(directory: OrgMemoryDirectory, opts: MemoryScopeAdmissionOptions): MemoryScopeAdmission; export {}; //# sourceMappingURL=org-memory-admission.d.ts.map