跳到主要内容
版本:0.4.x(Latest)

基本介绍

为提升框架整体的灵活性与可扩展性,主框架采用领域驱动的设计思路对核心能力进行建模,并以解耦方式组织各领域能力的实现与契约。apps/lina-core/pkg/plugin目录作为公开的Go契约边界,向插件暴露稳定的领域服务接口——源码插件通过pluginhost.Services消费完整的capability.Services目录,动态插件通过pluginbridge.Default()返回的pluginbridge.Services消费已经发布为hostServices的能力子集。

组件结构

路径职责
capability/聚合稳定宿主能力,包含ServicesAdminServices、插件作用域服务绑定和各领域窄接口;源码插件直接使用完整目录,动态插件使用已发布的桥接子集
pluginhost/源码插件宿主命名空间,提供编译期注册接口层和运行期回调契约
pluginbridge/动态插件桥接命名空间,提供pluginbridge.Default()/pluginbridge.New()运行时能力目录、Wasm执行契约和hostServices编解码

声明期与运行期

插件能力分为声明期和运行期两个阶段。声明期是插件的静态注册和发现阶段,主框架在业务执行前使用声明输出构建治理状态;运行期是插件业务逻辑执行阶段,插件消费主框架提供的领域能力服务。

声明期能力的详细设计和使用方式请参阅声明期能力概览,包括资源声明生命周期声明路由声明任务声明钩子声明提供方声明访问控制声明

声明期能力

声明期能力是插件的静态注册输出。源码插件在编译期通过pluginhost.Declarations注册,动态插件通过plugin.yaml清单和pluginbridge.Declarations声明。

源码插件声明期

源码插件通过pluginhost.Declarationsinit()中注册以下声明:

声明入口功能说明
ID()返回与plugin.yaml一致的稳定插件标识
Assets()绑定插件嵌入文件系统,包含清单、前端页面、SQLi18n资源
Lifecycle()注册安装、升级、禁用、卸载、租户禁用、租户删除和安装模式变更等16个生命周期回调
Hooks()订阅主框架扩展点事件,例如auth.login.succeededplugin.enabledsystem.started
HTTP()注册插件HTTP路由贡献回调,由主框架启动时统一触发
Jobs()注册定时任务贡献回调,由主框架调度时统一触发
Providers()声明领域能力提供方工厂,例如ProvideTenantProvideOrgProvideAIText
Access()注册菜单过滤和权限过滤回调,用于运行时动态调整工作台导航和权限

动态插件声明期

动态插件通过plugin.yaml清单和构建期契约表达声明:

声明来源功能说明
plugin.yaml声明插件身份、版本、依赖、菜单、权限、多租户策略、公开静态资源和hostServices授权申请
Routes()声明路由组绑定,指定API前缀和路由包
Jobs()通过host-service调用注册定时任务契约
WASM自定义段.wasm产物中嵌入ABI版本、运行时类型、编解码器和导出函数名等元数据
protocol.BridgeSpec定义桥接ABI契约,包括版本号、运行时类型、编解码方式和alloc/execute导出名称

运行期能力

运行期能力是插件业务逻辑执行时可用的服务。源码插件和动态插件共享宿主领域能力模型,但公开入口不同。

源码插件运行期

源码插件通过pluginhost.Services访问运行期能力。该接口内嵌capability.Services,直接暴露全部领域能力方法,并额外提供源码插件专属能力:

能力入口功能说明
全部领域能力包括AIAuthCacheStorage等能力
Admin()可信管理命令,例如修改用户状态、替换角色权限、吊销会话、写入运行时配置等
TenantFilter()为插件自有表追加租户过滤条件的数据库查询构建器

动态插件运行期

动态插件通过pluginbridge.Default()访问已发布的运行期能力。所有调用经由WASI host call传输,由宿主按hostServices授权快照校验后分发执行。动态插件访问的是动态服务目录中的能力子集,并拥有三个专属能力:

能力入口功能说明
已发布领域能力例如AIAuthCacheStorage等能力,通过host-call桥接访问;I18n()不发布为动态hostServices
Runtime()专属能力:日志写入、插件状态读写、时间获取、UUID生成、节点身份读取
Network()专属能力:受治理的出站HTTP请求,需在plugin.yaml中声明授权目标地址
RecordStore()专属能力:data服务的类ORM封装层,只能访问声明的插件自有表

AdminServices边界

capability.AdminServices是可信源码插件的管理命令目录,只通过pluginhost.Services.Admin()暴露。源码插件可以在宿主进程内接收经过领域治理的管理能力,例如用户管理、权限管理、通知管理、会话强退和插件治理命令。

动态插件的pluginbridge.Services接口不提供Admin()入口,因此不能直接使用sessioncap.AdminServicenotifycap.AdminService或其他领域AdminService接口。动态插件只能调用已经发布为动态hostServices、已经写入plugin.yaml声明、经过宿主授权并注册到WASM host-service分发器中的具体方法。

例如当前sessions动态服务只提供sessions.searchsessions.batch_get,不包含sessioncap.AdminService.RevokeSession对应的强退命令。如果未来确实需要让动态插件使用某个管理动作,再考虑开放管理接口。

领域能力概览

方法领域文档说明
AI()AI能力聚合文本、图片、向量、音频、视觉、文档、安全和视频子能力
APIDoc()接口文档能力解析路由操作键、本地化模块标签和操作摘要
Auth()认证与授权能力聚合Token()Authz()子能力
Users()用户能力用户视图、搜索和可见性校验
BizCtx()业务上下文能力读取当前请求用户、租户、模拟登录和平台绕过状态
Cache()缓存能力插件作用域运行时缓存
Dict()字典能力字典标签解析和刷新视图
Files()文件能力文件视图和可见性校验
HostConfig()配置管理能力读取宿主配置值;动态插件读取时必须声明keys
I18n()国际化能力源码插件运行时翻译能力;动态插件不开放对应host service
Infra()基础设施能力基础设施组件状态视图
Jobs()任务与定时能力定时任务视图读取
Manifest()清单资源能力读取当前插件manifest/下的只读资源
Notifications()通知能力通知消息视图读取
Org()组织能力可选组织能力,读取用户部门和岗位视图
Plugins()插件治理能力聚合插件注册表、插件配置、插件状态和生命周期子能力
Route()动态路由能力读取当前动态路由元数据
Sessions()在线会话能力在线会话搜索和批量读取
Storage()文件能力插件作用域对象存储操作
Tenant()租户能力可选租户能力,读取当前租户、可见性、切换校验和源码插件租户过滤
Lock()分布式锁能力插件可见的分布式锁获取、续租和释放

插件作用域能力会由宿主绑定插件身份。例如Plugins().Config()只读取当前插件自己的config.yamlManifest()只读取当前插件的manifest/资源,AI()会把来源插件ID注入后续提供方请求。

SPI架构设计

部分领域能力属于可选框架能力——它们不是主框架内置的,而是由提供方插件实现具体逻辑后注入到宿主运行时。当前采用SPI模式的能力比如AIOrgTenant等,对应的官方提供方插件分别为linapro-ai-corelinapro-org-corelinapro-tenant-core

架构设计

SPIService Provider Interface)模式的核心思想是将能力契约与能力实现分离。宿主定义领域能力的公开接口(即SPI契约),提供方插件负责实现具体业务逻辑。宿主通过延迟构造避免启动阶段对可选插件的强依赖——只有当能力首次被消费时,宿主才会实例化提供方。

设计要点说明
延迟构造宿主只在能力首次被消费时构造提供方实例,避免启动阶段强依赖可选插件
安全降级没有可用提供方时,能力返回空结果或不可用状态,而非nil或错误
来源注入宿主通过ProviderEnv向提供方注入请求上下文、插件身份和辅助能力
启用状态隔离提供方状态独立于业务入口可见性——插件的业务入口可能对当前租户不可见,但仍可作为平台能力提供方可用

SPI服务注册

源码插件通过pluginhost.Declarations.Providers()声明SPI工厂。每个工厂是一个构造函数,接收ProviderEnv参数并返回提供方实例:

ProviderEnv是宿主向提供方注入的运行期上下文,通常包含:

注入项说明
插件身份当前提供方插件的ID,用于审计和隔离
请求上下文当前请求的租户、用户等业务上下文
辅助能力提供方实现所需的宿主能力,例如TenantFilter、用户视图等

SPI提供方状态检查

宿主通过Plugins().State().IsProviderEnabled()判断提供方是否可用。该检查与IsEnabled语义不同:

检查方法语义适用场景
IsEnabled插件的业务入口对当前租户是否可见菜单过滤、路由可见性、权限过滤
IsProviderEnabled插件是否平台启用且可承接框架能力提供方调用AIOrgTenant等能力调用前检查

提供方检查确保即使业务入口被租户级禁用,平台级能力仍可正常服务。

插件实现SPI提供方

源码插件实现SPI提供方分为注册和实现两个步骤。以Org能力为例:

注册SPI工厂:

提供方插件在init()中通过Providers()声明入口注册工厂函数:

func init() {
plugin := pluginhost.NewDeclarations("my-author-my-org-provider")
if err := plugin.Providers().ProvideOrg(func(ctx context.Context, env orgspi.ProviderEnv) (orgspi.Provider, error) {
return &myOrgProvider{env: env}, nil
}); err != nil {
panic(err)
}

if err := pluginhost.RegisterSourcePlugin(plugin); err != nil {
panic(err)
}
}

实现SPI契约:

提供方需要实现能力领域包中定义的Provider接口。以orgcap.Provider为例,提供方需要实现部门视图、岗位视图等完整组织能力:

type myOrgProvider struct {
env orgcap.ProviderEnv
}

func (p *myOrgProvider) ListUserDeptAssignments(ctx context.Context, userIDs []string) ([]DeptAssignment, error) {
// 查询提供方自己的组织数据
// 可通过 p.env 访问宿主注入的辅助能力
}

func (p *myOrgProvider) GetUserDeptInfo(ctx context.Context, userID string) (*DeptInfo, error) {
// 实现部门信息查询
}

各能力的提供方接口定义位于对应的领域能力包中:

能力SPI接口SPI官方插件
AI各子能力独立接口aicaplinapro-ai-core
Orgorgcap.Providerorgcaplinapro-org-core
Tenanttenantcap.Provider + tenantcap.Resolvertenantcaplinapro-tenant-core

Tenant能力额外提供tenantcap.Resolver接口,负责从HTTP请求中解析租户身份,可按请求头、域名、路径、令牌或其他策略组成责任链。

动态插件与SPI

动态插件不能直接注册SPI工厂,因为提供方需要实现Go接口并运行在宿主进程中。动态插件通过以下方式与SPI能力交互:

交互方式说明
消费SPI能力通过hostServices声明调用已发布的SPI能力方法,例如service: aiservice: orgservice: tenant
检查SPI提供方状态通过plugins.provider_enabled.check动态方法判断提供方是否可用
状态查询通过capability.availablecapability.status动态方法查询能力可用性和活跃提供方

动态插件在plugin.yaml中声明对SPI能力的消费:

hostServices:
- service: ai
methods:
- text.generate
- service: org
methods:
- users.dept_name.get
- service: tenant
methods:
- tenants.current

动态hostServices

动态插件不能直接访问宿主实现包,也不能直接使用源码插件专属的AdminServices管理命令目录。它们通过plugin.yaml中的hostServices声明需要调用的宿主服务,一个典型的plugin.yaml中的hostServices声明如下:

hostServices:
- service: runtime
methods:
- log.write
- state.get
- state.set
- service: storage
methods:
- put
- get
- list
resources:
paths:
- exports/
- service: data
methods:
- list
- get
- create
resources:
tables:
- plugin_demo_reports
- service: network
methods:
- request
resources:
- url: https://api.example.com/v1/*
- service: hostconfig
methods: [get]
resources:
keys:
- workspace.basePath
- service: manifest
methods: [get]
resources:
paths:
- profile.yaml
- service: ai
methods:
- text.generate

资源声明形态

资源类型声明字段服务
none不声明resourcesruntimeapidocauthauthzaiusersbizctxdictfilesinfrajobsnotificationspluginsroutesessionsorgtenant
pathresources.pathsstoragemanifest
tableresources.tablesdata
keyresources.keyshostconfig
resourceresources[].urlresources[].ref及服务专属属性networkcachelocknotifications(仅messages.send

生产校验会要求data服务表属于插件自有命名空间。动态插件不得声明sys_*这类宿主核心表,也不应把宿主表名作为插件数据能力的目标。

动态服务目录

服务领域文档资源类型方法
runtime动态Runtime能力nonelog.writestate.getstate.setstate.deleteinfo.nowinfo.uuidinfo.node
storage文件能力pathputgetdeleteliststat
network外部网络能力resourcerequest
data数据记录能力tablelistgetcreateupdatedeletetransaction
cache缓存能力resourcegetsetdeleteincrexpire
lock分布式锁能力resourceacquirerenewrelease
hostconfig配置管理能力keyget
manifest清单资源能力pathget
apidoc接口文档能力noneroute_text.resolveroute_texts.resolveroute_title_operation_keys.find
auth认证与授权能力nonetenant.selecttenant.switchimpersonation_token.issueimpersonation_token.revoke
authz认证与授权能力nonepermissions.batch_getpermissions.hasusers.platform_admin.check
aiAI能力nonetext.generateimage.generateimage.editembedding.createaudio.transcribeaudio.synthesizevision.analyzedocument.analyzedocument.citesafety.moderatevideo.generatevideo.editvideo.extendvideo.operation.getvideo.operation.cancel
users用户能力noneusers.batch_getusers.searchusers.visible.ensure
bizctx业务上下文能力nonecurrent.get
dict字典能力nonelabels.resolve
files文件能力nonefiles.batch_getfiles.visible.ensure
infra基础设施能力nonestatus.batch_get
jobs任务与定时能力nonejobs.batch_getjobs.register
notifications通知能力读取无资源;messages.send使用resources[].refmessages.batch_getmessages.send
plugins插件治理能力noneplugins.batch_getplugins.tenant.listplugins.enabled.checkplugins.provider_enabled.checkplugins.enabled_authoritative.checkconfig.getlifecycle.tenant_plugin_disable.ensurelifecycle.tenant_plugin_disabled.notifylifecycle.tenant_delete.ensurelifecycle.tenant_deleted.notify
route动态路由能力nonemetadata.get
sessions在线会话能力nonesessions.searchsessions.batch_get
org组织能力nonecapability.availablecapability.statususers.dept_assignments.listusers.dept_info.getusers.dept_name.getusers.dept_ids.getusers.post_ids.get
tenant租户能力nonecapability.availablecapability.statustenants.currenttenants.platform_bypasstenants.visible.ensureusers.tenant_membership.validateusers.tenants.listtenants.switch.validate
secret预留resourceresolve
event预留resourcepublish
queue预留resourceenqueue

动态插件专属能力

Runtime()Network()RecordStore()pluginbridge.Default()返回目录上的动态插件专属能力。它们不属于capability.Services,因为源码插件已经运行在宿主进程内,可以使用宿主原生等价能力。

能力公开入口说明
Runtime()pluginbridge.Default().Runtime()动态插件通过WASI host-service客户端写日志、读写状态、读取时间、生成UUID和读取节点身份;源码插件直接使用宿主原生日志和运行期上下文
Network()pluginbridge.Default().Network()动态插件通过host-service授权访问受治理的出站HTTP;源码插件使用宿主原生HTTP client或注入的领域服务
RecordStore()pluginbridge.Default().RecordStore()动态插件使用pluginbridgefacade封装data host-service协议和类型化查询计划;源码插件使用自有DAO或提供方接缝

相关文档