This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-TMP-REPO/apps/api/src/modules/org/CONTRACT.md
T

3.6 KiB

module: org

职责: 员工与岗位(ADR-012):验签后的人是谁(名册即时更新)、他能进哪几个端(角色→端)、 岗位指派与在岗人员查询(负责人四策略解析的候选集来源)、名册同步(Admin API)、 在途工作(只读)、工作组(ADR-011)、种子(岗位 + 缺省角色→端) 不负责: 验签之外的 HTTP 语义(401/403 由 app 层中间件按路由归属判)、 负责人解析算法本身(见 process)、任务与卡的在途判定(经 InFlightWorkProbe 由 app 注入)

公开出口: index.ts

  • 类型:OrgService StaffWithPosition Identity 与 @contracts 的 Staff / Position / Principal / RoleAccess / RosterSyncOutcome / InFlightWork / Surface / WorkGroup / WorkGroupBinding 转出
  • 错误:TokenRejectedError(→401)AccountDisabledError(→403)AccessLockoutError(→409) StaffNotFoundError PositionNotFoundError
  • 端口类型:TokenVerifier VerifiedClaims RosterSource RosterUser IdentityPatch PositionRepository StaffRepository StaffRecord RoleAccessRepository WorkGroupRepository InFlightWorkProbe Clock IdGenerator
  • 用例工厂:createOrgService(deps: OrgServiceDeps): OrgService
  • 纯函数:identityOf isNoiseRole normalizeRoles endsOf assertNotLockedOut normalizeEnds buildInFlightWork
  • 常量:POSITION_SEED NONE_POSITION_CODE TEST_POSITION_CODE DEFAULT_ROLE_ACCESS
  • adapter 工厂(供 app 装配):createKeycloakTokenVerifier(jose,配置型 KeycloakVerifierOptions) createKeycloakRoster(Admin API,配置型 KeycloakRosterOptions) createPositionRepository createStaffRepository createRoleAccessRepository createWorkGroupRepository
  • 错误译文(供 app 拼 401 message):explainJoseError(jose 错误 → 人话,手册 4.4)
  • Drizzle 表:positionTable staffTable roleAccessTable workGroupTable

层级: L1(编码规范 §4) 依赖: @contracts;@shared/db(Drizzle 句柄与 sys schema);jose(仅 adapter) port:InFlightWorkProbe(app 注入 task / human-tool 的只读用例)、IdGenerator、 TokenVerifier(app 给 jose 远程 JWKS;测试给本地密钥对)、RosterSource(可缺省) 被依赖: process(负责人解析的候选集)、message(治理台收件人 = staffWithEnd('ops'))、 app(鉴权中间件与 /api/gov/staff、/api/gov/access 路由组装)

不变量:

  • Staff.id 就是 Keycloak sub;account 只作显示,永不当键
  • state 只由名册同步置 disabled;authenticate / principalOf 对 disabled 一律抛 AccountDisabledError, 有效 token 不能把它翻回 active(撤权在同步之后即时生效)
  • 名册即时更新只写变了的列;last_seen_at 60 秒内不重写
  • 角色→端:setRoleAccess / deleteRoleAccess 先算新表再验锁死不变量(名册为空不算锁死)
  • staffOfPosition 只回 active;哨兵岗 NONE 恒回 []
  • ensureSeeded 幂等:岗位按 code 判存在;缺省角色→端只在表空时播;测试账号策略只补不覆盖
  • 工作组是绑定不是策略(ADR-011):bindingOf 只出成员表快照,在岗与否由调用方核

影响半径(2026-08-25,ADR-012):contract / port / index 全面重写 —— 退役 login logout resolveSession setPassword authorize loadSession listGrants setGrants createStaff checkDisable disableStaff findByAccount 与 SessionRepository PasswordHasher GrantRepository; 下游 app(中间件 / 装配 / 路由)与 message 装配同批改,depcruise 已反查确认。