@@ -6,12 +6,17 @@ import type { PluginRuntime } from "../plugins/runtime/types.js";
66import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js" ;
77import { resetPluginStateStoreForTests } from "./plugin-state-store.js" ;
88
9- function createPluginRecord ( id : string , origin : PluginRecord [ "origin" ] = "bundled" ) : PluginRecord {
9+ function createPluginRecord (
10+ id : string ,
11+ origin : PluginRecord [ "origin" ] = "bundled" ,
12+ opts : { trustedOfficialInstall ?: boolean } = { } ,
13+ ) : PluginRecord {
1014 return {
1115 id,
1216 name : id ,
1317 source : `/plugins/${ id } /index.ts` ,
1418 origin,
19+ trustedOfficialInstall : opts . trustedOfficialInstall ,
1520 enabled : true ,
1621 status : "loaded" ,
1722 toolNames : [ ] ,
@@ -87,6 +92,22 @@ describe("plugin runtime state proxy", () => {
8792 } ) ;
8893 } ) ;
8994
95+ it ( "allows trusted official global plugins to use keyed state" , async ( ) => {
96+ await withOpenClawTestState ( { label : "plugin-state-trusted-global" } , async ( ) => {
97+ const registry = createTestPluginRegistry ( ) ;
98+ const record = createPluginRecord ( "slack" , "global" , { trustedOfficialInstall : true } ) ;
99+ registry . registry . plugins . push ( record ) ;
100+ const api = registry . createApi ( record , { config : { } } ) ;
101+
102+ const store = api . runtime . state . openKeyedStore < { plugin : string } > ( {
103+ namespace : "runtime" ,
104+ maxEntries : 10 ,
105+ } ) ;
106+ await expect ( store . register ( "thread" , { plugin : "slack" } ) ) . resolves . toBeUndefined ( ) ;
107+ await expect ( store . lookup ( "thread" ) ) . resolves . toEqual ( { plugin : "slack" } ) ;
108+ } ) ;
109+ } ) ;
110+
90111 it ( "rejects external plugins in this release" , ( ) => {
91112 const registry = createTestPluginRegistry ( ) ;
92113 const record = createPluginRecord ( "external-plugin" , "workspace" ) ;
@@ -95,6 +116,17 @@ describe("plugin runtime state proxy", () => {
95116
96117 expect ( ( ) =>
97118 api . runtime . state . openKeyedStore ( { namespace : "runtime" , maxEntries : 10 } ) ,
98- ) . toThrow ( "openKeyedStore is only available for bundled plugins" ) ;
119+ ) . toThrow ( "openKeyedStore is only available for trusted plugins" ) ;
120+ } ) ;
121+
122+ it ( "rejects untrusted global plugins" , ( ) => {
123+ const registry = createTestPluginRegistry ( ) ;
124+ const record = createPluginRecord ( "external-plugin" , "global" ) ;
125+ registry . registry . plugins . push ( record ) ;
126+ const api = registry . createApi ( record , { config : { } } ) ;
127+
128+ expect ( ( ) =>
129+ api . runtime . state . openKeyedStore ( { namespace : "runtime" , maxEntries : 10 } ) ,
130+ ) . toThrow ( "openKeyedStore is only available for trusted plugins" ) ;
99131 } ) ;
100132} ) ;
0 commit comments