1414// undid the operator's published change: `200`, and B's member lost it;
1515// - `POST /packages/:id/duplicate` copied the set, under the same name, into
1616// A's own package, and `GET /meta` then served A's copy;
17- // - `POST /packages/:id/revert` discarded the operator's pending draft;
17+ // - `POST /packages/:id/revert` discarded the operator's pending draft
18+ // (`POST /packages/:id/discard-drafts` is the same discard, by a second door);
1819// - `POST /packages/:id/adopt-orphans` moved the environment's catalog rows
1920// into A's package.
2021//
2122// Pinned here, under each walled posture: every one of those answers
2223// `403 PERMISSION_DENIED`, nothing moves, and B's resolution stays. The commit
2324// revert is judged by the commit's own items, whatever package the URL names.
24- // CONTROLS: A runs every one of these doors on its own catalog-free package as
25- // before, and the platform operator runs them on the catalog-carrying one.
26- // And under `single` (CONTROL): the same `manage_metadata` holder runs them on
27- // the operator's package as before.
25+ // CONTROLS: A runs publish-drafts, discard-drafts, revert, rollback, commit
26+ // revert and duplicate on its own catalog-free package as before. Not
27+ // adopt-orphans: that verb reads the environment's orphans, not A's package,
28+ // and this environment carries the operator's catalog orphan. The platform
29+ // operator runs every door on the catalog-carrying package, adopt-orphans
30+ // included. And under `single` (CONTROL): the same `manage_metadata` holder
31+ // runs every door on the operator's package as before.
2832//
2933// The boot is `multiTenant: 'posture-only'`: a real, non-degraded walled
3034// posture. The harness declares the seeded admin as `OS_PLATFORM_OWNER_EMAIL`,
@@ -199,6 +203,14 @@ for (const posture of ['isolated', 'group'] as const) {
199203 expect ( await rowsOf ( h , { package_id : OP_PKG , type : 'permission' , name : OP_SET , state : 'draft' } ) ) . toHaveLength ( 1 ) ;
200204 } ) ;
201205
206+ it ( 'discard-drafts: A discarding the operator\'s pending catalog draft is refused, and the draft stays' , async ( ) => {
207+ const drafted = await call ( h . stack , h . operator , 'PUT' , `/meta/permission/${ OP_SET } ?package=${ OP_PKG } &mode=draft` ,
208+ set ( OP_SET , [ 'manage_users' , 'manage_metadata' ] ) ) ;
209+ expect ( drafted . status , await drafted . clone ( ) . text ( ) ) . toBe ( 200 ) ;
210+ await refused ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ OP_PKG } /discard-drafts` , { } ) ) ;
211+ expect ( await rowsOf ( h , { package_id : OP_PKG , type : 'permission' , name : OP_SET , state : 'draft' } ) ) . toHaveLength ( 1 ) ;
212+ } ) ;
213+
202214 it ( 'rollback: A rolling the operator\'s package back past a catalog commit is refused, and B keeps `manage_users`' , async ( ) => {
203215 const before = await bSnapshot ( ) ;
204216 await refused ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ OP_PKG } /rollback` , { commitId : h . c1 } ) ) ;
@@ -232,7 +244,7 @@ for (const posture of ['isolated', 'group'] as const) {
232244 expect ( env . map ( ( r ) => r . package_id ?? null ) ) . not . toContain ( 'com.w3.a.adopt' ) ;
233245 } ) ;
234246
235- it ( 'CONTROL: A runs every one of these doors on its own catalog-free package as before' , async ( ) => {
247+ it ( 'CONTROL: A runs every door but adopt-orphans on its own catalog-free package as before' , async ( ) => {
236248 const pkg = 'com.w3.a.free' ;
237249 const dash = 'w3_free_dash' ;
238250 const ok = async ( res : Response ) => expect ( res . status , await res . clone ( ) . text ( ) ) . toBe ( 200 ) ;
@@ -247,13 +259,19 @@ for (const posture of ['isolated', 'group'] as const) {
247259 await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ pkg } /rollback` , { commitId : first } ) ) ;
248260 await ok ( await call ( h . stack , h . tokA , 'PUT' , `/meta/dashboard/${ dash } ?package=${ pkg } &mode=draft` , dashboard ( dash , 'v3' ) ) ) ;
249261 await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ pkg } /revert` , { } ) ) ;
262+ await ok ( await call ( h . stack , h . tokA , 'PUT' , `/meta/dashboard/${ dash } ?package=${ pkg } &mode=draft` , dashboard ( dash , 'v4' ) ) ) ;
263+ await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ pkg } /discard-drafts` , { } ) ) ;
264+ expect ( await rowsOf ( h , { package_id : pkg , state : 'draft' } ) ) . toHaveLength ( 0 ) ;
250265 await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ pkg } /duplicate` , { targetPackageId : 'com.w3.a.free.copy' } ) ) ;
251266 } ) ;
252267
253268 it ( 'CONTROL: the platform operator runs every one of these doors on its catalog-carrying package' , async ( ) => {
254269 const ok = async ( res : Response ) => expect ( res . status , await res . clone ( ) . text ( ) ) . toBe ( 200 ) ;
255270 await ok ( await call ( h . stack , h . operator , 'POST' , `/packages/${ OP_PKG } /duplicate` , { targetPackageId : 'com.w3.op.copy' } ) ) ;
256271 await ok ( await call ( h . stack , h . operator , 'POST' , `/packages/${ OP_PKG } /revert` , { } ) ) ;
272+ await ok ( await call ( h . stack , h . operator , 'PUT' , `/meta/permission/${ OP_SET } ?package=${ OP_PKG } &mode=draft` , set ( OP_SET , [ 'manage_metadata' ] ) ) ) ;
273+ await ok ( await call ( h . stack , h . operator , 'POST' , `/packages/${ OP_PKG } /discard-drafts` , { } ) ) ;
274+ expect ( await rowsOf ( h , { package_id : OP_PKG , type : 'permission' , name : OP_SET , state : 'draft' } ) ) . toHaveLength ( 0 ) ;
257275 await ok ( await call ( h . stack , h . operator , 'POST' , `/packages/${ OP_PKG } /commits/${ h . c2 } /revert` , { } ) ) ;
258276 expect ( ( await bGrants ( ) ) . systemPermissions ) . not . toContain ( 'manage_users' ) ;
259277 await ok ( await call ( h . stack , h . operator , 'PUT' , `/meta/permission/${ OP_SET } ?package=${ OP_PKG } &mode=draft` , set ( OP_SET , [ 'manage_users' ] ) ) ) ;
@@ -289,6 +307,8 @@ describe('[ADR-0131 D3 · #15204 W3] single (CONTROL): the refusal is inert', ()
289307 await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ OP_PKG } /rollback` , { commitId : h . c1 } ) ) ;
290308 await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ OP_PKG } /commits/${ h . c1 } /revert` , { } ) ) ;
291309 await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ OP_PKG } /revert` , { } ) ) ;
310+ await ok ( await call ( h . stack , h . operator , 'PUT' , `/meta/permission/${ OP_SET } ?package=${ OP_PKG } &mode=draft` , set ( OP_SET , [ 'manage_metadata' ] ) ) ) ;
311+ await ok ( await call ( h . stack , h . tokA , 'POST' , `/packages/${ OP_PKG } /discard-drafts` , { } ) ) ;
292312 expect ( ( await call ( h . stack , h . tokA , 'POST' , '/packages' , { id : 'com.w3.a.adopt' , name : 'adopt' , version : '1.0.0' , type : 'app' } ) ) . status ) . toBe ( 201 ) ;
293313 await ok ( await call ( h . stack , h . tokA , 'POST' , '/packages/com.w3.a.adopt/adopt-orphans' , { } ) ) ;
294314 } ) ;
0 commit comments