forked from ChaiHao/BPOS-MVP
minute(纪要):工作台五要素里唯一的主动动作。 纪要本身不产生责任,唯一通往责任的路是决议经登记触发起单 —— 登记人即来源。 正文可续、决议只增;同一决议不重复起单(起单一刻已有一条带来源的流在跑)。 report(汇报):日/周/月/年对任务日志的聚合投影,零手工汇报。 未提交的草案每次取回都重算 —— 汇报是投影不是账本,提交那刻才固定为事实快照。 度量八指标落在这里(§4 注:度量是只读投影,不设独立模块): 自主率 / 纠正率 / 有效自主率 / 打扰率 / 断点率 / DMN 覆盖率 / 单位成本 / 终态分布。 口径全部挂归侧标签与事件流,零埋点;单位成本的分母只认放行通过。 周窗口以周一为首日,按 UTC 切分(单组织单时区)。 FactSource 只读 memory 与 task,一行都不另记 —— 五要素同源。 gates: tsc / eslint / depcruise(305 模块)/ api-report / 377 测试 全绿 日报已在真实系统上由 A1 任务日志聚合出来,含治理干预两行 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
55 lines
2.0 KiB
TypeScript
55 lines
2.0 KiB
TypeScript
/**
|
|
* Hono 应用 —— 自建应用,Mastra 以库形态嵌入(ADR-001)。
|
|
* 鉴权、岗位权限、SSE 全归 app 层;不暴露 Mastra 默认端点。
|
|
*/
|
|
import { Hono } from 'hono';
|
|
import type { ApiError } from '@contracts';
|
|
import { DEFAULT_LOGIN_ACCOUNT } from '@modules/org';
|
|
import type { Container } from './container.ts';
|
|
import type { AppEnv } from './http-env.ts';
|
|
import { registerDeskRoutes } from './routes/desk.ts';
|
|
import { registerDeskElementRoutes } from './routes/desk-elements.ts';
|
|
import { registerGovernanceOpsRoutes } from './routes/governance-ops.ts';
|
|
import { registerGovernanceRoutes } from './routes/governance.ts';
|
|
import { registerIngestRoutes } from './routes/ingest.ts';
|
|
import { registerStreamRoute } from './routes/stream.ts';
|
|
import { registerWorkbenchRoutes } from './routes/workbench.ts';
|
|
|
|
export type { AppEnv };
|
|
|
|
export function createServer(container: Container): Hono<AppEnv> {
|
|
const app = new Hono<AppEnv>();
|
|
|
|
// 单组织 cookie session(编码规范 §4 鉴权定调)—— MVP 单登录者,cookie 缺省即种子登录者
|
|
app.use('*', async (c, next) => {
|
|
const cookie = c.req.header('cookie') ?? '';
|
|
const match = /(?:^|;\s*)jcai_account=([^;]+)/.exec(cookie);
|
|
c.set('account', match?.[1] ?? DEFAULT_LOGIN_ACCOUNT);
|
|
await next();
|
|
});
|
|
|
|
app.onError((error, c) => {
|
|
const body: ApiError = {
|
|
code: 'internal',
|
|
message: error instanceof Error ? error.message : String(error),
|
|
};
|
|
process.stderr.write(`[api] ${body.message}\n`);
|
|
return c.json(body, 500);
|
|
});
|
|
|
|
app.notFound((c) => {
|
|
const body: ApiError = { code: 'not-found', message: `无此路由:${c.req.path}` };
|
|
return c.json(body, 404);
|
|
});
|
|
|
|
registerWorkbenchRoutes(app, container);
|
|
registerGovernanceRoutes(app, container);
|
|
registerDeskRoutes(app, container);
|
|
registerDeskElementRoutes(app, container);
|
|
registerGovernanceOpsRoutes(app, container);
|
|
registerIngestRoutes(app, container);
|
|
registerStreamRoute(app, container.broadcaster);
|
|
|
|
return app;
|
|
}
|