@@ -1365,12 +1365,54 @@ describe('ADR-0131 D10 --apply — a customization conflict resolved by --metada
13651365 } ) ;
13661366 expect ( asked ) . toEqual ( [ [ 'view' , 'deal_list' , null ] ] ) ;
13671367 expect ( step ( report ) . status ) . toBe ( 'blocked' ) ;
1368- expect ( step ( report ) . blockers . join ( '\n' ) ) . toMatch ( / i s l o c k e d \( _ l o c k = f u l l : s h i p p e d l o c k e d \) .* N o t h i n g w a s d e l e t e d / s) ;
1368+ expect ( step ( report ) . blockers . join ( '\n' ) ) . toMatch ( / i s l o c k e d \( _ l o c k = f u l l : s h i p p e d l o c k e d \) .* N o t h i n g w a s w r i t t e n o r d e l e t e d / s) ;
13691369 expect ( labelOf ( 'md_env' ) ) . toBe ( 'Env list' ) ;
13701370 expect ( deletes ( ) ) . toEqual ( [ ] ) ;
13711371 } ) ;
13721372 } ) ;
13731373
1374+ it ( '⭐ the lock is asked before the history fold and the promotion: under a wall, a refusal leaves history and rows as they were' , async ( ) => {
1375+ metadataTable ( [
1376+ md ( 'md_org' , 'org_default' , 'view' , 'deal_list' , { name : 'deal_list' , label : 'Org list' } ) ,
1377+ md ( 'md_env' , null , 'view' , 'deal_list' , { name : 'deal_list' , label : 'Env list' } ) ,
1378+ md ( 'md_lone' , 'org_default' , 'dashboard' , 'sales' , { name : 'sales' } ) ,
1379+ ] . join ( ', ' ) ) ;
1380+ db . exec ( `
1381+ CREATE TABLE sys_metadata_history (id TEXT PRIMARY KEY, organization_id TEXT, type TEXT, name TEXT,
1382+ version INTEGER, event_seq INTEGER, checksum TEXT);
1383+ INSERT INTO sys_metadata_history VALUES
1384+ ('h_env', NULL, 'view', 'deal_list', 1, 1, 'e1'),
1385+ ('h_org1', 'org_default', 'view', 'deal_list', 1, 1, 'o1'), ('h_org2', 'org_default', 'view', 'deal_list', 2, 2, 'o2');
1386+ ` ) ;
1387+ const history = rows ( 'SELECT * FROM sys_metadata_history ORDER BY id' ) ;
1388+ const report = await apply ( storingDoor ( catalog ( ) ) , ledger ( ) , {
1389+ posture : 'isolated' ,
1390+ metadataChoices : [ 'md_org' ] ,
1391+ columnDrops : { drop : async ( columns ) => columns . map ( ( { table, column } ) => ( { table, column, outcome : 'not-proposed' as const } ) ) } ,
1392+ lock : { verdict : async ( type ) => ( type === 'view' ? { editable : false , lock : 'full' } : { editable : true } ) } ,
1393+ } ) ;
1394+ expect ( step ( report ) . status ) . toBe ( 'blocked' ) ;
1395+ expect ( step ( report ) . blockers . join ( '\n' ) ) . toMatch ( / v i e w d e a l _ l i s t c o u l d n o t t a k e t h e b o d y .* N o t h i n g w a s w r i t t e n o r d e l e t e d / s) ;
1396+ // No fold, no promotion, no write: history and both rows of the key are as they were.
1397+ expect ( writes . filter ( ( w ) => / s y s _ m e t a d a t a / . test ( w ) ) ) . toEqual ( [ ] ) ;
1398+ expect ( rows ( 'SELECT * FROM sys_metadata_history ORDER BY id' ) ) . toEqual ( history ) ;
1399+ expect ( owners ( ) ) . toEqual ( [ [ 'md_env' , null ] , [ 'md_lone' , 'org_default' ] , [ 'md_org' , 'org_default' ] ] ) ;
1400+ expect ( labelOf ( 'md_env' ) ) . toBe ( 'Env list' ) ;
1401+ } ) ;
1402+
1403+ it ( 'the door save after the in-place write sends the row as written, its stored lock family kept' , async ( ) => {
1404+ metadataTable ( [
1405+ md ( 'md_org' , 'org_default' , 'view' , 'crm_lead.intake' , formView ( true , 'Org copy' ) ) ,
1406+ md ( 'md_other' , 'org_b' , 'view' , 'crm_lead.intake' , formView ( false , 'Other copy' ) ) ,
1407+ md ( 'md_env' , null , 'view' , 'crm_lead.intake' , { ...formView ( true , 'Env copy' ) , _lock : 'customize' } ) ,
1408+ ] . join ( ', ' ) ) ;
1409+ const c = storingDoor ( catalog ( ) ) ;
1410+ const report = await apply ( c , ledger ( ) , { views : servedViews ( c , [ ] ) , metadataChoices : [ 'md_org' ] } ) ;
1411+ expect ( step ( report ) . status ) . toBe ( 'done' ) ;
1412+ expect ( c . viewSaves . at ( - 1 ) ! . body ) . toMatchObject ( { label : 'Org copy' , _lock : 'customize' } ) ;
1413+ expect ( ( c . viewSaves . at ( - 1 ) ! . body . config as any ) . sharing . enabled ) . toBe ( false ) ;
1414+ } ) ;
1415+
13741416 it ( 'two conflicts of one item that differ only by bundle member are two conflicts, each chosen for' , async ( ) => {
13751417 db . exec ( `
13761418 CREATE TABLE sys_metadata (id TEXT PRIMARY KEY, organization_id TEXT, type TEXT, name TEXT, state TEXT,
@@ -1775,7 +1817,8 @@ describe('ADR-0131 D10 --apply — history renumbering (seat answers 6162538253,
17751817 // environment scope (NULL is distinct), and no layout can move them.
17761818 viewWithHistory (
17771819 `('md_env', NULL, 'object', 'deal', 'active', NULL, NULL, 1, '{"name":"deal"}')` ,
1778- `('h_e1', NULL, 'object', 'deal', 1, 7, 'e1'), ('h_e2', NULL, 'object', 'deal', 2, 7, 'e2')` ,
1820+ `('h_e1', NULL, 'object', 'deal', 1, 7, 'e1'), ('h_e2', NULL, 'object', 'deal', 2, 7, 'e2'),
1821+ ('h_v1', NULL, 'object', 'account', 3, 8, 'v1'), ('h_v2', NULL, 'object', 'account', 3, 9, 'v2')` ,
17791822 ) ;
17801823 const drops : string [ ] [ ] = [ ] ;
17811824 const report = await apply ( catalog ( ) , ledger ( ) , {
@@ -1788,7 +1831,16 @@ describe('ADR-0131 D10 --apply — history renumbering (seat answers 6162538253,
17881831 } ) ;
17891832 const renumber = report . steps . find ( ( s ) => s . step === 'history-renumber' ) ! ;
17901833 expect ( renumber . status ) . toBe ( 'blocked' ) ;
1791- expect ( renumber . blockers . join ( '\n' ) ) . toMatch ( / e v e n t _ s e q i s n o t u n i q u e e n v i r o n m e n t - w i d e : 7 \( 2 r o w s \) / ) ;
1834+ // The refusal names the table, each item holding the number, and the remedy.
1835+ expect ( renumber . blockers ) . toContainEqual (
1836+ 'sys_metadata_history: event_seq is not unique environment-wide — event_seq 7: object deal (row h_e1), object deal ' +
1837+ '(row h_e2). The ceremony never renumbers history a database numbered twice: the organization_id column is not ' +
1838+ 'dropped until every event has its own number. Remedy: give each of these rows a number no other row holds (or ' +
1839+ 'remove the duplicate), then re-run --apply.' ,
1840+ ) ;
1841+ expect ( renumber . blockers ) . toContainEqual ( expect . stringMatching (
1842+ / ^ s y s _ m e t a d a t a _ h i s t o r y : a v e r s i o n o f a n i t e m i s h e l d m o r e t h a n o n c e — o b j e c t a c c o u n t v e r s i o n 3 \( 2 r o w s \) \. .* R e m e d y : g i v e e a c h o f t h e s e r o w s a v e r s i o n n o o t h e r r o w o f t h e i t e m h o l d s / ,
1843+ ) ) ;
17921844 expect ( report . steps . find ( ( s ) => s . step === 'column-drops' ) ! . status ) . toBe ( 'not-reached' ) ;
17931845 expect ( drops ) . toEqual ( [ ] ) ;
17941846 } ) ;
0 commit comments