@@ -1329,6 +1329,66 @@ describe("skills-clawhub", () => {
13291329 }
13301330 } ) ;
13311331
1332+ it ( "accepts owner-qualified installed verification targets" , async ( ) => {
1333+ const workspaceDir = await tempDirs . make ( "openclaw-skill-verify-" ) ;
1334+ try {
1335+ await writeClawHubOriginFixture ( {
1336+ workspaceDir,
1337+ slug : "weather" ,
1338+ ownerHandle : "demo-owner" ,
1339+ registry : "https://private.example.com/clawhub" ,
1340+ installedVersion : "2.0.0" ,
1341+ } ) ;
1342+
1343+ await expect (
1344+ resolveClawHubSkillVerificationTarget ( {
1345+ workspaceDir,
1346+ slug : "@demo-owner/weather" ,
1347+ } ) ,
1348+ ) . resolves . toMatchObject ( {
1349+ ok : true ,
1350+ slug : "weather" ,
1351+ ownerHandle : "demo-owner" ,
1352+ baseUrl : "https://private.example.com/clawhub" ,
1353+ version : "2.0.0" ,
1354+ tag : undefined ,
1355+ resolution : {
1356+ source : "installed" ,
1357+ selector : "installed-version" ,
1358+ registry : "https://private.example.com/clawhub" ,
1359+ installedVersion : "2.0.0" ,
1360+ } ,
1361+ } ) ;
1362+ } finally {
1363+ await fs . rm ( workspaceDir , { recursive : true , force : true } ) ;
1364+ }
1365+ } ) ;
1366+
1367+ it ( "rejects owner-qualified installed verification when the owner differs" , async ( ) => {
1368+ const workspaceDir = await tempDirs . make ( "openclaw-skill-verify-" ) ;
1369+ try {
1370+ await writeClawHubOriginFixture ( {
1371+ workspaceDir,
1372+ slug : "weather" ,
1373+ ownerHandle : "demo-owner" ,
1374+ } ) ;
1375+
1376+ const result = await resolveClawHubSkillVerificationTarget ( {
1377+ workspaceDir,
1378+ slug : "@other-owner/weather" ,
1379+ } ) ;
1380+
1381+ expect ( result . ok ) . toBe ( false ) ;
1382+ if ( result . ok ) {
1383+ throw new Error ( "expected owner mismatch failure" ) ;
1384+ }
1385+ expect ( result . error ) . toContain ( "is tracked as @demo-owner/weather" ) ;
1386+ expect ( result . error ) . toContain ( "not @other-owner/weather" ) ;
1387+ } finally {
1388+ await fs . rm ( workspaceDir , { recursive : true , force : true } ) ;
1389+ }
1390+ } ) ;
1391+
13321392 it ( "keeps the installed registry when an explicit version overrides the installed version" , async ( ) => {
13331393 const workspaceDir = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "openclaw-skill-verify-" ) ) ;
13341394 try {
@@ -1634,6 +1694,79 @@ describe("skills-clawhub", () => {
16341694 }
16351695 } ) ;
16361696
1697+ it ( "uses owner-qualified registry verification targets" , async ( ) => {
1698+ const workspaceDir = await tempDirs . make ( "openclaw-skill-verify-" ) ;
1699+ resolveClawHubBaseUrlMock . mockReturnValueOnce ( "https://configured.example.com/clawhub" ) ;
1700+ try {
1701+ await expect (
1702+ resolveClawHubSkillVerificationTarget ( {
1703+ workspaceDir,
1704+ slug : "@demo-owner/weather" ,
1705+ baseUrl : "https://configured.example.com/clawhub/" ,
1706+ } ) ,
1707+ ) . resolves . toEqual ( {
1708+ ok : true ,
1709+ slug : "weather" ,
1710+ ownerHandle : "demo-owner" ,
1711+ baseUrl : "https://configured.example.com/clawhub" ,
1712+ version : undefined ,
1713+ tag : undefined ,
1714+ resolution : {
1715+ source : "registry" ,
1716+ selector : "latest" ,
1717+ registry : "https://configured.example.com/clawhub" ,
1718+ skillDir : undefined ,
1719+ installedVersion : undefined ,
1720+ } ,
1721+ } ) ;
1722+ } finally {
1723+ await fs . rm ( workspaceDir , { recursive : true , force : true } ) ;
1724+ }
1725+ } ) ;
1726+
1727+ it ( "keeps owner-qualified registry selectors for explicit versions and tags" , async ( ) => {
1728+ const workspaceDir = await tempDirs . make ( "openclaw-skill-verify-" ) ;
1729+ try {
1730+ await expect (
1731+ resolveClawHubSkillVerificationTarget ( {
1732+ workspaceDir,
1733+ slug : "@demo-owner/weather" ,
1734+ version : "2.0.0" ,
1735+ } ) ,
1736+ ) . resolves . toMatchObject ( {
1737+ ok : true ,
1738+ slug : "weather" ,
1739+ ownerHandle : "demo-owner" ,
1740+ version : "2.0.0" ,
1741+ tag : undefined ,
1742+ resolution : {
1743+ source : "registry" ,
1744+ selector : "version" ,
1745+ } ,
1746+ } ) ;
1747+
1748+ await expect (
1749+ resolveClawHubSkillVerificationTarget ( {
1750+ workspaceDir,
1751+ slug : "@demo-owner/weather" ,
1752+ tag : "beta" ,
1753+ } ) ,
1754+ ) . resolves . toMatchObject ( {
1755+ ok : true ,
1756+ slug : "weather" ,
1757+ ownerHandle : "demo-owner" ,
1758+ version : undefined ,
1759+ tag : "beta" ,
1760+ resolution : {
1761+ source : "registry" ,
1762+ selector : "tag" ,
1763+ } ,
1764+ } ) ;
1765+ } finally {
1766+ await fs . rm ( workspaceDir , { recursive : true , force : true } ) ;
1767+ }
1768+ } ) ;
1769+
16371770 it ( "fails clearly when installed origin metadata is malformed" , async ( ) => {
16381771 const workspaceDir = await fs . mkdtemp ( path . join ( os . tmpdir ( ) , "openclaw-skill-verify-" ) ) ;
16391772 try {
0 commit comments