2026-10-24 23:19:17 +00:00
import assert from "node:assert/strict" ;
import { randomBytes } from "node:crypto" ;
import { once } from "node:events" ;
import { test } from "node:test" ;
import type { ApplicationConfigurationInput } from "@metis/companies/common" ;
import {
ApplicationConfigurationResponseSchema ,
ApplicationConfigurationsResponseSchema ,
CompanyResponseSchema ,
WorkProfileResponseSchema ,
} from "@metis/companies/common" ;
import {
ApplicationReferenceCapabilitiesSchema ,
CatalogResponseSchema ,
GetGlobalApplicationAdminResponseSchema ,
GlobalApplicationTemplateResponseSchema ,
InventoryResponseSchema ,
ListApplicationCandidatesResponseSchema ,
ResourceResponseSchema ,
} from "@metis/resources/common" ;
import { migrateResourceScope } from "@metis/resources/module" ;
import { QueryTypes } from "sequelize" ;
import { UniqueID } from "../../../packages/rdx-ddd/src/index" ;
import { createApp } from "./app" ;
import { prepareMembershipFixture } from "./asset-directory-memberships.fixture" ;
import { createDatabase , readDatabaseEnvironment } from "./config/database" ;
import { createIdentityRuntime } from "./infrastructure/http/identity-runtime" ;
import { disposableScopeEnvironment , writeScopeEvidence } from "./resource-scope.preflight" ;
import { scopeApiClient } from "./resource-scope-api.client" ;
import { latch , waitBarrier , waitCatalogLock } from "./resource-scope-concurrency.fixture" ;
import { scopeHttpFixture , seedScopeVolume } from "./resource-scope-http.fixture" ;
test ( "R2.5: configuraciones globales locales al perfil, HTTP y concurrencia MariaDB" , async ( t ) = > {
const database = createDatabase ( disposableScopeEnvironment ( ) ) ;
const owners = Array . from ( { length : 15 } , ( ) = > UniqueID . generateNewID ( ) . toPrimitive ( ) ) ;
const company = owners [ 0 ] ;
const other = owners [ 1 ] ;
assert . ok ( company && other ) ;
const actor = UniqueID . generateNewID ( ) . toPrimitive ( ) ;
const fixture = await prepareMembershipFixture ( database , "http://localhost:5173" , actor , owners ) ;
await migrateResourceScope ( database ) ;
const seedHttp = await scopeHttpFixture ( database , fixture ) ;
const volume = await seedScopeVolume ( fixture , seedHttp , company ) ;
await seedHttp . close ( ) ;
const a = volume . profileIds [ 0 ] ;
const a2 = volume . profileIds [ 1 ] ;
const host = volume . assetIds [ 0 ] ;
assert . ok ( a && a2 && host ) ;
const foreignHost = await fixture . asset ( other , "laptop" ) ;
let runtime = await createIdentityRuntime (
database ,
readDatabaseEnvironment ( {
. . . process . env ,
RESOURCE_GLOBAL_CATALOG_ENABLED : "true" ,
RESOURCE_GLOBAL_SOFTWARE_ENABLED : "false" ,
RESOURCE_GLOBAL_SOFTWARE_CANDIDATES_ENABLED : "false" ,
RESOURCE_GLOBAL_PROFILE_ENABLED : "true" ,
} )
) ;
let server = createApp ( ( ) = > undefined , runtime ) . listen ( 0 , "127.0.0.1" ) ;
await once ( server , "listening" ) ;
const address = server . address ( ) ;
assert . ok ( address && typeof address !== "string" ) ;
const base = ` http://127.0.0.1: ${ address . port } ` ;
const admin = await scopeApiClient ( base ) ;
const ordinary = await scopeApiClient ( base ) ;
const password = randomBytes ( 24 ) . toString ( "hex" ) ;
try {
assert . equal (
(
await admin . request ( "/auth/bootstrap" , {
name : "Preparación R2.5" ,
email : "r25-admin@example.invalid" ,
password ,
} )
) . status ,
201
) ;
await admin . refresh ( ) ;
assert . equal (
(
await admin . request ( "/users" , {
name : "Operador R2.5" ,
email : "r25-user@example.invalid" ,
password ,
} )
) . status ,
201
) ;
assert . equal (
( await ordinary . request ( "/auth/login" , { email : "r25-user@example.invalid" , password } ) )
. status ,
200
) ;
await ordinary . refresh ( ) ;
const specification = GlobalApplicationTemplateResponseSchema . parse (
await ( await admin . request ( "/resource-global-applications/template" ) ) . json ( )
) . specification ;
const product = async ( name : string , active = true ) = > {
const response = await admin . request ( "/resource-global-applications" , {
creationId : UniqueID.generateNewID ( ) . toPrimitive ( ) ,
values : {
name ,
templateId : specification.templateId ,
active ,
notes : "Gestión privada R2.5" ,
characteristics : { } ,
} ,
} ) ;
assert . equal ( response . status , 201 , await response . clone ( ) . text ( ) ) ;
return GetGlobalApplicationAdminResponseSchema . parse ( await response . json ( ) ) . resource ;
} ;
const global = await product ( "Ágil compartida R2.5" ) ;
const inactive = await product ( "Inactiva R2.5" , false ) ;
const catalog = CatalogResponseSchema . parse (
await ( await ordinary . request ( ` /resource-catalog/ ${ company } ` ) ) . json ( )
) ;
const template = ( key : string ) = > {
const found = catalog . items . find ( ( item ) = > item . builtinKey === key ) ;
assert . ok ( found ) ;
return found ;
} ;
const local = async ( owner : string , templateId : string , name : string ) = > {
const response = await ordinary . request ( ` /resources/ ${ owner } ` , {
values : { name , templateId , active : true , notes : "" , characteristics : { } } ,
} ) ;
assert . equal ( response . status , 201 ) ;
return ResourceResponseSchema . parse ( await response . json ( ) ) . resource . id ;
} ;
const own = await local ( company , specification . templateId , "Ágil particular" ) ;
const foreign = await local ( other , specification . templateId , "Ágil ajena" ) ;
const os = await local ( company , template ( "template:os" ) . id , "SO no configurable" ) ;
const license = await local (
company ,
template ( "template:software_license" ) . id ,
"Licencia no configurable"
) ;
const certificate = await local (
company ,
template ( "template:certificate" ) . id ,
"Certificado no configurable"
) ;
const locals : string [ ] = [ ] ;
for ( let index = 0 ; index < 50 ; index ++ ) {
locals . push ( await local ( company , specification . templateId , ` Ágil volumen ${ index + 1 } ` ) ) ;
}
const personResult = await ordinary . request ( ` /companies/ ${ other } /people ` , {
name : "Persona de B" ,
active : true ,
isContact : false ,
position : null ,
email : null ,
phone : null ,
} ) ;
const person = CompanyResponseSchema . parse ( await personResult . json ( ) ) . company . people . at ( - 1 ) ;
assert . ok ( person ) ;
const otherWorkstation = await ordinary . request ( ` /assets/ ${ other } /workstations ` , {
values : {
name : "Puesto B R2.5" ,
active : true ,
siteId : null ,
personId : person.id ,
computerAssetId : foreignHost.id.toPrimitive ( ) ,
assetIds : [ foreignHost . id . toPrimitive ( ) ] ,
} ,
} ) ;
assert . equal ( otherWorkstation . status , 201 ) ;
const profileResult = await ordinary . request ( ` /work-profiles/ ${ other } ` , {
values : {
name : "Perfil de B" ,
personId : person.id ,
assetId : foreignHost.id.toPrimitive ( ) ,
accountId : null ,
active : true ,
notes : null ,
} ,
} ) ;
assert . equal ( profileResult . status , 201 , await profileResult . clone ( ) . text ( ) ) ;
const b = WorkProfileResponseSchema . parse ( await profileResult . json ( ) ) . profile . id ;
const path = ` /application-configurations/ ${ company } ` ;
const input : ApplicationConfigurationInput = {
profileId : a ,
resourceId : global.id ,
delivery : "installed" ,
version : "123.4" ,
state : "pending" ,
notes : "Configuración A" ,
} ;
const save = async ( values : ApplicationConfigurationInput , owner = company ) = > {
const response = await ordinary . request ( ` /application-configurations/ ${ owner } ` , { values } ) ;
assert . equal ( response . status , 201 , await response . clone ( ) . text ( ) ) ;
return ApplicationConfigurationResponseSchema . parse ( await response . json ( ) ) . configuration ;
} ;
let first = await save ( input ) ;
const races : string [ ] = [ ] ;
await t . test (
"mismo UUID en varios perfiles y compañías, delivery/versión/estado propios, sin instalaciones" ,
async ( ) = > {
const second = await save ( {
. . . input ,
profileId : a2 ,
delivery : "web" ,
version : null ,
state : "configured" ,
notes : "Perfil A2" ,
} ) ;
const third = await save (
{ . . . input , profileId : b , version : "B-9" , state : "configured" , notes : "Compañía B" } ,
other
) ;
assert . notEqual ( first . id , second . id ) ;
assert . notEqual ( second . id , third . id ) ;
assert . equal ( second . values . version , null ) ;
assert . equal ( second . values . delivery , "web" ) ;
assert . equal ( third . companyId , other ) ;
assert . equal ( third . values . version , "B-9" ) ;
assert . equal ( first . values . version , "123.4" ) ;
const rows = await database . query ( "SELECT id FROM resources WHERE id=:id" , {
replacements : { id : global.id } ,
type : QueryTypes . SELECT ,
} ) ;
assert . equal ( rows . length , 1 ) ;
assert . equal (
(
await database . query ( "SELECT id FROM software_installations" , {
type : QueryTypes . SELECT ,
} )
) . length ,
0
) ;
const inventory = InventoryResponseSchema . parse (
await ( await ordinary . request ( ` /resources/ ${ company } ` ) ) . json ( )
) ;
assert . ok ( inventory . resources . every ( ( item ) = > item . id !== global . id ) ) ;
}
) ;
await t . test (
"matriz negativa, recurso/perfil inmutables, autorización, CSRF y contrato estricto" ,
async ( ) = > {
for ( const [ profileId , resourceId , status ] of [
[ a , foreign , 404 ] ,
[ b , own , 404 ] ,
[ a , inactive . id , 409 ] ,
[ a , os , 404 ] ,
[ a , license , 404 ] ,
[ a , certificate , 404 ] ,
[ a , UniqueID . generateNewID ( ) . toPrimitive ( ) , 404 ] ,
] as const ) {
assert . equal (
( await admin . request ( path , { values : { . . . input , profileId , resourceId } } ) ) . status ,
status
) ;
}
for ( const values of [
{ . . . input , profileId : a2 } ,
{ . . . input , resourceId : own } ,
] ) {
assert . equal (
( await ordinary . request ( ` ${ path } / ${ first . id } /update ` , { values } ) ) . status ,
409
) ;
}
assert . equal (
(
await ordinary . request (
path ,
{ values : { . . . input , resourceId : own } } ,
{ token : "invalid" }
)
) . status ,
403
) ;
assert . equal (
(
await ordinary . request (
path ,
{ values : { . . . input , resourceId : own } } ,
{ origin : "https://invalid.example" }
)
) . status ,
403
) ;
const anonymous = await scopeApiClient ( base ) ;
assert . equal ( ( await anonymous . request ( path ) ) . status , 401 ) ;
assert . equal ( ( await anonymous . request ( path , { values : input } ) ) . status , 401 ) ;
assert . equal (
( await ordinary . request ( path , { values : { . . . input , scope : "global" } } ) ) . status ,
400
) ;
assert . equal (
(
await ordinary . request ( path , {
values : { . . . input , delivery : "web" , version : "no admitida" } ,
} )
) . status ,
400
) ;
assert . equal (
(
await ordinary . request ( ` /work-profiles/ ${ company } ` , {
values : {
name : "Activo ajeno" ,
personId : person.id ,
assetId : foreignHost.id.toPrimitive ( ) ,
accountId : null ,
active : true ,
notes : null ,
} ,
} )
) . status ,
404
) ;
}
) ;
await t . test (
"locales de serie y plantilla propia application, legacy y negociación global v2" ,
async ( ) = > {
const created = await ordinary . request ( ` /resource-catalog/ ${ company } ` , {
values : {
. . . template ( "template:application" ) . values ,
name : "Aplicación propia R2.5" ,
usage : "application" ,
} ,
} ) ;
assert . equal ( created . status , 201 ) ;
const custom = CatalogResponseSchema . parse (
await ( await ordinary . request ( ` /resource-catalog/ ${ company } ` ) ) . json ( )
) . items . find ( ( item ) = > item . values . name === "Aplicación propia R2.5" ) ;
assert . ok ( custom ) ;
const customId = await local ( company , custom . id , "Aplicación propia elegible" ) ;
assert . equal (
(
await ordinary . request (
path ,
{ values : { . . . input , resourceId : own } } ,
{ contract : null }
)
) . status ,
201
) ;
assert . equal (
(
await ordinary . request (
path ,
{ values : { . . . input , resourceId : customId } } ,
{ contract : null }
)
) . status ,
201
) ;
assert . equal ( ( await ordinary . request ( path , undefined , { contract : null } ) ) . status , 409 ) ;
2026-10-25 19:39:06 +00:00
assert . equal ( ( await ordinary . request ( path , undefined , { contract : "3" } ) ) . status , 200 ) ;
assert . equal ( ( await ordinary . request ( path , undefined , { contract : "4" } ) ) . status , 400 ) ;
2026-10-24 23:19:17 +00:00
assert . equal (
(
await ordinary . request (
` ${ path } / ${ first . id } /update ` ,
{ values : first.values } ,
{ contract : null }
)
) . status ,
409
) ;
assert . equal (
( await ordinary . request ( ` ${ path } / ${ first . id } /delete ` , { } , { contract : null } ) ) . status ,
409
) ;
assert . equal (
(
await ordinary . request (
path ,
{
values : {
. . . input ,
profileId : volume.profileIds [ 2 ] ,
resourceId : global.id.toUpperCase ( ) ,
} ,
} ,
{ contract : null }
)
) . status ,
409
) ;
assert . equal (
(
await ordinary . request ( ` ${ path } / ${ first . id . toUpperCase ( ) } /update ` , {
values : { . . . first . values , resourceId : global.id.toUpperCase ( ) } ,
} )
) . status ,
200
) ;
}
) ;
await t . test (
"candidatos de perfil mixtos sin SO/licencias, proyección privada y cursor por propósito" ,
async ( ) = > {
for ( let index = 0 ; index < 25 ; index ++ ) {
await product ( ` Ágil global de perfil ${ index } ` , index % 5 !== 0 ) ;
}
let cursor : string | null = null ;
const ids = new Set < string > ( ) ;
const scopes = new Set < string > ( ) ;
do {
const response = await ordinary . request (
` /resource-application-candidates/ ${ company } ?purpose=application-configuration&search=agil&pageSize=7 ${ cursor ? ` &cursor= ${ encodeURIComponent ( cursor ) } ` : "" } `
) ;
assert . equal ( response . status , 200 ) ;
const page = ListApplicationCandidatesResponseSchema . parse ( await response . json ( ) ) ;
assert . equal ( page . purpose , "application-configuration" ) ;
for ( const item of page . items ) {
assert . equal ( item . kind , "application" ) ;
assert . equal ( item . active , true ) ;
assert . equal ( ids . has ( item . id ) , false ) ;
ids . add ( item . id ) ;
scopes . add ( item . scope ) ;
for ( const key of [
"notes" ,
"history" ,
"actorId" ,
"profiles" ,
"installations" ,
"characteristics" ,
] ) {
assert . equal ( Object . hasOwn ( item , key ) , false ) ;
}
}
cursor = page . nextCursor ;
} while ( cursor ) ;
assert . deepEqual ( [ . . . scopes ] . sort ( ) , [ "company" , "global" ] ) ;
assert . equal ( ids . size , 72 ) ;
const caps = ApplicationReferenceCapabilitiesSchema . parse (
await (
await ordinary . request ( ` /resource-application-candidates/ ${ company } /capabilities ` )
) . json ( )
) ;
assert . equal ( caps . profileAssociation , true ) ;
assert . equal ( caps . softwareAssociation , false ) ;
assert . equal ( caps . softwareSelection , false ) ;
assert . equal (
(
await ordinary . request ( ` /software-installations/ ${ company } ` , {
values : {
assetId : host ,
resourceId : global.id ,
licenseResourceId : null ,
version : null ,
state : "pending" ,
notes : null ,
} ,
} )
) . status ,
409
) ;
}
) ;
await t . test (
"edición semántica, historial y UUID preservados tras renombrar/desactivar; notas y retirada" ,
async ( ) = > {
const snapshot = first . history ;
const unchanged = ApplicationConfigurationResponseSchema . parse (
await (
await ordinary . request ( ` ${ path } / ${ first . id } /update ` , { values : first.values } )
) . json ( )
) . configuration ;
assert . deepEqual ( unchanged . history , first . history ) ;
const updated = await ordinary . request ( ` ${ path } / ${ first . id } /update ` , {
values : { . . . input , version : "124" , state : "configured" } ,
} ) ;
assert . equal ( updated . status , 200 ) ;
first = ApplicationConfigurationResponseSchema . parse ( await updated . json ( ) ) . configuration ;
assert . equal ( first . history . length , 2 ) ;
assert . deepEqual ( first . history . slice ( 0 , 1 ) , snapshot ) ;
assert . equal (
(
await admin . request ( ` /resource-global-applications/ ${ global . id } /update ` , {
values : { . . . global . values , name : "Ágil renombrada R2.5" } ,
} )
) . status ,
200
) ;
assert . equal (
(
await admin . request ( ` /resource-global-applications/ ${ global . id } /status ` , {
active : false ,
} )
) . status ,
200
) ;
const before = ApplicationConfigurationsResponseSchema . parse (
await ( await ordinary . request ( path ) ) . json ( )
) . configurations . find ( ( item ) = > item . id === first . id ) ;
assert . ok ( before ) ;
assert . equal ( before . needsReview , true ) ;
assert . deepEqual ( before . history , first . history ) ;
assert . equal (
(
await ordinary . request ( ` ${ path } / ${ first . id } /update ` , {
values : { . . . first . values , version : "125" } ,
} )
) . status ,
409
) ;
const notes = await ordinary . request ( ` ${ path } / ${ first . id } /update ` , {
values : { . . . first . values , notes : "Revisión documentada" } ,
} ) ;
assert . equal ( notes . status , 200 ) ;
first = ApplicationConfigurationResponseSchema . parse ( await notes . json ( ) ) . configuration ;
const retirement = await ordinary . request ( ` ${ path } / ${ first . id } /update ` , {
values : { . . . first . values , state : "removal_pending" } ,
} ) ;
assert . equal ( retirement . status , 200 ) ;
first = ApplicationConfigurationResponseSchema . parse ( await retirement . json ( ) ) . configuration ;
assert . equal ( first . values . resourceId , global . id ) ;
assert . equal ( first . values . version , "124" ) ;
const otherConfigurations = ApplicationConfigurationsResponseSchema . parse (
await ( await ordinary . request ( ` /application-configurations/ ${ other } ` ) ) . json ( )
) ;
assert . equal ( otherConfigurations . configurations [ 0 ] ? . history . length , 1 ) ;
const resolver = await ordinary . request (
` /resource-application-references/ ${ company } /resolve ` ,
{ purpose : "application-configuration" , ids : [ global . id ] }
) ;
assert . equal ( resolver . status , 200 ) ;
assert . match ( await resolver . text ( ) , /Ágil renombrada/ ) ;
}
) ;
await t . test ( "carrera: configuración primero, desactivación espera el commit" , async ( ) = > {
const target = await product ( "Carrera perfil primero" ) ;
const arrived = latch ( ) ;
const release = latch ( ) ;
database . addHook ( "afterQuery" , "r25-create" , async ( _options , query ) = > {
const sql : unknown = Reflect . get ( query , "sql" ) ;
if ( typeof sql === "string" && sql . startsWith ( "INSERT INTO application_configurations" ) ) {
arrived . release ( ) ;
await release . promise ;
}
} ) ;
const configuring = ordinary . request ( path , { values : { . . . input , resourceId : target.id } } ) ;
let disabling : Promise < Response > | undefined ;
try {
await waitBarrier ( arrived . promise ) ;
disabling = admin . request ( ` /resource-global-applications/ ${ target . id } /status ` , {
active : false ,
} ) ;
await waitCatalogLock ( process . env . METIS_RESOURCE_SCOPE_DISPOSABLE ? ? "" ) ;
release . release ( ) ;
assert . equal ( ( await configuring ) . status , 201 ) ;
assert . equal ( ( await disabling ) . status , 200 ) ;
const read = ApplicationConfigurationsResponseSchema . parse (
await ( await ordinary . request ( path ) ) . json ( )
) . configurations . find ( ( item ) = > item . values . resourceId === target . id ) ;
assert . ok ( read ) ;
assert . equal ( read . needsReview , true ) ;
races . push ( "configuration-before-deactivation" ) ;
} finally {
release . release ( ) ;
database . removeHook ( "afterQuery" , "r25-create" ) ;
await Promise . allSettled ( [ configuring , . . . ( disabling ? [ disabling ] : [ ] ) ] ) ;
}
} ) ;
await t . test (
"carrera: desactivación primero, revalidación posterior rechaza sin crear revisión" ,
async ( ) = > {
const target = await product ( "Carrera desactivación perfil" ) ;
const arrived = latch ( ) ;
const release = latch ( ) ;
database . addHook ( "afterQuery" , "r25-status" , async ( _options , query ) = > {
const sql : unknown = Reflect . get ( query , "sql" ) ;
if (
typeof sql === "string" &&
sql . startsWith ( "INSERT INTO `resources`" ) &&
sql . includes ( target . id )
) {
arrived . release ( ) ;
await release . promise ;
}
} ) ;
const disabling = admin . request ( ` /resource-global-applications/ ${ target . id } /status ` , {
active : false ,
} ) ;
let configuring : Promise < Response > | undefined ;
try {
await waitBarrier ( arrived . promise ) ;
configuring = ordinary . request ( path , { values : { . . . input , resourceId : target.id } } ) ;
await waitCatalogLock ( process . env . METIS_RESOURCE_SCOPE_DISPOSABLE ? ? "" ) ;
release . release ( ) ;
assert . equal ( ( await disabling ) . status , 200 ) ;
assert . equal ( ( await configuring ) . status , 409 ) ;
assert . equal (
(
await database . query (
"SELECT id FROM application_configurations WHERE resourceId=:id" ,
{ replacements : { id : target.id } , type : QueryTypes . SELECT }
)
) . length ,
0
) ;
assert . equal (
(
await database . query (
"SELECT id FROM application_configuration_revisions WHERE resourceId=:id" ,
{ replacements : { id : target.id } , type : QueryTypes . SELECT }
)
) . length ,
0
) ;
races . push ( "deactivation-before-configuration" ) ;
} finally {
release . release ( ) ;
database . removeHook ( "afterQuery" , "r25-status" ) ;
await Promise . allSettled ( [ disabling , . . . ( configuring ? [ configuring ] : [ ] ) ] ) ;
}
}
) ;
await t . test (
"concurrencia de la pareja: un único registro abierto y revisiones propias" ,
async ( ) = > {
const target = await product ( "Concurrencia pareja de perfil" ) ;
const results = await Promise . all ( [
ordinary . request ( path , { values : { . . . input , resourceId : target.id } } ) ,
ordinary . request ( path , { values : { . . . input , resourceId : target.id } } ) ,
] ) ;
assert . deepEqual ( results . map ( ( result ) = > result . status ) . sort ( ) , [ 201 , 409 ] ) ;
assert . equal (
(
await database . query (
"SELECT id FROM application_configurations WHERE profileId=:profileId AND resourceId=:resourceId" ,
{ replacements : { profileId : a , resourceId : target.id } , type : QueryTypes . SELECT }
)
) . length ,
1
) ;
}
) ;
await t . test (
"volumen de cincuenta configuraciones preserva aislamiento por perfil" ,
async ( ) = > {
for ( let index = 0 ; index < 50 ; index ++ ) {
const id = volume . profileIds [ index ] ;
const resourceId = locals [ index ] ;
assert . ok ( id && resourceId ) ;
await save ( { . . . input , profileId : id , resourceId , version : ` Perfil- ${ index + 1 } ` } ) ;
}
const listed = ApplicationConfigurationsResponseSchema . parse (
await ( await ordinary . request ( path ) ) . json ( )
) ;
assert . ok ( listed . configurations . length >= 50 ) ;
assert . ok ( listed . configurations . every ( ( item ) = > item . companyId === company ) ) ;
}
) ;
await t . test (
"gates independientes y apagado: lectores, notas, retirada y locales siguen funcionando" ,
async ( ) = > {
server . close ( ) ;
await once ( server , "close" ) ;
runtime . stop ( ) ;
runtime = await createIdentityRuntime (
database ,
readDatabaseEnvironment ( {
. . . process . env ,
RESOURCE_GLOBAL_CATALOG_ENABLED : "true" ,
RESOURCE_GLOBAL_SOFTWARE_ENABLED : "true" ,
RESOURCE_GLOBAL_SOFTWARE_CANDIDATES_ENABLED : "true" ,
RESOURCE_GLOBAL_PROFILE_ENABLED : "false" ,
} )
) ;
server = createApp ( ( ) = > undefined , runtime ) . listen ( address . port , "127.0.0.1" ) ;
await once ( server , "listening" ) ;
const caps = ApplicationReferenceCapabilitiesSchema . parse (
await (
await ordinary . request ( ` /resource-application-candidates/ ${ company } /capabilities ` )
) . json ( )
) ;
assert . equal ( caps . profileAssociation , false ) ;
assert . equal ( caps . softwareAssociation , true ) ;
const target = await product ( "Gates independientes R2.5" ) ;
assert . equal (
( await ordinary . request ( path , { values : { . . . input , resourceId : target.id } } ) ) . status ,
409
) ;
assert . equal (
(
await ordinary . request ( ` /software-installations/ ${ company } ` , {
values : {
assetId : host ,
resourceId : target.id ,
licenseResourceId : null ,
version : "R2.4" ,
state : "configured" ,
notes : null ,
} ,
} )
) . status ,
201
) ;
const read = ApplicationConfigurationsResponseSchema . parse (
await ( await ordinary . request ( path ) ) . json ( )
) . configurations . find ( ( item ) = > item . id === first . id ) ;
assert . ok ( read ) ;
assert . equal ( read . values . resourceId , global . id ) ;
assert . equal (
(
await ordinary . request ( ` ${ path } / ${ first . id } /update ` , {
values : { . . . read . values , notes : "Notas tras apagado" } ,
} )
) . status ,
200
) ;
assert . equal (
(
await ordinary . request ( ` ${ path } / ${ first . id } /update ` , {
values : { . . . read . values , state : "removed" } ,
} )
) . status ,
200
) ;
const candidates = ListApplicationCandidatesResponseSchema . parse (
await (
await ordinary . request (
` /resource-application-candidates/ ${ company } ?purpose=application-configuration `
)
) . json ( )
) ;
assert . ok ( candidates . items . every ( ( item ) = > item . scope === "company" ) ) ;
assert . equal (
(
await ordinary . request (
path ,
{ values : { . . . input , profileId : a2 , resourceId : own } } ,
{ contract : null }
)
) . status ,
201
) ;
assert . equal ( ( await ordinary . request ( ` ${ path } / ${ first . id } /delete ` , { } ) ) . status , 200 ) ;
server . close ( ) ;
await once ( server , "close" ) ;
runtime . stop ( ) ;
runtime = await createIdentityRuntime (
database ,
readDatabaseEnvironment ( {
. . . process . env ,
RESOURCE_GLOBAL_CATALOG_ENABLED : "false" ,
RESOURCE_GLOBAL_SOFTWARE_ENABLED : "true" ,
RESOURCE_GLOBAL_PROFILE_ENABLED : "true" ,
} )
) ;
server = createApp ( ( ) = > undefined , runtime ) . listen ( address . port , "127.0.0.1" ) ;
await once ( server , "listening" ) ;
const closed = ApplicationReferenceCapabilitiesSchema . parse (
await (
await ordinary . request ( ` /resource-application-candidates/ ${ company } /capabilities ` )
) . json ( )
) ;
assert . equal ( closed . profileAssociation , false ) ;
assert . equal ( closed . softwareAssociation , false ) ;
assert . equal ( ( await ordinary . request ( path ) ) . status , 200 ) ;
}
) ;
await writeScopeEvidence ( "profile-results.json" , {
companies : 15 ,
principal : {
people : 50 ,
assets : 50 ,
profiles : 50 ,
workstations : 50 ,
localResourcesAtLeast : 50 ,
configurationsAtLeast : 50 ,
} ,
races ,
softwareAndProfileIndependent : true ,
migrationsAdded : false ,
} ) ;
await writeScopeEvidence (
"profile-foreign-keys.json" ,
await database . query (
"SELECT TABLE_NAME,COLUMN_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN ('application_configurations','application_configuration_revisions') AND REFERENCED_TABLE_NAME IS NOT NULL ORDER BY TABLE_NAME,COLUMN_NAME" ,
{ type : QueryTypes . SELECT }
)
) ;
} finally {
server . close ( ) ;
await once ( server , "close" ) ;
runtime . stop ( ) ;
await database . close ( ) ;
}
} ) ;