@@ -612,93 +612,116 @@ async function bootWithOverlays(
612612}
613613
614614describe ( '[#23074] the artifact envelope is stamped only on the member the package ships' , ( ) => {
615- it ( 'the boot hydration: an unshipped member\'s overlay registers as the tenant row it is; CONTROL the shipped member\'s wears its artifact\'s envelope ' , async ( ) => {
615+ it ( 'the boot hydration: an unshipped member\'s overlay registers as the tenant row it is' , async ( ) => {
616616 const { engine } = await bootWithOverlays ( new Map ( ) , DIGEST ) ;
617617 const zh = engine . registry . getItem < any > ( T , DIGEST , undefined , 'zh-CN' ) ;
618618 expect ( zh ?. subject ) . toBe ( `ADMIN ${ DIGEST } zh-CN` ) ;
619619 expect ( protectionOf ( zh ) ) . toEqual ( TENANT ) ;
620620 expect ( isCodeArtifactBody ( zh ) ) . toBe ( false ) ;
621621 // The package ships no `zh-CN` member, and the overlay is not one.
622622 expect ( engine . registry . getArtifactItem ( T , DIGEST , undefined , 'zh-CN' ) ) . toBeUndefined ( ) ;
623- // CONTROL — the bundle's canonical member, which the package ships.
623+ } ) ;
624+
625+ it ( 'CONTROL the boot hydration: an overlay of a shipped member wears its artifact\'s envelope' , async ( ) => {
626+ // The bundle's canonical member, beside the unshipped one.
627+ const { engine } = await bootWithOverlays ( new Map ( ) , DIGEST ) ;
624628 const en = engine . registry . getItem < any > ( T , DIGEST , undefined , 'en-US' ) ;
625629 expect ( en ?. subject ) . toBe ( `ADMIN ${ DIGEST } en-US` ) ;
626630 expect ( protectionOf ( en ) ) . toEqual ( PACKAGED ) ;
627631 expect ( isCodeArtifactBody ( en ) ) . toBe ( true ) ;
628-
629- // CONTROL — a non-canonical member the package ships.
632+ // A non-canonical member the package ships.
630633 const shipped = ( await bootWithOverlays ( new Map ( ) , NAME ) ) . engine ;
631- const shippedZh = shipped . registry . getItem < any > ( T , NAME , undefined , 'zh-CN' ) ;
632- expect ( shippedZh ?. subject ) . toBe ( `ADMIN ${ NAME } zh-CN` ) ;
633- expect ( protectionOf ( shippedZh ) ) . toEqual ( PACKAGED ) ;
634- expect ( isCodeArtifactBody ( shippedZh ) ) . toBe ( true ) ;
634+ const zh = shipped . registry . getItem < any > ( T , NAME , undefined , 'zh-CN' ) ;
635+ expect ( zh ?. subject ) . toBe ( `ADMIN ${ NAME } zh-CN` ) ;
636+ expect ( protectionOf ( zh ) ) . toEqual ( PACKAGED ) ;
637+ expect ( isCodeArtifactBody ( zh ) ) . toBe ( true ) ;
635638 expect ( shipped . registry . getArtifactItem < any > ( T , NAME , undefined , 'zh-CN' ) ?. subject ) . toBe ( 'PKG zh' ) ;
636639 } ) ;
637640
638- it ( 'the by-name read (?member=): an unshipped member is served as the environment\'s item; CONTROL the shipped member under its package ' , async ( ) => {
641+ it ( 'the by-name read (?member=): an unshipped member is served as the environment\'s item' , async ( ) => {
639642 const { protocol } = await bootWithOverlays ( new Map ( ) , DIGEST ) ;
640643 const zh : any = await protocol . getMetaItem ( { type : T , name : DIGEST , member : 'zh-CN' } ) ;
641644 expect ( zh . item . subject ) . toBe ( `ADMIN ${ DIGEST } zh-CN` ) ;
642645 expect ( protectionOf ( zh . item ) ) . toEqual ( { _packageId : undefined , _packageVersion : undefined , _provenance : undefined } ) ;
643646 expect ( isCodeArtifactBody ( zh . item ) ) . toBe ( false ) ;
644647 expect ( [ zh . provenance , zh . packageId , zh . packageVersion ] ) . toEqual ( [ undefined , undefined , undefined ] ) ;
645648 expect ( zh ) . toMatchObject ( { lock : 'none' , editable : true , deletable : true } ) ;
649+ } ) ;
646650
647- const shipped = ( await bootWithOverlays ( new Map ( ) , NAME ) ) . protocol ;
648- const shippedZh : any = await shipped . getMetaItem ( { type : T , name : NAME , member : 'zh-CN' } ) ;
649- expect ( shippedZh . item . subject ) . toBe ( `ADMIN ${ NAME } zh-CN` ) ;
650- expect ( protectionOf ( shippedZh . item ) ) . toEqual ( PACKAGED ) ;
651- expect ( shippedZh ) . toMatchObject ( {
651+ it ( 'CONTROL the by-name read (?member=): a shipped member is served under its package' , async ( ) => {
652+ const { protocol } = await bootWithOverlays ( new Map ( ) , NAME ) ;
653+ const zh : any = await protocol . getMetaItem ( { type : T , name : NAME , member : 'zh-CN' } ) ;
654+ expect ( zh . item . subject ) . toBe ( `ADMIN ${ NAME } zh-CN` ) ;
655+ expect ( protectionOf ( zh . item ) ) . toEqual ( PACKAGED ) ;
656+ expect ( zh ) . toMatchObject ( {
652657 provenance : 'package' , packageId : PKG , packageVersion : '1.0.0' , lock : 'none' , editable : true , deletable : true ,
653658 } ) ;
654659 } ) ;
655660
656- it ( 'the list, served and for execution: an unshipped member is listed as the environment\'s item; CONTROL the shipped members under their package' , async ( ) => {
657- const unshipped = ( await bootWithOverlays ( new Map ( ) , DIGEST ) ) . protocol ;
658- const shipped = ( await bootWithOverlays ( new Map ( ) , NAME ) ) . protocol ;
661+ /** Each listed member of `name` by locale, from the served list or the execution list. */
662+ const listedMembers = async ( protocol : ObjectStackProtocolImplementation , audience : 'served' | 'execution' , name : string ) => {
663+ const res : any = audience === 'served'
664+ ? await protocol . getMetaItems ( { type : T } )
665+ : await protocol . getMetaItemsForExecution ( { type : T } ) ;
666+ return new Map < string , any > ( ( ( res ?. items ?? [ ] ) as any [ ] ) . filter ( ( it ) => it ?. name === name ) . map ( ( it ) => [ String ( it . locale ) , it ] ) ) ;
667+ } ;
668+
669+ it ( 'the list, served and for execution: an unshipped member is listed as the environment\'s item' , async ( ) => {
670+ const { protocol } = await bootWithOverlays ( new Map ( ) , DIGEST ) ;
659671 for ( const audience of [ 'served' , 'execution' ] as const ) {
660- const list = async ( protocol : ObjectStackProtocolImplementation ) => ( ( ( audience === 'served'
661- ? await protocol . getMetaItems ( { type : T } )
662- : await protocol . getMetaItemsForExecution ( { type : T } ) ) as any ) . items ?? [ ] ) as any [ ] ;
663- const member = ( items : any [ ] , name : string , locale : string ) =>
664- items . find ( ( it ) => it ?. name === name && it ?. locale === locale ) ;
665- const items = await list ( unshipped ) ;
666- const zh = member ( items , DIGEST , 'zh-CN' ) ;
672+ const zh = ( await listedMembers ( protocol , audience , DIGEST ) ) . get ( 'zh-CN' ) ;
667673 expect ( zh ?. subject , audience ) . toBe ( `ADMIN ${ DIGEST } zh-CN` ) ;
668674 expect ( protectionOf ( zh ) , audience ) . toEqual ( { _packageId : undefined , _packageVersion : undefined , _provenance : undefined } ) ;
669- expect ( protectionOf ( member ( items , DIGEST , 'en-US' ) ) , audience ) . toEqual ( PACKAGED ) ;
670- expect ( protectionOf ( member ( await list ( shipped ) , NAME , 'zh-CN' ) ) , audience ) . toEqual ( PACKAGED ) ;
671675 }
672676 } ) ;
673677
674- it ( 'the reset (?member=): an unshipped member is retired by the overlay-entry tier; CONTROL the shipped member is un-shadowed onto its artifact' , async ( ) => {
675- // The registry's two heal verbs over the hydrated entries, as the
676- // delete's heal (`restoreArtifactRegistryView`) calls them.
677- const unshipped = ( await bootWithOverlays ( new Map ( ) , DIGEST ) ) . engine ;
678- expect ( unshipped . registry . removeRuntimeShadow ( T , DIGEST , 'zh-CN' ) ) . toBe ( false ) ;
679- expect ( unshipped . registry . removeOverlayEntry ( T , DIGEST , 'zh-CN' ) ) . toBe ( true ) ;
680- expect ( unshipped . registry . getItem ( T , DIGEST , undefined , 'zh-CN' ) ) . toBeUndefined ( ) ;
681- expect ( unshipped . registry . getItem < any > ( T , DIGEST , undefined , 'en-US' ) ?. subject ) . toBe ( `ADMIN ${ DIGEST } en-US` ) ;
682-
683- const shipped = ( await bootWithOverlays ( new Map ( ) , NAME ) ) . engine ;
684- expect ( shipped . registry . removeOverlayEntry ( T , NAME , 'zh-CN' ) ) . toBe ( false ) ;
685- expect ( shipped . registry . removeRuntimeShadow ( T , NAME , 'zh-CN' ) ) . toBe ( true ) ;
686- expect ( shipped . registry . getItem < any > ( T , NAME , undefined , 'zh-CN' ) ?. subject ) . toBe ( 'PKG zh' ) ;
687- expect ( shipped . registry . getItem < any > ( T , NAME , undefined , 'en-US' ) ?. subject ) . toBe ( `ADMIN ${ NAME } en-US` ) ;
688-
689- // Through the door, both members, at once and after a restart.
690- for ( const [ name , after ] of [ [ DIGEST , undefined ] , [ NAME , 'PKG zh' ] ] as const ) {
691- const stores = new Map < string , Map < string , Record < string , unknown > > > ( ) ;
692- const { engine, protocol } = await bootWithOverlays ( stores , name ) ;
693- expect ( await protocol . deleteMetaItem ( { type : T , name, member : 'zh-CN' } ) , name ) . toMatchObject ( { success : true } ) ;
694- expect ( engine . registry . getItem < any > ( T , name , undefined , 'zh-CN' ) ?. subject , name ) . toBe ( after ) ;
695- expect ( engine . registry . getItem < any > ( T , name , undefined , 'en-US' ) ?. subject , name ) . toBe ( `ADMIN ${ name } en-US` ) ;
696- expect ( ( ( await protocol . getMetaItem ( { type : T , name, member : 'zh-CN' } ) ) as any ) ?. item ?. subject , name ) . toBe ( after ) ;
697- const restarted = await boot ( stores ) ;
698- expect ( ( ( await restarted . protocol . getMetaItem ( { type : T , name, member : 'zh-CN' } ) ) as any ) ?. item ?. subject , name ) . toBe ( after ) ;
678+ it ( 'CONTROL the list, served and for execution: shipped members are listed under their package' , async ( ) => {
679+ const unshipped = ( await bootWithOverlays ( new Map ( ) , DIGEST ) ) . protocol ;
680+ const shipped = ( await bootWithOverlays ( new Map ( ) , NAME ) ) . protocol ;
681+ for ( const audience of [ 'served' , 'execution' ] as const ) {
682+ expect ( protectionOf ( ( await listedMembers ( unshipped , audience , DIGEST ) ) . get ( 'en-US' ) ) , audience ) . toEqual ( PACKAGED ) ;
683+ const zh = ( await listedMembers ( shipped , audience , NAME ) ) . get ( 'zh-CN' ) ;
684+ expect ( zh ?. subject , audience ) . toBe ( `ADMIN ${ NAME } zh-CN` ) ;
685+ expect ( protectionOf ( zh ) , audience ) . toEqual ( PACKAGED ) ;
699686 }
700687 } ) ;
701688
689+ /**
690+ * A by-name reset of the `zh-CN` member of `name`, through the delete door,
691+ * read back at once and after a restart: `after` is the `zh-CN` subject the
692+ * registry and the by-name read then serve. Before the door, each of the
693+ * registry's two heal verbs that the delete's heal
694+ * (`restoreArtifactRegistryView`) calls is asked about the hydrated entry,
695+ * on a boot of its own.
696+ */
697+ async function resetZh ( name : string , verbs : { shadow : boolean ; overlayEntry : boolean } , after : string | undefined ) {
698+ const shadowBoot = ( await bootWithOverlays ( new Map ( ) , name ) ) . engine ;
699+ expect ( shadowBoot . registry . removeRuntimeShadow ( T , name , 'zh-CN' ) , 'removeRuntimeShadow' ) . toBe ( verbs . shadow ) ;
700+ const overlayEntryBoot = ( await bootWithOverlays ( new Map ( ) , name ) ) . engine ;
701+ expect ( overlayEntryBoot . registry . removeOverlayEntry ( T , name , 'zh-CN' ) , 'removeOverlayEntry' ) . toBe ( verbs . overlayEntry ) ;
702+
703+ const stores = new Map < string , Map < string , Record < string , unknown > > > ( ) ;
704+ const { engine, protocol } = await bootWithOverlays ( stores , name ) ;
705+ expect ( await protocol . deleteMetaItem ( { type : T , name, member : 'zh-CN' } ) ) . toMatchObject ( { success : true } ) ;
706+ expect ( engine . registry . getItem < any > ( T , name , undefined , 'zh-CN' ) ?. subject ) . toBe ( after ) ;
707+ expect ( engine . registry . getItem < any > ( T , name , undefined , 'en-US' ) ?. subject ) . toBe ( `ADMIN ${ name } en-US` ) ;
708+ expect ( ( ( await protocol . getMetaItem ( { type : T , name, member : 'zh-CN' } ) ) as any ) ?. item ?. subject ) . toBe ( after ) ;
709+ const restarted = await boot ( stores ) ;
710+ expect ( ( ( await restarted . protocol . getMetaItem ( { type : T , name, member : 'zh-CN' } ) ) as any ) ?. item ?. subject ) . toBe ( after ) ;
711+ }
712+
713+ it ( 'the reset (?member=): an unshipped member is retired by the overlay-entry tier, and nothing is left serving it' , async ( ) => {
714+ // No `zh-CN` artifact takes its place, so the shadow heal declines and
715+ // the overlay-entry retirement takes the tenant row.
716+ await resetZh ( DIGEST , { shadow : false , overlayEntry : true } , undefined ) ;
717+ } ) ;
718+
719+ it ( 'CONTROL the reset (?member=): a shipped member is un-shadowed onto its artifact' , async ( ) => {
720+ // The shadow heal lifts the entry onto the `zh-CN` artifact, and the
721+ // retirement refuses it as packaged code.
722+ await resetZh ( NAME , { shadow : true , overlayEntry : false } , 'PKG zh' ) ;
723+ } ) ;
724+
702725 it ( 'a registry that answers another member\'s artifact: the graft keeps it off the body' , async ( ) => {
703726 // `lookupArtifactItem`'s note: a registry without the member parameter
704727 // ignores it, so it answers the bundle's artifact canonical-first.
@@ -708,12 +731,12 @@ describe('[#23074] the artifact envelope is stamped only on the member the packa
708731 vi . spyOn ( registry , 'getArtifactItem' ) . mockImplementation ( ( ...args : any [ ] ) => artifactOf ( args [ 0 ] , args [ 1 ] , args [ 2 ] ) ) ;
709732 } ) ;
710733 expect ( engine . registry . getArtifactItem < any > ( T , DIGEST , undefined , 'zh-CN' ) ?. locale ) . toBe ( 'en-US' ) ;
734+ // CONTROL — the canonical member is that artifact's own member, and wears it.
735+ expect ( protectionOf ( engine . registry . getItem ( T , DIGEST , undefined , 'en-US' ) ) ) . toEqual ( PACKAGED ) ;
711736 expect ( protectionOf ( engine . registry . getItem ( T , DIGEST , undefined , 'zh-CN' ) ) ) . toEqual ( TENANT ) ;
712737 const zh : any = await protocol . getMetaItem ( { type : T , name : DIGEST , member : 'zh-CN' } ) ;
713738 expect ( zh . item . _packageId ) . toBeUndefined ( ) ;
714739 expect ( zh . packageId ) . toBeUndefined ( ) ;
715- // CONTROL — the canonical member is that artifact's own member, and wears it.
716- expect ( protectionOf ( engine . registry . getItem ( T , DIGEST , undefined , 'en-US' ) ) ) . toEqual ( PACKAGED ) ;
717740 } ) ;
718741
719742 it ( 'CONTROL: a type with no members keeps its artifact\'s envelope, even where the overlay\'s locale is not the artifact\'s' , async ( ) => {
0 commit comments