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
ymy
c72f8c7050
Merge branch 'chore/grants-panel-wider'
2026-07-27 17:00:42 +08:00
ymy
947f969967
chore(filelib-web): 详情容器加宽到 1400px,宽屏下授权表格全列无遮挡;仅文件预览挤压时出横向滚动条
2026-07-27 17:00:41 +08:00
ymy
60856d7cc1
Merge branch 'chore/grants-table-overflow'
2026-07-27 16:54:07 +08:00
ymy
2e08c0a734
chore(filelib-web): 授权表格外套横向滚动容器,修删除列贴边与文件预览打开时表格挤压
2026-07-27 16:54:07 +08:00
ymy
2225c6d43b
Merge branch 'chore/grants-table-width'
2026-07-27 16:47:05 +08:00
ymy
fc908eaf3b
chore(filelib-web): 拉宽授权表格:容器 880→1120px,单元格留白/禁换行,长 id 截断+悬停全文
2026-07-27 16:47:05 +08:00
ymy
2395671693
Merge branch 'chore/grant-id-columns'
2026-07-27 16:40:26 +08:00
ymy
cc4d9d907c
chore(filelib-web): 授权成员单元格只留头像+名称,userId 与飞书 ID 拆为独立两列
...
GrantDto 增加 principalOpenId(USER 主体的 feishuOpenId),GROUP 行两列显示 —;
搜索过滤同步覆盖 openId。
2026-07-27 16:40:25 +08:00
ymy
ef02428bb6
Merge branch 'chore/grant-avatar'
2026-07-27 16:22:03 +08:00
ymy
ad1a464f22
chore(filelib-web): 授权成员单元格改用首字母圆形头像(复用 Avatar 组件)
2026-07-27 16:22:01 +08:00
ymy
2dfe72cd5e
Merge branch 'chore/grant-modal-copy'
2026-07-27 16:16:17 +08:00
ymy
12a1246a7a
chore(filelib-web): 移除添加授权弹窗底部的 8.1 规则提示语
2026-07-27 16:16:16 +08:00
ymy
405312b36b
Merge branch 'chore/role-label-zh'
2026-07-27 15:57:42 +08:00
ymy
be17f74fc2
chore(filelib-web): 文件库权限名称汉化(VIEW/EDIT/MANAGE → 只读/可编辑/可管理)
...
统一走新增共享常量 labels.ts ROLE_LABEL(与 OverviewPanel 既有文案一致);
覆盖授权表格与弹窗下拉、详情头 tag、树节点角标;API 传参仍用英文枚举。
2026-07-27 15:57:41 +08:00
ymy
fccae5dacb
Merge branch 'feat/grants-table'
2026-07-27 15:16:30 +08:00
ymy
0dd2ae347e
feat(filelib-web): 授权面板表格化:搜索、添加弹窗、权限下拉与成员跳转
...
- GrantsPanel 重写为表格:顶部左侧授权成员搜索框(名称/id/类型过滤),
右侧「添加授权」弹窗(类型 + 主体搜索选择 + 权限);行内权限下拉
直接改级(复用 PUT upsert),操作列删除;成员单元格跳转用户管理
(?q= 过滤)或 Group 管理(?select= 选中)。
- grantService: GrantDto 增加 principalName,list/put/force 三处统一
批量回填(用户 displayName / 组 name),前端不再只显示裸 id。
- 用户管理页加过滤框并从 ?q= 初始化;GroupAdmin 支持 ?select= 直达。
- 测试:resetDb 补 MemberGroup 三表清理(全局表不被 org/user 级联清到,
此前跨用例污染导致级联软删用例断言失败);cph_hub_test 补 migrate。
- 顺带合并 types.ts 里重复的 Grant 声明(interface 合并残留)。
2026-07-27 15:13:57 +08:00
ymy
a4c07d1a5d
Merge branch 'fix/filelib-tree-loading'
2026-07-27 14:09:48 +08:00
ymy
91afd3c1b1
fix(filelib-web): 文件库树加载失败时显示错误而非永久加载中
2026-07-27 14:09:35 +08:00
白
e6e23294a2
Merge branch 'feat/member-group-hierarchy'
...
MemberGroup 全局嵌套层级(ADR-0028)与 /database 前后端分离(ADR-0029)。
2026-07-26 20:43:59 +08:00
白
8a13e455fb
chore: 删除 .omo/ 与文件库-接口契约.md
...
.omo/ 下 12 个 run-continuation/ses_*.json 是 agent 会话续跑状态,
机器生成,本不该进版本库;文件库-开工计划.md 一并删除。
《文件库-接口契约.md》(C/D 编号)同时删除。两份文档的内容都可从 git
历史取回。
代码注释里的 C/D 编号(契约 8.1、C2、C4、D11–D19 等)因此不再有在库
文档可查,分布在 filelib 的 model / grantService / treeService /
guards、prisma schema 与迁移、以及 ADR-0028。README 原先按路径引用
这两份文档,现改为说明出处与取回方式。
2026-07-26 20:32:38 +08:00
白
6990082247
build(deploy): 部署与限流配置切换到 filelib-web,并加共存回归测试
...
三处引用旧工程名/旧资源路径的地方一并更新,它们必须同时改 —— 少改一处
就是静默故障,而不是构建期报错:
1. 部署脚本(deploy_platform.sh / deploy_fleet_release.sh):npm ci 的
prefix、rsync 排除项、构建产物存在性检查从 database-admin 换成
filelib-web。最后一项是真门禁:static.ts 缺产物时只 warn 不注册路由,
漏改会让 /app 与 /database 静默 404 —— 恰是 database-admin 长期处于
禁用状态的原因。
2. silo 限流豁免:资源路径随 appDir 改名而变(/database/_app/* 已不存在,
现为 /_filelib/*);/app/* 此前不在豁免列表,它现在也是 SPA 外壳,
客户端路由无法预先枚举。
注:/database/* 是整体豁免,filelib 的 JSON API 也绕过限流预算。这是
迁移前就有的行为,原样保留,但覆盖面因多了 /app/* 而变宽。
3. 回归测试:把 registerStaticSpa 与 registerDatabaseSpa 挂到同一个
Fastify 实例,断言 ready() 不因重复路由抛错 —— appDir 若用回默认的
_app,这里会红(ADR-0029 的承重约束)。另断言 /app 与
/database/dashboard/users 返回同一份字节(SPA 回退不读请求)、body 含
/_filelib/。构建产物缺失时不 skip 而是直接失败:那说明该先跑
filelib-web 的 build,不是测试不适用。
2026-07-26 20:23:15 +08:00
白
cdeb29ccf2
fix(database): 补回文件库的「授权」tab 与 /me 的显示名
...
迁移时整个授权 tab 连同四个端点一起漏掉了 —— 后端一直可用,前端零调用:
GET/PUT/DELETE /nodes/:id/grants
PUT /projects/:id/independent-permission
权限编辑是这个后台的核心用途,而它此前在界面上完全不可达。
tab 组装也修正为与旧 libraryBrowser 一致:概览恒有、文件仅 PROJECT、
授权仅 MANAGE。注意文件夹也有授权 tab —— 它虽是透明组织节点,授权仍
挂在节点上(ADR-0021);此前文件夹一个 tab 都没有。
GrantsPanel 的语义按契约 8.1:创建者授权不给收回入口;MANAGE 仅创建者
可授,前端不拦,后端 fail closed 的报错原样呈现;GROUP 主体走
/groups/search 下拉选,不手敲 id。
/database/api/me 加 displayName 与 avatarUrl:侧栏此前显示原始 userId。
旧页面是服务端渲染,handler 里查 Prisma 就有名字;页面不再服务端渲染后
(ADR-0029),模板闭包过的数据也是被迁移的契约的一部分,不是旧实现的
无关细节。
概览面板同时补回丢失的「类型」「更新时间」两行、导出 target 下拉、
节点标题旁的角色 tag,以及整块缺失的独立权限开关。
2026-07-26 20:19:47 +08:00
白
eeb8f56742
fix(filelib-web): 补齐 Group 管理面板,与旧后端面板逐条对齐
...
迁移时误把分支上一个早先存在的简易 GroupAdmin(281 行)当成迁移产物,
它与旧 renderGroupsPanel(747 行)从来不是同一个东西,于是后端 8 个
group 端点前端只调了 5 个。
补上的功能(端点一直可用,只是没有入口):
PATCH /groups/:id 重命名 / 改描述
GET /groups?includeArchived=1 列出已归档组
POST /groups/:id/restore 恢复(连带恢复已归档祖先链,子树仍归档)
GET /users/search 成员选择器,不再手敲 userId
影响最实际的是恢复:软删的组此前在界面上无法恢复。
补上的交互:折叠树、组名过滤(命中项保留整条祖先链,过滤态强制展开)、
右键菜单(归档组只给「恢复」)、面包屑、统计条、树底部计数、成员表的
头像/openId/加入时间三列。
types.ts 之前也是截断的:MemberGroupNode 少 archivedAt,
MemberGroupMember 少 feishuOpenId/avatarUrl/joinedAt —— 类型里没有,
UI 自然渲染不出来。
一处实现偏离:折叠状态用数组而非 Set。Svelte 5 的 $state 深层代理不
跟踪 Set 变更,用 Set 会点了没反应。
groups tab 外框补 padding:20px/overflow:hidden,对齐旧 #tab-groups,
否则面板贴着侧边栏。
2026-07-26 20:19:30 +08:00
白
325b4fc137
fix(filelib-web): 补回迁移丢失的共享组件样式层与图标集
...
第一版迁移只把 uiTheme.ts 的 @theme 颜色令牌搬了过来,155 行里约 90
行的组件类(.btn/.panel/.input/.select/table.list/.tag/.switch/
.link-danger/.quiet 等)被丢掉,于是每个组件各自内联重述按钮、输入框、
面板的样式 —— 正是旧代码的重复问题被原样复刻,后台观感明显退化。
现在 app.css 是设计系统的唯一去处:@theme 管令牌,@layer components
管组件类。组件只带布局工具类,不重述组件样式。
图标集同样是丢的:旧面板有 13 个内联 SVG,新版一个不剩,只有纯文字的
「+」「删除」—— 这是"简陋"最直接的来源。提成 Icon.svelte 共享。
Group 节点沿用两人剪影而非文件夹图标:MemberGroup 与文件库的
FOLDER/PROJECT 是两套无关层级,图标不应混淆(ADR-0028/0021)。
顺手修 FilesPanel 的 uploadInput:bind:this 的目标要用 $state,
否则 Svelte 5 下不保证更新。
2026-07-26 20:19:10 +08:00
白
a7f90f387d
chore(database-admin): 删除该前端工程,已被 filelib-web 取代
...
12628c9 引入它意在替换后端渲染的 /database 页面,但从未接通:具体
路由 /database/dashboard 比 SPA 通配 /database/* 更具体,服务端
handler 永远胜出,SPA 的 dashboard 不可达。工程头注释声称 SPA 已
接管 dashboard、且 /database/config 存在,两者当时都不成立。
hub 的 build 脚本也从未构建它,于是 static.ts 里的 existsSync 守卫
每次部署都失败,这个外壳实际长期处于禁用状态 —— 它没服务过一个请求。
与 filelib-web 合并而非并存的理由:两者共用文件库浏览器、会话层、
toast 宿主与设计令牌,拆开就要把这些全复制一遍(ADR-0029)。
内容可从 git 历史取回。
2026-07-26 20:18:15 +08:00
白
d159e372d2
refactor(database)!: 后端不再渲染任何 HTML,只出 JSON
...
删掉约 1770 行服务端模板拼接:renderDashboard / renderLoginPage
(databaseRoutes)、adminPanels、libraryBrowser、uiTheme,以及
libraryPage —— 后者迁移前已是无人引用的死代码。
新增两个端点承接原先在 page handler 里 inline 算的东西:
GET /database/config 免鉴权 bootstrap(org slug + dev 开关);
注册位置刻意早于 silo org 的提前返回,
org 未就绪时登录页仍要能渲染。
GET /database/api/stats 概览统计,要求 silo org OWNER/ADMIN ——
它聚合的是 org 级计数与审计流,不是
单节点权限视图。
静态托管收敛到 static.ts:一份 filelib-web 构建产物挂 /app 与
/database 两个前缀,资源路由只注册一次。并发症是路由顺序成了硬约束
—— 具体页面路由必须先于 SPA 通配注册,否则重演 /database/dashboard
盖住 SPA 的老 bug(ADR-0029)。
/database/library 改为 302 到 /database/dashboard/library。
BREAKING: 部署需先构建 filelib-web,否则 static.ts 的 existsSync
守卫会让 /app 与 /database 全部 404。
2026-07-26 20:17:59 +08:00
白
3d0f4e5c2d
feat(filelib-web): 把 /database 各页从后端 HTML 拼接迁到 SvelteKit 路由
...
登录页、后台外壳与六个 tab 全部成为客户端路由:
/database/admin 登录(迁自 renderLoginPage)
/database/dashboard 概览(迁自 renderDashboard)
.../library .../users .../groups .../search .../settings
六个 tab 是真 URL,不再是 location.hash + display:none —— 刷新不丢
位置,链接可分享。
BrowserShell 拆成 LibraryView,加 showUserFooter:老师端 /app 显示
身份/登出页脚,后台的文件库 tab 不显示(外层已有身份区)。
bootstrap 走 /database/config 而非 /database/api/login-info:后者由
teacherApp 在 silo org 查找成功后才注册,前者无条件注册,登录页在
org 未就绪时也必须能拿到配置。
后端拥有的链接(OAuth、DEV 一键登录)标 data-sveltekit-reload,
否则被客户端路由拦下。
2026-07-26 20:17:43 +08:00
白
de9f846fd0
build(filelib-web): 从 Svelte+Vite 改为 SvelteKit(adapter-static)
...
纯 SPA:adapter-static + fallback index.html,不做 SSR/预渲染。
index.html / main.ts / App.svelte 由 app.html + src/routes/ 取代。
两项配置是承重的(ADR-0029),不是风格选择:
appDir: '_filelib' 默认 _app 会与 admin-web 在根上注册的 /_app/*
撞成 Fastify 重复路由,启动即抛错。
paths.relative: false 同一份 index.html 会在 /app 和
/database/dashboard/users 等不同深度送出,
相对资源路径会解析到错的 base。
dev 代理表列出后端拥有的全部路径:JSON API、免鉴权 bootstrap
(/database/config)、OAuth、以及 DEV 一键登录端点 —— 后者不代理会被
SPA 回退吃掉。
2026-07-26 20:17:27 +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
白
2f2ece1a3a
fix(database): expose submitCreate on window.__lib in library browser
...
新建根目录/子节点弹窗的「创建」按钮 onclick 调 window.__lib.submitCreate,
但该函数虽已定义却漏挂到 __lib 导出表,导致点击报 "submitCreate is not
a function"。补挂即可。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-26 16:39:38 +08:00
白
58c81d4379
Merge remote-tracking branch 'origin/main' into feat/member-group-hierarchy
2026-07-24 00:00:50 +08:00
bai
d16bd4899d
Merge pull request 'feat(database): init database folder frontend and permission' ( #1 ) from maoyuanyang/curriculum-project-hub:main into main
...
Reviewed-on: #1
2026-07-23 23:44:17 +08:00
ymy
4021e58d5d
feat(database): init database folder frontend and permission
2026-07-23 23:41:11 +08:00
白
192cd43245
feat(hub): add global nestable member group hierarchy
...
Global, unlimited-depth member groups managed by the platform super
admin (requirement 3.1-3.3). Stores membership + nesting only, never
permission data; exposes user -> ancestor-closed group set.
- MemberGroup: soft delete via archivedAt; parentId FK RESTRICT.
Deleting a group cascade-soft-deletes its whole subtree as an
application operation, not a DB cascade.
- MemberGroupMembership: user<->group many-to-many, revokedAt soft
delete, user/group indexed for resolution hot path.
- MemberGroupClosure: transitive closure (depth-0 self rows) for
one-join ancestor/descendant resolution; maintained on
create/reparent with a cycle guard.
Permission side (GROUP principal, FOLDER resource, grant inheritance)
is deferred. This principal is deliberately not org-scoped and will
need ADR-0028 to supersede the ADR-0020 cross-org invariant before the
GROUP principal ships.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-23 22:31:26 +08:00
白
12628c9233
feat(hub): migrate database admin pages to SPA (database-admin)
...
- scaffold hub/database-admin as SvelteKit 2 + Svelte 5 static SPA
with aurora/glass visual style (paths.base='/database')
- add lib/{api,session,org}.ts + Aurora.svelte component
- add routes: root redirect, /admin login page, /dashboard (OWNER/ADMIN only)
- backend: replace server-rendered HTML routes with /database/config JSON endpoint
- add hub/src/database/static.ts to serve SPA under /database/*
- wire registerDatabaseSpa into plugin.ts
- exempt /database/* from silo rate-limit (same treatment as /admin/*)
- add database:dev + database:build npm scripts; update deploy scripts
- update hub/src/database/README.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-23 21:51:53 +08:00
白
5df1900ca8
docs(hub): document HUB_DEV_LOGIN_BYPASS dev login in database README
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-20 21:09:14 +08:00
白
df66691d24
feat(hub): add /database admin surface with Feishu login
...
Adds a self-contained `/database/*` HTTP surface under hub/src/database:
- /database/admin: Feishu-only login page (Tailwind, light theme)
- /database/dashboard: session-gated sidebar + content shell
- /database/dev-login: DEV ONLY session bypass, double-gated by
NODE_ENV != production AND HUB_DEV_LOGIN_BYPASS; never active in prod
hub.ts mounts the plugin after the admin plugin so the cookie parser and
/auth/feishu/* routes are available. The dev bypass logic is fully contained
in the database module; admin auth routes are untouched.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-20 21:02:04 +08:00
hongjr03
73cb0e5b47
feat(hub): embed agent images via Feishu upload + release v0.0.36 ( #14 )
...
feat(hub): embed agent images via Feishu upload + release v0.0.36
Merge pull request #14
2026-07-20 18:42:38 +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
dc2d1c2f9e
Merge pull request 'chore: remove Lean spec; ADRs are the single source of truth' ( #13 ) from chore/remove-lean-spec into main
...
Reviewed-on: EduCraft/curriculum-project-hub#13
2026-07-20 17:21:14 +08:00
hongjr03
3f9b60f692
chore: remove Lean spec; ADRs are the single source of truth
...
The spec/ Lean semantic master had no conformance gate, no codegen, and
no CI tie to implementations — alignment was carried entirely by human
review, the same mechanism that carries the ADRs. In practice the ADRs
plus greppable code comments were already the load-bearing artifacts,
so spec/ was the most expensive kind of stale documentation.
- delete spec/ and the spec-check CI workflow
- README: constitution rewritten around ADRs as decision truth
- AGENTS.md/CLAUDE.md: discipline re-anchored (new decisions -> new ADR,
never rewrite ADR history; supersede instead)
- code comments: re-anchor 'Mirrors Spec.X' invariants to ADR numbers
(cph-diag, cph-check, cph-model, hub runner/capacity/org, prisma)
- leave ADR bodies and .scratch audit snapshots untouched (history);
fix live references in open readiness tickets
2026-07-20 09:07:26 +00:00
hongjr03
4234ba4c96
Merge pull request 'fix(hub): mark bootstrap Inbox as SYSTEM_INBOX' ( #12 ) from fix/hub-bootstrap-system-inbox into main
2026-07-19 20:16:09 +08:00
hongjr03
15f9443d3d
fix(hub): mark bootstrap Inbox as SYSTEM_INBOX
...
Alpha silo bootstrap created the root Inbox without kind=SYSTEM_INBOX, so
Feishu card project creation tried to insert a second Inbox and hit the
sibling-name unique index. Tag the bootstrap folder correctly and promote
any legacy root Inbox on ensure.
2026-07-19 20:08:44 +08:00
hongjr03
7f09fb1f13
feat(hub): drop redundant /admin/org/:slug path + release v0.0.35 ( #11 )
...
Silo hostname already carries tenancy. Admin SPA routes become /admin/..., legacy bookmarks redirect, login lands on /admin.
Co-authored-by: Hong Jiarong <me@jrhim.com >
Co-committed-by: Hong Jiarong <me@jrhim.com >
v0.0.35
2026-07-19 01:36:10 +08:00
hongjr03
eb0be43eac
feat(hub): usage fact breakdown API + admin usage/session UI + release v0.0.34 ( #10 )
...
Expose UsageFact kind/capability rollups on org and project usage reports, and add admin pages that separate model tokens from external-capability meters.
Co-authored-by: Hong Jiarong <me@jrhim.com >
Co-committed-by: Hong Jiarong <me@jrhim.com >
v0.0.34
2026-07-19 01:19:59 +08:00
hongjr03
ce18740870
feat(hub): expose pdf_to_md_bundle as MCP tool to agent + skill (ADR-0027) ( #9 )
...
Co-authored-by: Hong Jiarong <me@jrhim.com >
Co-committed-by: Hong Jiarong <me@jrhim.com >
2026-07-18 21:43:00 +08:00
hongjr03
ef96f8d33d
feat(hub): capability connection admin API + UI + release v0.0.32 ( #8 )
...
Co-authored-by: Hong Jiarong <me@jrhim.com >
Co-committed-by: Hong Jiarong <me@jrhim.com >
2026-07-18 17:57:04 +08:00
hongjr03
5e10419fc8
fix(hub): docmind client stream upload + correct API response parsing ( #7 )
...
Co-authored-by: Hong Jiarong <me@jrhim.com >
Co-committed-by: Hong Jiarong <me@jrhim.com >
2026-07-18 17:26:11 +08:00