白
26523d1b54
feat(filelib): 操作日志模块——防篡改哈希链、组合查询与 CSV 导出
...
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com >
2026-08-06 22:54:45 +08:00
白
c96ea60482
docs(adr): member-group ADR 改号 0028→0038,避免与 agent-config-folder-tree 撞号
2026-08-06 00:58:51 +08:00
白
ecc92c9a87
docs(adr): cph 的 nested-manifest / batch-export 改号 0036/0037
...
上游 0029/0030 与本地 filelib 侧同号 ADR 相撞,cph 两份改到本地空闲号段,
代码锚点引用一并跟随。
2026-08-06 00:51:33 +08:00
白
e878b46701
Merge remote-tracking branch 'educraft/main' into merge/educraft-cph
...
# Conflicts:
# .gitignore
# hub/.env.example
# hub/deploy/deploy_fleet_release.sh
# hub/deploy/deploy_platform.sh
# hub/test/integration/helpers.ts
2026-08-06 00:49:02 +08:00
hongjr03
e0bd6120ec
docs(adr): nested outline manifest and batch/combined export design
...
ADR-0029 supersedes ADR-0008's flat [[parts]] with a per-folder
manifest.toml outline tree (root = implicit top container, single
section container kind, DFS pre-order = lesson order).
ADR-0030 extends ADR-0009/0011: cph build batches all targets (any
failure => non-zero), cph bundle assembles ordered lessons into one
SingleFile/FileTree artifact (self-contained lessons, export-time
combination only).
2026-08-05 18:34:05 +08:00
白
dc271ff9f3
Merge branch 'maoyuanyang-main'
...
# Conflicts:
# hub/filelib-web/src/lib/GrantsPanel.svelte
# hub/filelib-web/src/lib/OverviewPanel.svelte
# hub/filelib-web/src/lib/types.ts
# hub/src/database/filelib/grantService.ts
2026-08-03 15:35:44 +08:00
ymy
d9cde19bdf
fix(filelib): 恢复保留原名,撞名报清晰错误而非自动加后缀(ADR-0035,supersede ADR-0033)
...
恢复不再改名;同名兄弟占位时抛 409 name_conflict_on_restore + 人话提示,
操作者自行重命名现有节点或彻底删除旧节点后再恢复。
2026-07-31 14:28:34 +08:00
ymy
beaa92de2e
feat(filelib): 彻底删除改与条目可见性同权(ADR-0034,supersede ADR-0031 仅管理员条款)
...
能删进回收站(MANAGE)的人就能清空;无关者 404(D8)。二次确认与
node.purge 审计不变;BinView 彻底删除按钮对全部可见条目开放。
2026-07-31 14:01:46 +08:00
ymy
9e38d1e011
fix(filelib): 恢复撞名不再死锁,自动改名「(已恢复)」(ADR-0033)
...
- restore 前查活跃兄弟:撞名则恢复为「原名(已恢复[/ N])」(截断计入
128 长度预算),同事务落审计并记 renamedFrom;API 返回最终名
- BinView toast 提示改名;测试补撞名/二次恢复用例
2026-07-31 13:52:23 +08:00
ymy
83a6b012b7
feat(filelib): 移除最近打开模块(ADR-0032,supersede ADR-0031 对应半部)
...
- FileLibRecentVisit 删表(手写迁移;表当日新建无生产数据)
- recentService/recentRoutes/RecentView 删除;GridLibraryView 埋点与
navTarget 跳转一并移除;types 清 RecentEntry
- 左栏保留 文件库/回收站(ADR-0031 回收站半部不受影响)
- breadcrumb 的 role 字段保留(独立可用的增量字段)
2026-07-31 13:39:18 +08:00
ymy
d072e9ec1e
feat(filelib): 老师端左栏导航:回收站 + 最近打开(ADR-0031)
...
- 回收站:listBin(祖先全活跃的已删顶点;管理员/直连 MANAGE 可见)、
restore(与 D15 对称只清本节点,落审计)、purge(仅管理员,pathIds 枚举
子树按深度降序分批硬删,绕过 self-FK RESTRICT)
- 最近打开:FileLibRecentVisit 表(filePath='' 兜底 PG 唯一索引),客户端
成功打开后上报(VIEW 门禁,upsert 刷新),列表 20 条,D8/D15 可见性过滤
- 前端:/app 左栏(文件库/最近打开/回收站);RecentView/BinView;
GridLibraryView 埋点 + navTarget 跳转(breadcrumb 建栈,role 已捎带)
- 测试:filelib-nav 集成 4 例;全套 79 例绿
2026-07-31 13:27:04 +08:00
ymy
39a2be6347
feat(filelib): 项目级授权恒生效,移除独立权限开关(ADR-0030)
...
- permission.ts: effectiveRole 删除 D11 冻结分支,输入不再含开关字段
- treeService: 停止读 FileLibProjectSettings;建项目不再写默认行
- grantService/routes: 删 setIndependentPermission 与 PUT 路由;节点详情 DTO 去掉 independentPermission
- filelib-web: 概览 tab 移除开关;NodeDetail 类型同步
- 测试: 单测/集成改为断言恒生效语义;ADR-0030 废除契约 D11/P5
- FileLibProjectSettings 表保留(存量行忽略,不再读写),审计词表保留历史读取
2026-07-30 22:27:45 +08:00
ChickenPige0n
c9adf83e5c
feat(hub): org-scoped agent role/skill folder tree (ADR-0028)
...
Add a shared transparent OrganizationAgentConfigFolder tree for grouping
agent roles and skills in the admin UI without affecting identity, bindings,
run loading, or slash commands.
2026-07-30 11:36:27 +08:00
白
82241afb56
feat(filelib)!: VersionStore 改为真 git,一项目一仓库
...
内存 store 换成 gitVersionStore:init 建目录并 git init,VersionId 是
commit hash,某文件的版本取 `git log -1 -- <path>`(D16 文件级版本不因
别的文件提交而失效)。删除也是一个 commit,旧版本仍可读。决策见 ADR-0030。
git 用 execFile 调系统二进制,不引依赖。每次调用钉死 --git-dir/--work-tree
并禁 hooks、隔离全局 gitconfig:项目仓库是老师上传的数据,而 storage root
默认就在本 repo 内,不钉死会让命令落到外层仓库上。
同时:
- 单文件上限改为 HUB_FILELIB_MAX_FILE_BYTES(缺省 10MiB),前端从
/database/config 读,不再两处硬编码
- commit 身份 name=displayName、email=<userId>@filelib.paradigm-edu.net;
message 缺省为「【用户名】修改了【路径】」,调用方显式传则优先
- 上传改走弹窗,路径与 commit 信息可手填(原先 prompt 只能填路径)
BREAKING CHANGE: VersionId 由计数器(v1/v2)变为 commit hash;
CommitRequest.author 由字符串变为 { userId, displayName? }。
旧 .version-store.json 不迁移,此前建的项目报 repo_not_found。
2026-07-27 15:55:01 +08:00
白
683e97ca53
docs(adr): 0029 web 界面一律静态 SPA,hub 只出 JSON
...
记录本次迁移的语义决策:没有 HTTP handler 渲染 HTML;/app 与
/database 是同一个前端工程 filelib-web,构建一次挂两个前缀;
客户端导航用真 URL 路由而非 hash 片段。
两条承重配置约束一并写明:appDir 必须改名(默认 _app 与 admin-web
在根上的 /_app/* 撞重复路由,Fastify 启动即失败),以及
paths.relative=false(同一份 index.html 在不同 URL 深度被送出)。
2026-07-26 20:17:09 +08:00
白
11a7ec8004
feat(database): 后台成员组(MemberGroup)管理与嵌套解析
2026-07-26 18:06:18 +08:00
hongjr03
e21096c642
feat(hub): embed agent images via Feishu upload + release v0.0.36
...
Materialize markdown image refs on agent finish: fetch/read bytes, upload
im.v1.image, and render native card img elements so remote image URLs no
longer trip Feishu content-security. Stream masks image URLs mid-run;
card failure falls back to plain text plus standalone image messages.
Docs: clarify im:resource covers outbound Agent image send.
2026-07-20 10:40:03 +00:00
hongjr03
b673dd1fe9
feat(hub): external capability registry for PDF/ASR transforms (ADR-0027) ( #5 )
...
Co-authored-by: Hong Jiarong <me@jrhim.com >
Co-committed-by: Hong Jiarong <me@jrhim.com >
2026-07-18 15:55:02 +08:00
hongjr03
aaa098bb8b
feat(hub): usage fact ledger for run-scoped cost attribution (ADR-0026) ( #4 )
...
Co-authored-by: Hong Jiarong <me@jrhim.com >
Co-committed-by: Hong Jiarong <me@jrhim.com >
2026-07-18 14:46:41 +08:00
hongjr03
79f72ecca8
feat(admin): web-based skill management with file editor
...
Add full skill lifecycle to the org-admin web surface: create, read,
edit, disable. Skills are directories (SKILL.md manifest + supporting
files), content-addressed by SHA-256 in an immutable store.
Backend:
- skillStore: extract commitSkillContent (shared populate→inspect→
dedup→atomic rename); add importSkillFromFiles (in-memory file list
ingestion) and readSkillFiles (read stored version back as UTF-8)
- configuration: add installSkillFromFiles, readSkillFiles, disableSkill
(soft-delete + archive bound role sessions), updateSkillDescription
(label-only, no archival); refactor installSkill to share
commitInstalledSkill
- agentConfigRoutes: wire skillStoreRoot; add GET
/agent-skills/:name/files, PUT /agent-skills/:name (create/replace),
PATCH /agent-skills/:name (description/disable)
- orgRoutes: pass readSkillStoreRoot() to agent config routes
Frontend:
- api.ts: agentSkillFiles, installAgentSkill, patchAgentSkill methods
- SkillEditor.svelte: file tree + text editor + version/description form
- skills/+page.svelte: skill list, create form (generates SKILL.md
template), per-skill editor
- layout: add 技能 nav item
ADR-0018: update Decision to reflect web surface joining host-console
CLI in the shared content-addressed ingestion pipeline.
Spec (AgentRole.lean): unchanged — storage mechanism is OPEN, web
installation is one implementation of it.
2026-07-16 01:11:49 +08:00
hongjr03
69837bd50c
feat: redesign Feishu project console
2026-07-13 16:52:45 +08:00
hongjr03
82f57317df
feat: archive bindings on Feishu lifecycle events
2026-07-13 15:53:28 +08:00
hongjr03
6ed56ddfc8
feat: auto-join scoped Feishu OAuth users
2026-07-11 14:00:43 +08:00
hongjr03
3bf643ff4d
fix: guide Feishu users through onboarding
2026-07-11 13:52:19 +08:00
hongjr03
d36b00bbec
feat: make agent roles and skills dynamic
2026-07-11 12:55:05 +08:00
hongjr03
17c0536958
fix: enable only curated agent skills
2026-07-11 12:25:52 +08:00
hongjr03
96e120e02c
feat: add curated curriculum agent skills
2026-07-11 12:22:01 +08:00
hongjr03
9d494f446f
docs: clarify Feishu user profile permissions
2026-07-11 02:42:09 +08:00
hongjr03
7fcb57013e
fix: restore bounded agent sandbox execution
2026-07-11 02:34:56 +08:00
hongjr03
035c264179
fix: keep agent sandbox sockets on short paths
2026-07-11 02:22:19 +08:00
hongjr03
38d9a9c6cb
fix: bootstrap fresh alpha silo
2026-07-11 01:40:20 +08:00
hongjr03
9e954790dc
feat: add deployable alpha silo
2026-07-11 00:25:45 +08:00
hongjr03
848f913597
feat: secure organization provider credentials
2026-07-10 22:04:43 +08:00
hongjr03
f07f280b8f
fix: prove Linux Agent sandbox boundary
2026-07-10 17:59:56 +08:00
hongjr03
f4968d6657
fix: confine Agent and MCP data access
2026-07-10 16:38:08 +08:00
hongjr03
420c1c40bc
docs: define platform admin identity boundary
2026-07-10 13:36:35 +08:00
hongjr03
4ca4afb141
docs: define SaaS capacity controls
2026-07-10 12:07:08 +08:00
hongjr03
34e07e229f
feat: add org admin project onboarding foundation
2026-07-10 00:25:00 +08:00
hongjr03
2b7aa3294f
feat: add organization tenant model
2026-07-09 23:37:20 +08:00
hongjr03
346aee5a68
fix: bind agent sessions to role
2026-07-09 16:06:06 +08:00
hongjr03
dfcc2d70f8
feat(hub): 支持教师团队权限
2026-07-08 15:42:53 +08:00
hongjr03
ecbc2c8666
fix(hub): 对齐 ADR-0018 agent 执行面边界
...
runner.ts: 启用 SDK 内置沙箱(bubblewrap/seatbelt),写入限制在 workspace,
denyRead 敏感路径,failIfUnavailable 硬拒非沙箱运行。bypassPermissions 保留
(headless 无交互),沙箱是硬边界而非权限提示层。
install_service.sh: 默认 service user 从 root 改为 cph-hub;env 模板修正
OPENROUTER_API_KEY → ANTHROPIC_AUTH_TOKEN/ANTHROPIC_BASE_URL/ANTHROPIC_API_KEY
(与 server.ts 实际读取一致);补 __BASE_DIR__ sed 替换。
cph-hub.service: AssertPathExists=/usr/bin/bwrap 强制沙箱依赖;NoNewPrivileges。
不加 ProtectSystem/ProtectHome(会破坏 cph render-cache 与 bwrap user-namespace)。
trigger.ts: 权限闸门去掉 if (senderOpenId !== '') 短路——缺 open_id 一律
fail-closed 拒绝,不再静默跳过;role gate 同步去掉冗余守卫(已由上游保证)。
顺手把 JSON.parse(msg.content) 的 inline cast 换成 Zod schema parse
(FileMessageContentSchema / TextMessageContentSchema)。
ADR-0018: 状态改为 Accepted+implemented,机制段写定 SDK 沙箱,网络决定为开放,
Open Questions 更新。
2026-07-08 13:11:14 +08:00
hongjr03
5b7fd70124
spec: 钉死 agent 执行面边界(ADR-0018)
...
ADR-0001/0002/0004 覆盖协作治理到 triggerAgent,但触发后 agent 在执行层
能干什么——读哪些文件、跑什么命令——无 ADR / spec 覆盖。ADR-0017 落地时
采用 bypassPermissions + 全量内置工具,agent 文件/shell 面对宿主无界;
workspace.ts 的 confine() 沙箱意图存在但被 ADR-0017 静默覆盖成死代码。
新增 ADR-0018 + Spec.System.AgentSurface 模块补这一层:
- AgentFileOp(run × path)+ Authorized 谓词(路径必须落在 run 工作区内)
- 与 Lock 正交:Lock 限定并发,Surface 限定波及面,都按 run × project 作用域
- 机制 OPEN(工具包装 / OS 沙箱 / SDK 钩子),契约只钉不变式
- ADR-0017 的 bypassPermissions + workspace.ts 死代码标为偏离契约,对齐为 follow-up
2026-07-08 12:37:37 +08:00
hongjr03
c73b41e1da
fix(hub): resume Claude SDK sessions
2026-07-08 11:48:20 +08:00
hongjr03
b9f50407be
fix(hub): Claude Code SDK 经 OpenRouter Anthropic Skin,保留 provider-agnostic
...
我之前判断错了——OpenRouter 有 Anthropic Messages API 兼容端点
(https://openrouter.ai/api ),Claude Code SDK 直连不需要代理。
ANTHROPIC_AUTH_TOKEN=OpenRouter key,ANTHROPIC_API_KEY='' 即可。
而且 ANTHROPIC_DEFAULT_SONNET_MODEL 可设 OpenRouter model ID
(z-ai/glm-4.7 等),所以 provider-agnostic 没丢。
ADR-0017 重写:从'Anthropic 专有'改为'Claude Code SDK via OpenRouter,
保留 provider-agnostic'。tsc rc=0。
2026-07-08 01:46:09 +08:00
hongjr03
082562ca08
docs(adr): ADR-0017 重写——从 provider-agnostic 改为 Claude Code SDK
...
放弃 provider-agnostic,用 @anthropic-ai/claude-agent-sdk。代价:不能走
OpenRouter(GLM 等),需 Anthropic API key。收益:compaction、工具审批、
partial message 流式、Claude-to-IM 原生兼容。迁移路径:如果将来需要
provider-agnostic,用 streamText + SSE 转换层(~100 行)替回 query()。
2026-07-08 01:40:28 +08:00
hongjr03
f8c3e16a52
feat(hub): 事件去重(A-4) + 审计写入路径(A-8)
...
A-4 FeishuEventReceipt:
- 新增 FeishuEventReceipt 表(eventId @unique),lark ws 至少一次投递的幂等兜底
- MessageReceiveEvent 加 header.event_id 字段
- trigger 入口查重:已存在的 event_id → 跳过(不建第二次 run)
- resetDb 加入 FeishuEventReceipt
A-8 审计写入:
- AuditEntry 加 projectId(权限拒绝/slash 命令等无 run 的审计点可定位)
- 新建 src/audit.ts:writeAudit(prisma, entry) best-effort 写入(吞错,不阻断 trigger)
- trigger 五个审计点:trigger.denied / trigger.role_denied / run.created / run.lock_race / run.finished / run.failed
- 新增 audit unit 测试(3) + trigger 集成测试(去重 + 审计,2)
59 tests 全过。
2026-07-07 21:34:15 +08:00
hongjr03
18aac1ff16
feat(spec): System 层补 ADR-0001/0003/0004 缺口 + ADR-0017 provider-bound session
...
ADR-0001/0003/0004 已 PINNED 但 spec/System 未落,补三模块:
- ProjectGroup: project↔飞书群 1:1 绑定 + 单射良构(ADR-0001);群失效态 OPEN
- Memory: 锚点类别 + MCP 读上下文按 run/project 授权不变式(ADR-0003)
- PermissionGrant: grant(resource×principal×role)+settings 六旋钮(ADR-0004);
role-capability×settings-policy 组合规则 OPEN
- Prelude: 新增 ChatId 载体
- ADR-0017: AgentSession provider/model 绑定,切 model 即新 session,
跨 session 连续性由 ADR-0003 记忆/锚点重建;agent 层 provider 无关,
@Claude 仅为触发品牌。RunId/SessionId doc 去 provider 暗示。
lake build 28/28 绿。
2026-07-06 22:30:05 +08:00
sjfhsjfh
ebcb3a7589
feat(model+spec): .cph-version 契约文件 + CphVersionMismatch 诊断(ADR-0016);bump 0.0.2
...
教研工程文件根放 .cph-version(内容=面向的 cph 版本)。cph 加载时比对自身版本
(CARGO_PKG_VERSION),不相容报 CphVersionMismatch error 并拒绝。当前判定为版本完全
相等(MVP);判定逻辑孤立在 versions_compatible 单谓词,后续可放宽为 semver 区间而
不动诊断分类/spec/CLI。
spec(7 类诊断,原 6 类):
- Diagnostic.lean: DiagKind 增 cphVersionMismatch(error 级),分类注释 6→7
- Pipeline.lean: load 阶段含 .cph-version 兼容性判定
- Courseware.lean: ADR 区间 →0016
实现:
- cph-diag: DiagCode::CphVersionMismatch("E-CPH-VERSION")
- cph-model: load() 解析 manifest 成功后 check_cph_version;versions_compatible
谓词(完全相等);CPH_VERSION const。missing .cph-version 暂跳过(迁移期 OPEN);
空文件报 error
- examples/TH-141、valid/mini fixture、KenKen 课各加 .cph-version=0.0.2
测试:cph-model 4 个版本门测试;全 workspace 53 passed;lake 25 jobs 绿。
负向验证:9.9.9 .cph-version → E-CPH-VERSION error + check 拒绝(exit 1)。
bump: workspace.package 0.0.1→0.0.2;cph --version 报 cph 0.0.2;README 同步
(含版本契约说明)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-23 16:03:54 +08:00
sjfhsjfh
144e2d8c80
feat(spec+checker): slides/逐字稿 markdown 内容面 + assembleMarkdown step(ADR-0015)
...
给课程加两个 markdown 内容面:slides(大纲:h2 part → h3 小节 → ![]() 图 +
:::widget 教具)与逐字稿(口播)。直接 markdown+KaTeX 撰写,绕开 typst→md
公式转换(等于在 slides 面选 ADR-0014 的 R2)。
spec:
- RichContent.lean: content leaf 带 format(typst|markdown),新增 ContentFormat
归纳,RichContentRef 加 format 字段
- Export/Render.lean: Step 加 assembleMarkdown (field),钉执行语义
(同 shell 三边界 + 注入课程 h1 + 自包含收集引用图)
- Courseware.lean: ADR 区间 →0015
实现:
- cph-schema: x-cph-content 支持 true→.typ / 字符串→该扩展名(.md);
ContentField 带 ext;4 个 kind schema 各加可选 slides/transcript
- cph-model: Step::AssembleMarkdown{field} + manifest "assemble-markdown" 解析
- cph-check: run_markdown_assemble_target / target_is_markdown_assemble
(照 run_shell_target 形状:check 门控、注入 h1、按 [[parts]] 序拼、写盘后
收集  引用图进 build 根使产物自包含、引用图缺失属 build-过程错误
不入 6 类诊断);compile_targets 已 filter TypstCompile,纯 assemble 自然排除
- cph-cli: run_markdown_assemble_build 路由
- cph-typst: template_step 补 AssembleMarkdown => None 分支
测试:全 workspace 49 passed(新增 6 个 markdown 装配测试含图收集);
lake build 25 jobs 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-23 14:55:55 +08:00