@@ -28,7 +28,7 @@ import {
2828 SysMetadataHistoryObject ,
2929} from './metadata/index.js' ;
3030import { SysSetting } from './system/index.js' ;
31- import { SETUP_APP , SETUP_NAV_CONTRIBUTIONS } from './apps/index.js' ;
31+ import { ACCOUNT_APP , SETUP_APP , SETUP_NAV_CONTRIBUTIONS , STUDIO_APP } from './apps/index.js' ;
3232import { AppSchema } from '@objectstack/spec/ui' ;
3333
3434const systemObjects = [
@@ -156,6 +156,24 @@ describe('@objectstack/platform-objects', () => {
156156 } ) ;
157157 } ) ;
158158
159+ describe ( 'platform app protection (ADR-0010 §3.7)' , ( ) => {
160+ // All three platform apps are core UI shipped by this package: a
161+ // tenant overlay that breaks Setup/Studio locks admins/implementers
162+ // out of the repair surface, and Account is every user's only
163+ // self-service security surface. The loader translates `protection`
164+ // into the `_lock` envelope; clients (e.g. objectui's
165+ // isNavigationSyncableApp) rely on `_lock` to skip automatic
166+ // navigation writes into these apps.
167+ it . each ( [
168+ [ 'SETUP_APP' , SETUP_APP ] ,
169+ [ 'STUDIO_APP' , STUDIO_APP ] ,
170+ [ 'ACCOUNT_APP' , ACCOUNT_APP ] ,
171+ ] ) ( '%s declares a full lock' , ( _name , app ) => {
172+ expect ( app . protection ?. lock ) . toBe ( 'full' ) ;
173+ expect ( ( ) => AppSchema . parse ( app ) ) . not . toThrow ( ) ;
174+ } ) ;
175+ } ) ;
176+
159177 describe ( 'SETUP_NAV_CONTRIBUTIONS (ADR-0029 D7)' , ( ) => {
160178 const shellGroupIds = new Set (
161179 ( SETUP_APP . navigation ?? [ ] ) . map ( ( n ) => n . id ) ,
0 commit comments