@objectstack/metadata 17.0.0-rc.5 → 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@ import { MetadataFormat, MetadataLoaderContract, MetadataLoadOptions, MetadataLo
3
3
  export { MetadataCollectionInfo, MetadataDiffResult, MetadataFormat, MetadataHistoryQueryOptions, MetadataHistoryQueryResult, MetadataHistoryRecord, MetadataHistoryRetentionPolicy, MetadataLoadOptions, MetadataLoadResult, MetadataLoaderContract, MetadataManagerConfig, MetadataSaveOptions, MetadataSaveResult, MetadataStats, MetadataWatchEvent } from '@objectstack/spec/system';
4
4
  import { IMetadataService, IDataDriver, IDataEngine, IRealtimeService, MetadataWriteOptions, MetadataWatchCallback, MetadataWatchHandle, MetadataExportOptions, MetadataImportOptions, MetadataImportResult, MetadataTypeInfo, ApiEndpointMatch, IPubSub, ISchemaDriver } from '@objectstack/spec/contracts';
5
5
  export { IMetadataService, MetadataExportOptions, MetadataImportOptions, MetadataImportResult, MetadataTypeInfo, MetadataWatchCallback, MetadataWatchHandle } from '@objectstack/spec/contracts';
6
- import { MetadataTypeRegistryEntry, MetadataQuery, MetadataQueryResult, MetadataBulkResult, MetadataOverlay, MetadataValidationResult, MetadataDependency, MetadataPluginConfig } from '@objectstack/spec/kernel';
6
+ import { MetadataTypeRegistryEntryParsed, MetadataQuery, MetadataQueryResult, MetadataBulkResult, MetadataOverlay, MetadataValidationResult, MetadataDependency, MetadataPluginConfig } from '@objectstack/spec/kernel';
7
7
  export { MetadataBulkResult, MetadataDependency, MetadataPluginConfig, MetadataPluginManifest, MetadataQuery, MetadataQueryResult, MetadataType, MetadataTypeRegistryEntry, MetadataValidationResult } from '@objectstack/spec/kernel';
8
8
  import { Logger, Plugin, PluginContext } from '@objectstack/core';
9
9
  import { z } from 'zod';
@@ -191,6 +191,23 @@ interface MetadataLoader {
191
191
  * Watch callback function (legacy)
192
192
  */
193
193
  type WatchCallback = (event: MetadataWatchEvent) => void | Promise<void>;
194
+ /**
195
+ * [#6504] What one `list()` read actually produced: the best-effort set, plus
196
+ * whether assembling it lost a loader.
197
+ *
198
+ * The return of {@link MetadataManager.readListUncached}, the value shared
199
+ * through `inflightListReads`, and — minus the cache bookkeeping — what
200
+ * {@link MetadataManager.listDiagnosed} hands to a caller. One shape for all
201
+ * three on purpose: the verdict used to be dropped at each hop outward
202
+ * (`readListUncached` computed it, the in-flight promise kept only `items`,
203
+ * `list()` returned only that), and a single carried record is what makes
204
+ * losing it again take an edit rather than an omission.
205
+ */
206
+ interface ListReadResult {
207
+ items: unknown[];
208
+ degraded: boolean;
209
+ errors: string[];
210
+ }
194
211
  interface MetadataManagerOptions extends MetadataManagerConfig {
195
212
  loaders?: MetadataLoader[];
196
213
  /** Optional IDataDriver instance. When provided alongside config.datasource, auto-configures DatabaseLoader. */
@@ -270,6 +287,15 @@ declare class MetadataManager implements IMetadataService {
270
287
  * only, so a fresh read that already replaced it keeps its slot. Nothing
271
288
  * accumulates — a wave of callers arriving after settle finds the cache the
272
289
  * settle just wrote, and once that lapses it starts one new read.
290
+ *
291
+ * [#6504] The shared value is the whole {@link ListReadResult}, not just
292
+ * `items`. "Sharers share the outcome" above is stated about the answer *and*
293
+ * its degraded verdict, and while the promise carried only `items` that was
294
+ * true of `list()` alone: a {@link listDiagnosed} caller joining an in-flight
295
+ * read had no way to reach the verdict that read had already computed, and
296
+ * would have had to either re-walk the loaders (defeating this map) or invent
297
+ * a second, unmemoized answer. `list()` narrows to `.items` at its own return
298
+ * instead, so every sharer still receives the same array instance.
273
299
  */
274
300
  private readonly inflightListReads;
275
301
  private readonly loaderReadFailureReported;
@@ -287,7 +313,7 @@ declare class MetadataManager implements IMetadataService {
287
313
  /**
288
314
  * Set the type registry for metadata type discovery.
289
315
  */
290
- setTypeRegistry(entries: MetadataTypeRegistryEntry[]): void;
316
+ setTypeRegistry(entries: MetadataTypeRegistryEntryParsed[]): void;
291
317
  /**
292
318
  * Configure and register a DatabaseLoader for database-backed metadata persistence.
293
319
  * Can be called at any time to enable database storage (e.g. after kernel resolves the driver).
@@ -389,16 +415,30 @@ declare class MetadataManager implements IMetadataService {
389
415
  * has with {@link loadDiagnosed}, so every existing caller keeps its exact
390
416
  * behaviour and only callers that ASK for the verdict pay for it.
391
417
  *
392
- * [#5840] Deliberately NOT expressed as `(await getDiagnosed(…)).data`,
393
- * although that is what it computes. The obvious delegation adds one
394
- * `await` hop, and a registry hit here is observed one microtask sooner than
395
- * it would be through a second async frame — which `register()`'s watchers
396
- * depend on, because `notifyWatchers` does not await its handlers and
397
- * ObjectQL's bridge re-reads through `get()` on the event rather than
398
- * trusting the payload (`register-notifies-watchers.test.ts` pins it, and
399
- * went red on the delegating version). The duplication is three lines and is
400
- * pinned from the other side: `get()` and `getDiagnosed().data` are asserted
401
- * to agree on every case in `metadata-manager-get-diagnosed.test.ts`.
418
+ * Not expressed as `(await getDiagnosed(…)).data`, although that is what it
419
+ * computes and the reason has CHANGED, so do not read the duplication as a
420
+ * standing constraint.
421
+ *
422
+ * [#5840] recorded the delegation as unsafe: it adds one `await` hop, and
423
+ * `register-notifies-watchers.test.ts` went red on the delegating version, so
424
+ * three lines were duplicated to hold the frame count fixed. [#6043] measured
425
+ * that test and found it was pinning this method's microtask depth rather than
426
+ * the ordering guarantee it named `notifyWatchers` never awaits its handlers,
427
+ * so a subscriber's `await get(…)` had simply been settling inside the
428
+ * microtasks `await register(…)` yields. That case now asserts the ordering
429
+ * synchronously against the registry and does not observe this method's frame
430
+ * count at all; the whole `@objectstack/metadata` suite was re-measured on the
431
+ * delegating version and stayed green.
432
+ *
433
+ * What survives is a plain, local reason: the registry hit is the hot path and
434
+ * answering it without a second async frame is worth three lines. Nothing
435
+ * external depends on the hop count any more. Consolidating the two into one
436
+ * delegation is therefore a viable, deliberately un-taken change (#6043 was
437
+ * test-scoped) — if you take it, note that `get()`'s callers outside this
438
+ * package were never surveyed for timing sensitivity, only this package's
439
+ * tests. Either way the two stay pinned to each other from the other side:
440
+ * `get()` and `getDiagnosed().data` are asserted to agree on every case in
441
+ * `metadata-manager-get-diagnosed.test.ts`.
402
442
  */
403
443
  get(type: string, name: string): Promise<unknown | undefined>;
404
444
  /**
@@ -443,6 +483,46 @@ declare class MetadataManager implements IMetadataService {
443
483
  * `listCache`.
444
484
  */
445
485
  list(type: string): Promise<unknown[]>;
486
+ /**
487
+ * `list`, plus whether the answer can be trusted as complete.
488
+ *
489
+ * [#6504] The plural counterpart of {@link getDiagnosed}, and the same defect
490
+ * one read over: `readListUncached` has computed this verdict since #5184 and
491
+ * `list()` spent it entirely on a cache TTL, so a consumer receiving a short
492
+ * set could not ask whether it was short because that is all anyone declared
493
+ * or because a loader was down. {@link reportLoaderReadFailure}'s own message
494
+ * says what that costs — "every list served from now on is a PARTIAL set
495
+ * presented as a complete one, and the server keeps reporting healthy" — and
496
+ * until this member existed that sentence was addressed to a log reader only,
497
+ * because no caller had a way to ask.
498
+ *
499
+ * Sharper than the singular case rather than merely analogous: `list` is the
500
+ * read whose answer carries a **count**, and a consumer restating
501
+ * `items.length` as "this environment contains N items" makes a positive,
502
+ * numeric claim about what an author declared out of a read that partly did
503
+ * not happen.
504
+ *
505
+ * Reads through exactly the same cache and single-flight machinery `list()`
506
+ * does — same entry, same TTLs, same in-flight join — so asking for the
507
+ * verdict costs no extra loader walk, and `list()` and
508
+ * `listDiagnosed().items` cannot drift: they are the same read, narrowed at
509
+ * different points. `degraded` is true when at least one loader threw while
510
+ * this set was assembled; unlike {@link getDiagnosed} it does NOT additionally
511
+ * require that nothing answered, because a plural read that lost one loader is
512
+ * partial even when the others answered plenty — which is the whole fact.
513
+ */
514
+ listDiagnosed(type: string): Promise<ListReadResult>;
515
+ /**
516
+ * The cached / single-flight read behind {@link list} and
517
+ * {@link listDiagnosed}.
518
+ *
519
+ * [#6504] Extracted so the two members are one read seen at two widths rather
520
+ * than two implementations that have to be kept in agreement — the shape
521
+ * `get`/`getDiagnosed` pay for with a duplicated body and a test pinning them
522
+ * to each other. Everything below is unchanged in behaviour from when it was
523
+ * inlined in `list()`; only the verdict now survives the return.
524
+ */
525
+ private readList;
446
526
  /**
447
527
  * Assemble the `list()` answer for `type` from the in-memory registry plus
448
528
  * every loader, reporting (but not rethrowing) loaders that could not be
@@ -502,6 +582,11 @@ declare class MetadataManager implements IMetadataService {
502
582
  * one thing this cache used to throw away. A result assembled while a loader
503
583
  * was unreadable is stored, but stored *as* what it is, so it expires on the
504
584
  * degraded TTL and any reader can tell it apart from a complete answer.
585
+ *
586
+ * [#6504] Takes the whole read result rather than its parts for the same
587
+ * reason: a signature that spreads the verdict across positional arguments is
588
+ * one a later caller can quietly fill with `false`, which is how the verdict
589
+ * was lost on the way out in the first place.
505
590
  */
506
591
  private cacheListResult;
507
592
  /**
@@ -787,10 +872,16 @@ declare class MetadataManager implements IMetadataService {
787
872
  * ## What it judges, and on what
788
873
  *
789
874
  * The registry stores either a raw spec document or a publish envelope
790
- * (`{ name, packageId, state, metadata: {…spec} }`); the endpoint is read
791
- * out with the SAME rule this method's caller uses for
792
- * `publishedDefinition` (`data.metadata ?? data`), so publish gates exactly
793
- * the document publish is about to snapshot. An item that does not satisfy
875
+ * (`{ name, packageId, state, metadata: {…spec} }`), and in BOTH shapes the
876
+ * row carries the metadata layer's bookkeeping. [#5309] The envelope is
877
+ * peeled off first (`peelStoredEnvelope`) and the gate judges the authored
878
+ * BODY: the wrapped half of that peel is the `data.metadata ?? data` rule
879
+ * this method used to spell inline — the same document `publishedDefinition`
880
+ * snapshots — and the flat half additionally removes `packageId` / `state` /
881
+ * `version` / `published*`, which are storage identity, never endpoint
882
+ * vocabulary. (What publish SNAPSHOTS is unchanged: `publishedDefinition`
883
+ * still stores `data.metadata ?? data` verbatim, envelope included, because
884
+ * `revertPackage` restores from it.) An item whose body does not satisfy
794
885
  * `ApiEndpointSchema` fails here too — not extra strictness but a
795
886
  * precondition: an unparsed shape cannot be gated, and it could never be
796
887
  * served either (the matcher's own loud skip refuses it at load).
@@ -1786,7 +1877,7 @@ declare class YAMLSerializer implements MetadataSerializer {
1786
1877
  declare class MigrationExecutor {
1787
1878
  private driver;
1788
1879
  constructor(driver: ISchemaDriver);
1789
- executeChangeSet(changeSet: System.ChangeSet): Promise<void>;
1880
+ executeChangeSet(changeSet: System.ChangeSetParsed): Promise<void>;
1790
1881
  private executeOperation;
1791
1882
  }
1792
1883
 
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { MetadataFormat, MetadataLoaderContract, MetadataLoadOptions, MetadataLo
3
3
  export { MetadataCollectionInfo, MetadataDiffResult, MetadataFormat, MetadataHistoryQueryOptions, MetadataHistoryQueryResult, MetadataHistoryRecord, MetadataHistoryRetentionPolicy, MetadataLoadOptions, MetadataLoadResult, MetadataLoaderContract, MetadataManagerConfig, MetadataSaveOptions, MetadataSaveResult, MetadataStats, MetadataWatchEvent } from '@objectstack/spec/system';
4
4
  import { IMetadataService, IDataDriver, IDataEngine, IRealtimeService, MetadataWriteOptions, MetadataWatchCallback, MetadataWatchHandle, MetadataExportOptions, MetadataImportOptions, MetadataImportResult, MetadataTypeInfo, ApiEndpointMatch, IPubSub, ISchemaDriver } from '@objectstack/spec/contracts';
5
5
  export { IMetadataService, MetadataExportOptions, MetadataImportOptions, MetadataImportResult, MetadataTypeInfo, MetadataWatchCallback, MetadataWatchHandle } from '@objectstack/spec/contracts';
6
- import { MetadataTypeRegistryEntry, MetadataQuery, MetadataQueryResult, MetadataBulkResult, MetadataOverlay, MetadataValidationResult, MetadataDependency, MetadataPluginConfig } from '@objectstack/spec/kernel';
6
+ import { MetadataTypeRegistryEntryParsed, MetadataQuery, MetadataQueryResult, MetadataBulkResult, MetadataOverlay, MetadataValidationResult, MetadataDependency, MetadataPluginConfig } from '@objectstack/spec/kernel';
7
7
  export { MetadataBulkResult, MetadataDependency, MetadataPluginConfig, MetadataPluginManifest, MetadataQuery, MetadataQueryResult, MetadataType, MetadataTypeRegistryEntry, MetadataValidationResult } from '@objectstack/spec/kernel';
8
8
  import { Logger, Plugin, PluginContext } from '@objectstack/core';
9
9
  import { z } from 'zod';
@@ -191,6 +191,23 @@ interface MetadataLoader {
191
191
  * Watch callback function (legacy)
192
192
  */
193
193
  type WatchCallback = (event: MetadataWatchEvent) => void | Promise<void>;
194
+ /**
195
+ * [#6504] What one `list()` read actually produced: the best-effort set, plus
196
+ * whether assembling it lost a loader.
197
+ *
198
+ * The return of {@link MetadataManager.readListUncached}, the value shared
199
+ * through `inflightListReads`, and — minus the cache bookkeeping — what
200
+ * {@link MetadataManager.listDiagnosed} hands to a caller. One shape for all
201
+ * three on purpose: the verdict used to be dropped at each hop outward
202
+ * (`readListUncached` computed it, the in-flight promise kept only `items`,
203
+ * `list()` returned only that), and a single carried record is what makes
204
+ * losing it again take an edit rather than an omission.
205
+ */
206
+ interface ListReadResult {
207
+ items: unknown[];
208
+ degraded: boolean;
209
+ errors: string[];
210
+ }
194
211
  interface MetadataManagerOptions extends MetadataManagerConfig {
195
212
  loaders?: MetadataLoader[];
196
213
  /** Optional IDataDriver instance. When provided alongside config.datasource, auto-configures DatabaseLoader. */
@@ -270,6 +287,15 @@ declare class MetadataManager implements IMetadataService {
270
287
  * only, so a fresh read that already replaced it keeps its slot. Nothing
271
288
  * accumulates — a wave of callers arriving after settle finds the cache the
272
289
  * settle just wrote, and once that lapses it starts one new read.
290
+ *
291
+ * [#6504] The shared value is the whole {@link ListReadResult}, not just
292
+ * `items`. "Sharers share the outcome" above is stated about the answer *and*
293
+ * its degraded verdict, and while the promise carried only `items` that was
294
+ * true of `list()` alone: a {@link listDiagnosed} caller joining an in-flight
295
+ * read had no way to reach the verdict that read had already computed, and
296
+ * would have had to either re-walk the loaders (defeating this map) or invent
297
+ * a second, unmemoized answer. `list()` narrows to `.items` at its own return
298
+ * instead, so every sharer still receives the same array instance.
273
299
  */
274
300
  private readonly inflightListReads;
275
301
  private readonly loaderReadFailureReported;
@@ -287,7 +313,7 @@ declare class MetadataManager implements IMetadataService {
287
313
  /**
288
314
  * Set the type registry for metadata type discovery.
289
315
  */
290
- setTypeRegistry(entries: MetadataTypeRegistryEntry[]): void;
316
+ setTypeRegistry(entries: MetadataTypeRegistryEntryParsed[]): void;
291
317
  /**
292
318
  * Configure and register a DatabaseLoader for database-backed metadata persistence.
293
319
  * Can be called at any time to enable database storage (e.g. after kernel resolves the driver).
@@ -389,16 +415,30 @@ declare class MetadataManager implements IMetadataService {
389
415
  * has with {@link loadDiagnosed}, so every existing caller keeps its exact
390
416
  * behaviour and only callers that ASK for the verdict pay for it.
391
417
  *
392
- * [#5840] Deliberately NOT expressed as `(await getDiagnosed(…)).data`,
393
- * although that is what it computes. The obvious delegation adds one
394
- * `await` hop, and a registry hit here is observed one microtask sooner than
395
- * it would be through a second async frame — which `register()`'s watchers
396
- * depend on, because `notifyWatchers` does not await its handlers and
397
- * ObjectQL's bridge re-reads through `get()` on the event rather than
398
- * trusting the payload (`register-notifies-watchers.test.ts` pins it, and
399
- * went red on the delegating version). The duplication is three lines and is
400
- * pinned from the other side: `get()` and `getDiagnosed().data` are asserted
401
- * to agree on every case in `metadata-manager-get-diagnosed.test.ts`.
418
+ * Not expressed as `(await getDiagnosed(…)).data`, although that is what it
419
+ * computes and the reason has CHANGED, so do not read the duplication as a
420
+ * standing constraint.
421
+ *
422
+ * [#5840] recorded the delegation as unsafe: it adds one `await` hop, and
423
+ * `register-notifies-watchers.test.ts` went red on the delegating version, so
424
+ * three lines were duplicated to hold the frame count fixed. [#6043] measured
425
+ * that test and found it was pinning this method's microtask depth rather than
426
+ * the ordering guarantee it named `notifyWatchers` never awaits its handlers,
427
+ * so a subscriber's `await get(…)` had simply been settling inside the
428
+ * microtasks `await register(…)` yields. That case now asserts the ordering
429
+ * synchronously against the registry and does not observe this method's frame
430
+ * count at all; the whole `@objectstack/metadata` suite was re-measured on the
431
+ * delegating version and stayed green.
432
+ *
433
+ * What survives is a plain, local reason: the registry hit is the hot path and
434
+ * answering it without a second async frame is worth three lines. Nothing
435
+ * external depends on the hop count any more. Consolidating the two into one
436
+ * delegation is therefore a viable, deliberately un-taken change (#6043 was
437
+ * test-scoped) — if you take it, note that `get()`'s callers outside this
438
+ * package were never surveyed for timing sensitivity, only this package's
439
+ * tests. Either way the two stay pinned to each other from the other side:
440
+ * `get()` and `getDiagnosed().data` are asserted to agree on every case in
441
+ * `metadata-manager-get-diagnosed.test.ts`.
402
442
  */
403
443
  get(type: string, name: string): Promise<unknown | undefined>;
404
444
  /**
@@ -443,6 +483,46 @@ declare class MetadataManager implements IMetadataService {
443
483
  * `listCache`.
444
484
  */
445
485
  list(type: string): Promise<unknown[]>;
486
+ /**
487
+ * `list`, plus whether the answer can be trusted as complete.
488
+ *
489
+ * [#6504] The plural counterpart of {@link getDiagnosed}, and the same defect
490
+ * one read over: `readListUncached` has computed this verdict since #5184 and
491
+ * `list()` spent it entirely on a cache TTL, so a consumer receiving a short
492
+ * set could not ask whether it was short because that is all anyone declared
493
+ * or because a loader was down. {@link reportLoaderReadFailure}'s own message
494
+ * says what that costs — "every list served from now on is a PARTIAL set
495
+ * presented as a complete one, and the server keeps reporting healthy" — and
496
+ * until this member existed that sentence was addressed to a log reader only,
497
+ * because no caller had a way to ask.
498
+ *
499
+ * Sharper than the singular case rather than merely analogous: `list` is the
500
+ * read whose answer carries a **count**, and a consumer restating
501
+ * `items.length` as "this environment contains N items" makes a positive,
502
+ * numeric claim about what an author declared out of a read that partly did
503
+ * not happen.
504
+ *
505
+ * Reads through exactly the same cache and single-flight machinery `list()`
506
+ * does — same entry, same TTLs, same in-flight join — so asking for the
507
+ * verdict costs no extra loader walk, and `list()` and
508
+ * `listDiagnosed().items` cannot drift: they are the same read, narrowed at
509
+ * different points. `degraded` is true when at least one loader threw while
510
+ * this set was assembled; unlike {@link getDiagnosed} it does NOT additionally
511
+ * require that nothing answered, because a plural read that lost one loader is
512
+ * partial even when the others answered plenty — which is the whole fact.
513
+ */
514
+ listDiagnosed(type: string): Promise<ListReadResult>;
515
+ /**
516
+ * The cached / single-flight read behind {@link list} and
517
+ * {@link listDiagnosed}.
518
+ *
519
+ * [#6504] Extracted so the two members are one read seen at two widths rather
520
+ * than two implementations that have to be kept in agreement — the shape
521
+ * `get`/`getDiagnosed` pay for with a duplicated body and a test pinning them
522
+ * to each other. Everything below is unchanged in behaviour from when it was
523
+ * inlined in `list()`; only the verdict now survives the return.
524
+ */
525
+ private readList;
446
526
  /**
447
527
  * Assemble the `list()` answer for `type` from the in-memory registry plus
448
528
  * every loader, reporting (but not rethrowing) loaders that could not be
@@ -502,6 +582,11 @@ declare class MetadataManager implements IMetadataService {
502
582
  * one thing this cache used to throw away. A result assembled while a loader
503
583
  * was unreadable is stored, but stored *as* what it is, so it expires on the
504
584
  * degraded TTL and any reader can tell it apart from a complete answer.
585
+ *
586
+ * [#6504] Takes the whole read result rather than its parts for the same
587
+ * reason: a signature that spreads the verdict across positional arguments is
588
+ * one a later caller can quietly fill with `false`, which is how the verdict
589
+ * was lost on the way out in the first place.
505
590
  */
506
591
  private cacheListResult;
507
592
  /**
@@ -787,10 +872,16 @@ declare class MetadataManager implements IMetadataService {
787
872
  * ## What it judges, and on what
788
873
  *
789
874
  * The registry stores either a raw spec document or a publish envelope
790
- * (`{ name, packageId, state, metadata: {…spec} }`); the endpoint is read
791
- * out with the SAME rule this method's caller uses for
792
- * `publishedDefinition` (`data.metadata ?? data`), so publish gates exactly
793
- * the document publish is about to snapshot. An item that does not satisfy
875
+ * (`{ name, packageId, state, metadata: {…spec} }`), and in BOTH shapes the
876
+ * row carries the metadata layer's bookkeeping. [#5309] The envelope is
877
+ * peeled off first (`peelStoredEnvelope`) and the gate judges the authored
878
+ * BODY: the wrapped half of that peel is the `data.metadata ?? data` rule
879
+ * this method used to spell inline — the same document `publishedDefinition`
880
+ * snapshots — and the flat half additionally removes `packageId` / `state` /
881
+ * `version` / `published*`, which are storage identity, never endpoint
882
+ * vocabulary. (What publish SNAPSHOTS is unchanged: `publishedDefinition`
883
+ * still stores `data.metadata ?? data` verbatim, envelope included, because
884
+ * `revertPackage` restores from it.) An item whose body does not satisfy
794
885
  * `ApiEndpointSchema` fails here too — not extra strictness but a
795
886
  * precondition: an unparsed shape cannot be gated, and it could never be
796
887
  * served either (the matcher's own loud skip refuses it at load).
@@ -1786,7 +1877,7 @@ declare class YAMLSerializer implements MetadataSerializer {
1786
1877
  declare class MigrationExecutor {
1787
1878
  private driver;
1788
1879
  constructor(driver: ISchemaDriver);
1789
- executeChangeSet(changeSet: System.ChangeSet): Promise<void>;
1880
+ executeChangeSet(changeSet: System.ChangeSetParsed): Promise<void>;
1790
1881
  private executeOperation;
1791
1882
  }
1792
1883