forked from EduCraft/curriculum-project-hub
chore: add c4 spec
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
model {
|
||||
teacher = actor 'Teacher' {
|
||||
description '教研老师。可以同时参与多个项目群,在群里讨论并在需要时 @Claude。'
|
||||
}
|
||||
|
||||
admin = actor 'Admin' {
|
||||
description '管理员。管理项目、权限、异常锁释放和审计。'
|
||||
}
|
||||
|
||||
feishu = externalSystem 'Feishu / Lark' {
|
||||
description '项目群、消息、卡片交互和历史消息 API。'
|
||||
}
|
||||
|
||||
claude = externalSystem 'Claude / Claude Code' {
|
||||
description '执行课程资料生成、修改和问答的 AI agent。'
|
||||
}
|
||||
|
||||
workspace = externalSystem 'Project Workspace' {
|
||||
description '每个课程项目的文件、素材、课件、教案和生成产物所在工作区。'
|
||||
}
|
||||
|
||||
hub = system 'Curriculum Project Hub' {
|
||||
description '教研项目工作台。把项目、飞书群、Claude run、锁、上下文和产物管理成一个明确的协作系统。'
|
||||
|
||||
web = app 'Project Console' {
|
||||
description '后台/工作台 UI,用于项目管理、权限、run 审计、异常取消和强制释放锁。'
|
||||
}
|
||||
|
||||
api = service 'Hub API' {
|
||||
description '对 UI、飞书回调、内部 agent runtime 暴露业务 API。'
|
||||
}
|
||||
|
||||
project = service 'Project Service' {
|
||||
description '管理 Project、成员、项目群绑定、项目状态和产物引用。'
|
||||
}
|
||||
|
||||
permission = service 'Permission Service' {
|
||||
description '飞书云文档式权限层。按 resource + principal + role 授权,并用 permission settings 控制分享、评论、下载、协作者管理和 Claude 调用。'
|
||||
}
|
||||
|
||||
im = adapter 'IM Bridge Adapter' {
|
||||
description '飞书/Lark 适配层。负责事件去重、卡片、消息投递、按钮回调和限流;优先评估复用 Claude-to-IM 的 adapter/delivery 能力。'
|
||||
}
|
||||
|
||||
run = service 'Run Orchestrator' {
|
||||
description '在 @Claude 时创建 AgentRun,申请项目锁,调度 Claude runtime,处理取消、失败、等待用户和完成。'
|
||||
}
|
||||
|
||||
locks = service 'Project Lock Service' {
|
||||
description '统一项目级锁。scope = project_id,owner = run_id,lifetime = 一次 Claude run。'
|
||||
}
|
||||
|
||||
context = service 'Context Service' {
|
||||
description '提供当前触发消息、回复链、项目记忆、产物上下文和按需历史读取。第一版不长期缓存飞书全文。'
|
||||
}
|
||||
|
||||
mcp = service 'MCP Gateway' {
|
||||
description 'Claude 可调用的内部工具入口,例如读取当前项目群历史、触发消息、附件和产物上下文。'
|
||||
}
|
||||
|
||||
runtime = runtime 'Claude Runtime' {
|
||||
description '调用 Claude Code / SDK / wrapper,维护 provider session resume,并执行具体任务。'
|
||||
}
|
||||
|
||||
db = store 'Application Database' {
|
||||
description '项目、群绑定、AgentSession、AgentRun、锁、审计和轻量索引。'
|
||||
|
||||
projectEntity = entity 'Project'
|
||||
groupEntity = entity 'ProjectGroupChat'
|
||||
sessionEntity = entity 'AgentSession'
|
||||
runEntity = entity 'AgentRun'
|
||||
lockEntity = entity 'ProjectAgentLock'
|
||||
permissionEntity = entity 'PermissionGrant'
|
||||
settingsEntity = entity 'PermissionSettings'
|
||||
memoryEntity = entity 'ProjectMemory / Decisions'
|
||||
auditEntity = entity 'AuditLog'
|
||||
}
|
||||
|
||||
web -> api 'manage projects, runs and locks'
|
||||
api -> project 'project commands'
|
||||
api -> permission 'authorize user actions'
|
||||
api -> run 'trigger/cancel/admin actions'
|
||||
api -> db 'read/write application state'
|
||||
|
||||
im -> api 'Feishu events and card callbacks'
|
||||
im -> feishu 'send messages, cards, updates'
|
||||
im -> project 'bind chat to project'
|
||||
im -> permission 'check card/action permissions'
|
||||
im -> run 'create/cancel run on @Claude or card action'
|
||||
|
||||
project -> db 'persist projects and group bindings'
|
||||
permission -> db 'persist grants and settings'
|
||||
run -> locks 'acquire/release project lock'
|
||||
run -> permission 'authorize trigger/cancel/force release'
|
||||
locks -> db 'persist lock owner = run_id'
|
||||
run -> context 'build seed context'
|
||||
run -> runtime 'execute Claude turn'
|
||||
run -> db 'persist AgentRun state'
|
||||
|
||||
runtime -> claude 'resume/call Claude'
|
||||
runtime -> workspace 'read/write project files'
|
||||
runtime -> mcp 'request project context'
|
||||
mcp -> context 'resolve run-scoped context'
|
||||
context -> feishu 'read messages by chat/thread/message id'
|
||||
context -> db 'read project memory and anchors'
|
||||
|
||||
projectEntity -> groupEntity 'has project group'
|
||||
projectEntity -> permissionEntity 'has collaborators'
|
||||
projectEntity -> settingsEntity 'has operation settings'
|
||||
projectEntity -> sessionEntity 'has long-lived Claude session'
|
||||
projectEntity -> runEntity 'has many runs'
|
||||
projectEntity -> lockEntity 'has current lock'
|
||||
permissionEntity -> settingsEntity 'is constrained by'
|
||||
runEntity -> lockEntity 'owns while running'
|
||||
sessionEntity -> runEntity 'is reused by runs'
|
||||
projectEntity -> memoryEntity 'stores summary and decisions'
|
||||
runEntity -> auditEntity 'records lifecycle events'
|
||||
}
|
||||
|
||||
teacher -> feishu 'discusses in project groups'
|
||||
teacher -> hub.im '@Claude and card actions'
|
||||
teacher -> hub.web 'reviews projects and runs'
|
||||
admin -> hub.web 'administers locks, permissions and audit'
|
||||
|
||||
feishu -> hub.im 'message events and callbacks'
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
specification {
|
||||
element actor {
|
||||
style {
|
||||
shape person
|
||||
color indigo
|
||||
}
|
||||
}
|
||||
|
||||
element system {
|
||||
style {
|
||||
color primary
|
||||
}
|
||||
}
|
||||
|
||||
element externalSystem {
|
||||
style {
|
||||
color gray
|
||||
}
|
||||
}
|
||||
|
||||
element app {
|
||||
style {
|
||||
shape browser
|
||||
color green
|
||||
}
|
||||
}
|
||||
|
||||
element service {
|
||||
style {
|
||||
shape component
|
||||
color primary
|
||||
}
|
||||
}
|
||||
|
||||
element adapter {
|
||||
style {
|
||||
shape component
|
||||
color amber
|
||||
}
|
||||
}
|
||||
|
||||
element runtime {
|
||||
style {
|
||||
shape component
|
||||
color secondary
|
||||
}
|
||||
}
|
||||
|
||||
element store {
|
||||
style {
|
||||
shape storage
|
||||
color muted
|
||||
}
|
||||
}
|
||||
|
||||
element entity {
|
||||
style {
|
||||
shape storage
|
||||
color muted
|
||||
}
|
||||
}
|
||||
|
||||
relationship sync {
|
||||
line solid
|
||||
}
|
||||
|
||||
relationship async {
|
||||
line dotted
|
||||
}
|
||||
|
||||
relationship reads {
|
||||
line dashed
|
||||
color gray
|
||||
}
|
||||
|
||||
relationship writes {
|
||||
line solid
|
||||
color gray
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
views {
|
||||
view index {
|
||||
title 'System Context'
|
||||
description '''
|
||||
Curriculum Project Hub treats a Feishu group as the long-lived project collaboration space.
|
||||
Claude joins only when teachers @Claude, and the Hub creates one AgentRun for that work.
|
||||
'''
|
||||
|
||||
include teacher, admin, hub, feishu, claude, workspace
|
||||
}
|
||||
|
||||
view containers of hub {
|
||||
title 'Target Containers'
|
||||
description 'Main runtime containers and external integrations for the target architecture.'
|
||||
|
||||
include *
|
||||
include teacher, admin, feishu, claude, workspace
|
||||
}
|
||||
|
||||
view permissions of hub {
|
||||
title 'Permission Model'
|
||||
description '''
|
||||
Permissions follow the Feishu Docs pattern: collaborator grants are separate from operation settings.
|
||||
Grants are resource + principal + role; settings decide who may share, comment, copy/download, manage collaborators and invoke Claude.
|
||||
'''
|
||||
|
||||
include permission, project, im, run, db
|
||||
include db.projectEntity, db.groupEntity, db.permissionEntity, db.settingsEntity, db.auditEntity
|
||||
include teacher, admin, feishu
|
||||
}
|
||||
|
||||
view domain_model of hub.db {
|
||||
title 'Core Domain Model'
|
||||
description '''
|
||||
The main correction from the old demo model: project groups and Claude sessions are long-lived,
|
||||
but project locks are owned by AgentRun, not by teacher, chat or session.
|
||||
'''
|
||||
|
||||
include *
|
||||
}
|
||||
|
||||
dynamic view run_lifecycle {
|
||||
title '@Claude Run Lifecycle'
|
||||
description 'A teacher @Claude message creates one AgentRun, which owns the project lock until completion, cancellation or timeout.'
|
||||
|
||||
teacher -> feishu 'send @Claude in project group'
|
||||
feishu -> hub.im 'message event'
|
||||
hub.im -> hub.project 'resolve chat binding'
|
||||
hub.im -> hub.permission 'check trigger permission'
|
||||
hub.im -> hub.run 'create AgentRun'
|
||||
hub.run -> hub.locks 'acquire project lock with run_id'
|
||||
hub.run -> hub.context 'build seed context'
|
||||
hub.run -> hub.runtime 'execute Claude turn'
|
||||
hub.runtime -> claude 'resume/call Claude'
|
||||
hub.runtime -> workspace 'read/write project files'
|
||||
hub.runtime -> hub.mcp 'request extra context if needed'
|
||||
hub.mcp -> hub.context 'resolve run-scoped tools'
|
||||
hub.context -> feishu 'read history by message/thread/chat'
|
||||
hub.runtime -> hub.run 'return result'
|
||||
hub.run -> hub.im 'publish status/result card'
|
||||
hub.im -> feishu 'send/update card'
|
||||
hub.run -> hub.locks 'release run-owned lock'
|
||||
|
||||
include teacher, feishu, claude, workspace
|
||||
}
|
||||
|
||||
dynamic view cancel_lifecycle {
|
||||
title 'Cancel Current Processing'
|
||||
description 'A permitted teacher can cancel the current active run from card action or @Claude cancel command.'
|
||||
|
||||
teacher -> feishu 'click cancel or @Claude cancel'
|
||||
feishu -> hub.im 'callback/event'
|
||||
hub.im -> hub.project 'resolve project group binding'
|
||||
hub.im -> hub.permission 'check cancel permission'
|
||||
hub.im -> hub.run 'cancel active run'
|
||||
hub.run -> hub.runtime 'abort controller if local process is alive'
|
||||
hub.run -> hub.locks 'release lock by run_id'
|
||||
hub.run -> hub.db 'mark AgentRun canceled and audit actor'
|
||||
hub.run -> hub.im 'update status card'
|
||||
hub.im -> feishu 'processing canceled'
|
||||
|
||||
include teacher, feishu
|
||||
}
|
||||
|
||||
dynamic view context_access {
|
||||
title 'On-demand Context Access'
|
||||
description '''
|
||||
The Hub stores anchors and memory, not full Feishu history. Claude can call MCP tools
|
||||
to fetch the current trigger message, reply chain, thread history and recent group messages.
|
||||
'''
|
||||
|
||||
hub.runtime -> hub.mcp 'call get_current_message / get_thread_context'
|
||||
hub.mcp -> hub.context 'authorize by run_id and project_id'
|
||||
hub.context -> hub.db 'read anchors, memory and decisions'
|
||||
hub.context -> feishu 'fetch message/thread/chat history'
|
||||
feishu -> hub.context 'history page'
|
||||
hub.context -> hub.mcp 'filtered context'
|
||||
hub.mcp -> hub.runtime 'tool result'
|
||||
hub.runtime -> claude 'continue with retrieved context'
|
||||
|
||||
include feishu, claude
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user