Skip to content

Commit 044b4d9

Browse files
committed
refactor(metadata-protocol): also move refuseUnmintableMetaType and overlaidShippedContainerViewNames, and follow the moved throw sites in the refusal-opener pin
Both members were earlier stays; re-measured on today's tree, neither moves the read-seam census nor any by-path pin, so they move on the same terms as the rest of this cut. The bracketed-refusal-opener pin scans PRODUCERS by file: the four modules that now hold moved throw sites join it at their own new Error count, so the scan keeps seeing them. Claude-Session: https://claude.ai/code/session_01L6bhgVeV5GgzaH9Ny16aSx Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2c6ff0a commit 044b4d9

4 files changed

Lines changed: 104 additions & 26 deletions

File tree

‎packages/metadata-protocol/src/protocol-registry-view-predicates.ts‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
* - `isAnotherPackagesObject` — whether a code package other than the
1313
* container's owns its object;
1414
* - `registryTakesStoredRows` — whether this protocol's engine registry takes
15-
* the rows this kernel stores.
15+
* the rows this kernel stores;
16+
* - `overlaidShippedContainerViewNames` — the view names of the shipped
17+
* container a container row overlays by its own name.
1618
*
1719
* A MOVE, not a redesign. Each function below is the body of the
1820
* `ObjectStackProtocolImplementation` method of the same name as it stood,
@@ -49,6 +51,7 @@ export interface RegistryViewPredicatesHost {
4951
readonly environmentId: ObjectStackProtocolImplementation['environmentId'];
5052
readonly expandRuntimeViewContainer: ObjectStackProtocolImplementation['expandRuntimeViewContainer'];
5153
readonly runtimeViewContainerObject: ObjectStackProtocolImplementation['runtimeViewContainerObject'];
54+
readonly runtimeViewContainerPackage: ObjectStackProtocolImplementation['runtimeViewContainerPackage'];
5255
readonly shippedViewContainerOf: ObjectStackProtocolImplementation['shippedViewContainerOf'];
5356
readonly storeHydratedIntoRegistry: ObjectStackProtocolImplementation['storeHydratedIntoRegistry'];
5457
}
@@ -102,3 +105,18 @@ export function isAnotherPackagesObject(this: Pick<RegistryViewPredicatesHost, '
102105
export function registryTakesStoredRows(this: Pick<RegistryViewPredicatesHost, 'environmentId' | 'storeHydratedIntoRegistry'>): boolean {
103106
return this.environmentId === undefined || this.storeHydratedIntoRegistry;
104107
}
108+
109+
/** The body of `ObjectStackProtocolImplementation#overlaidShippedContainerViewNames`; the method's docblock there is its contract. */
110+
export function overlaidShippedContainerViewNames(
111+
this: Pick<RegistryViewPredicatesHost, 'expandRuntimeViewContainer' | 'runtimeViewContainerPackage' | 'shippedViewContainerOf'>,
112+
type: string,
113+
container: Record<string, unknown>,
114+
packageId: string | null | undefined,
115+
): ReadonlySet<string> {
116+
const ownPackageId = this.runtimeViewContainerPackage(type, container, { packageId });
117+
const shipped = this.shippedViewContainerOf(type, container.name, ownPackageId);
118+
if (shipped === undefined) return new Set();
119+
return new Set(
120+
this.expandRuntimeViewContainer(type, shipped, { packageId: ownPackageId }).map((view) => String(view.name)),
121+
);
122+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* [#25467 cut 33] The `/meta` save door's refusal of a `:type` segment that is
5+
* not a metadata type at all, on the one entry point that mints a
6+
* `sys_metadata` namespace, from `ObjectStackProtocolImplementation`, moved
7+
* out of `protocol.ts` whole: `refuseUnmintableMetaType`.
8+
*
9+
* A MOVE, not a redesign. Each function below is the body of the
10+
* `ObjectStackProtocolImplementation` method of the same name as it stood,
11+
* re-indented one level and otherwise unedited.
12+
*
13+
* ## How the moved bodies reach the class
14+
*
15+
* The shape #23050 set for `rest-server.ts` (its `data-action-routes.ts`
16+
* header carries the full reasoning), as `protocol-batch-data.ts` applies it.
17+
* The class keeps each method — the published `dist/*.d.ts` lists its name,
18+
* docblock and declared signature — and its body is one literal of exactly
19+
* the {@link UnmintableMetaTypeHost} members it reads, plus a `.call`; a body
20+
* that reads no member is called as a plain function. Its call to
21+
* `metaTypeNamespaceExists` is handed over as a closure, so it still reaches
22+
* the class method, which stays. Every caller keeps calling the class
23+
* methods.
24+
*
25+
* What the bodies read from elsewhere, they import from where `protocol.ts`
26+
* imports it. Nothing re-exports this module, so the published surface does
27+
* not move.
28+
*/
29+
30+
import { unrecognisedMetaTypeRefusal } from '@objectstack/spec/shared';
31+
import type { ObjectStackProtocolImplementation } from './protocol.js';
32+
33+
/**
34+
* The `ObjectStackProtocolImplementation` members the function below reads —
35+
* every one of them, and no other; the function's `this` is the `Pick` of them. Each is typed AS the class member (an indexed access
36+
* on the class), so a change to a member's signature on the class is a change
37+
* here too, and naming a member the class does not have is a compile error.
38+
*/
39+
export interface UnmintableMetaTypeHost {
40+
readonly metaTypeNamespaceExists: ObjectStackProtocolImplementation['metaTypeNamespaceExists'];
41+
}
42+
43+
/** The body of `ObjectStackProtocolImplementation#refuseUnmintableMetaType`; the method's docblock there is its contract. */
44+
export async function refuseUnmintableMetaType(this: Pick<UnmintableMetaTypeHost, 'metaTypeNamespaceExists'>, request: { type: string, name: string }): Promise<void> {
45+
const unrecognised = unrecognisedMetaTypeRefusal(request.type);
46+
if (!unrecognised) return;
47+
// The old exemption 1 (skip when the name contains a slash) was
48+
// removed by commit 311433f6b — the grammar verdict upstream refuses every
49+
// slash-bearing name before this probe runs. See the header.
50+
// Exemption 2 — the namespace predates this write.
51+
if (await this.metaTypeNamespaceExists(unrecognised.type)) return;
52+
const err = new Error(
53+
`'${unrecognised.type}' is not a metadata type. The platform declares `
54+
+ `no such type, and a plugin cannot declare one either: 'additionalTypes' was retired because `
55+
+ `nothing ever read it — so this write would mint a sys_metadata namespace under `
56+
+ `type='${unrecognised.type}' that nothing reads and nothing serves. Address a real `
57+
+ `metadata type; GET /api/v1/meta/types lists the ones this deployment carries.`,
58+
);
59+
(err as any).code = 'INVALID_REQUEST';
60+
(err as any).status = 400;
61+
throw err;
62+
}

‎packages/metadata-protocol/src/protocol.bracketed-refusal-opener-absence.test.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ const PRODUCERS: Readonly<Record<string, number>> = {
9393
// The package door's save refusal, moved out of `protocol.ts` whole on the
9494
// same terms.
9595
'protocol-packaged-base-refusal.ts': 1,
96+
// [#25467 cut 33] The named-base rule and the app package-id key, the `/meta`
97+
// mint door's refusal, the MetadataService 503 and the overlay-index DDL
98+
// probe, moved out of `protocol.ts` whole on the same terms.
99+
'protocol-package-scope.ts': 2,
100+
'protocol-unmintable-meta-type.ts': 1,
101+
'protocol-loud-degradations.ts': 1,
102+
'protocol-overlay-index.ts': 1,
96103
'sys-metadata-repository.ts': 5,
97104
'runtime-authoring-gate.ts': 1,
98105
};

‎packages/metadata-protocol/src/protocol.ts‎

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,14 @@ import { overlayLockLayerAt, resolveOverlayPackageBinding, storedRowKnownDatasou
425425
import { throwMetadataServiceUnavailable, warnClosureReadUnavailable } from './protocol-loud-degradations.js';
426426
// [#25467 cut 33] The overlay-uniqueness indexes and the bundle-member backfill, once per process.
427427
import { ensureOverlayIndex, ensureOverlayMembersBackfilled } from './protocol-overlay-index.js';
428-
// [#25467 cut 33] The registry and view-container predicates: stored container expansion, binding, ownership, registry scope.
429-
import { copiesOwnShippedViewContainer, expandStoredViewContainers, isAnotherPackagesObject, registryTakesStoredRows, runtimeViewContainerObject } from './protocol-registry-view-predicates.js';
428+
// [#25467 cut 33] The registry and view-container predicates: stored container expansion, binding, ownership, registry scope, overlaid views.
429+
import { copiesOwnShippedViewContainer, expandStoredViewContainers, isAnotherPackagesObject, overlaidShippedContainerViewNames, registryTakesStoredRows, runtimeViewContainerObject } from './protocol-registry-view-predicates.js';
430430
// [#25467 cut 33] The ADR-0067 commit row of a publish or revert turn, and its named INSERT.
431431
import { persistPackageCommitRow, recordPackageCommit } from './protocol-package-commit-record.js';
432432
// [#25467 cut 33] Package scope: the writable base, the named-base rule, storage teardown, the app package-id key.
433433
import { isWritablePackage, resolveAppPackageIdKey, shouldDropStorage, uninstalledNamedBaseRefusal } from './protocol-package-scope.js';
434+
// [#25467 cut 33] The /meta save door's refusal of a `:type` that is no metadata type at all.
435+
import { refuseUnmintableMetaType } from './protocol-unmintable-meta-type.js';
434436
// [#25467 cut 33] The deployment's SDUI component manifest, and the load-time page `requires` report against it.
435437
import { reportPageRequiresAbsentAtLoad, resolveSduiManifest } from './protocol-sdui-manifest.js';
436438

@@ -19410,23 +19412,11 @@ export class ObjectStackProtocolImplementation implements
1941019412
* existence claim (see {@link metaTypeNamespaceExists}).
1941119413
*/
1941219414
private async refuseUnmintableMetaType(request: { type: string, name: string }): Promise<void> {
19413-
const unrecognised = unrecognisedMetaTypeRefusal(request.type);
19414-
if (!unrecognised) return;
19415-
// The old exemption 1 (skip when the name contains a slash) was
19416-
// removed by commit 311433f6b — the grammar verdict upstream refuses every
19417-
// slash-bearing name before this probe runs. See the header.
19418-
// Exemption 2 — the namespace predates this write.
19419-
if (await this.metaTypeNamespaceExists(unrecognised.type)) return;
19420-
const err = new Error(
19421-
`'${unrecognised.type}' is not a metadata type. The platform declares `
19422-
+ `no such type, and a plugin cannot declare one either: 'additionalTypes' was retired because `
19423-
+ `nothing ever read it — so this write would mint a sys_metadata namespace under `
19424-
+ `type='${unrecognised.type}' that nothing reads and nothing serves. Address a real `
19425-
+ `metadata type; GET /api/v1/meta/types lists the ones this deployment carries.`,
19426-
);
19427-
(err as any).code = 'INVALID_REQUEST';
19428-
(err as any).status = 400;
19429-
throw err;
19415+
// [#25467 cut 33] The body moved to `protocol-unmintable-meta-type.ts` (see `UnmintableMetaTypeHost`).
19416+
const host: ThisParameterType<typeof refuseUnmintableMetaType> = {
19417+
metaTypeNamespaceExists: (...a) => this.metaTypeNamespaceExists(...a),
19418+
};
19419+
return refuseUnmintableMetaType.call(host, request);
1943019420
}
1943119421

1943219422
/**
@@ -19937,12 +19927,13 @@ export class ObjectStackProtocolImplementation implements
1993719927
container: Record<string, unknown>,
1993819928
packageId: string | null | undefined,
1993919929
): ReadonlySet<string> {
19940-
const ownPackageId = this.runtimeViewContainerPackage(type, container, { packageId });
19941-
const shipped = this.shippedViewContainerOf(type, container.name, ownPackageId);
19942-
if (shipped === undefined) return new Set();
19943-
return new Set(
19944-
this.expandRuntimeViewContainer(type, shipped, { packageId: ownPackageId }).map((view) => String(view.name)),
19945-
);
19930+
// [#25467 cut 33] The body moved to `protocol-registry-view-predicates.ts` (see `RegistryViewPredicatesHost`).
19931+
const host: ThisParameterType<typeof overlaidShippedContainerViewNames> = {
19932+
expandRuntimeViewContainer: (...a) => this.expandRuntimeViewContainer(...a),
19933+
runtimeViewContainerPackage: (...a) => this.runtimeViewContainerPackage(...a),
19934+
shippedViewContainerOf: (...a) => this.shippedViewContainerOf(...a),
19935+
};
19936+
return overlaidShippedContainerViewNames.call(host, type, container, packageId);
1994619937
}
1994719938

1994819939
/**

0 commit comments

Comments
 (0)