Measured while implementing #9846 (sourcing package-routes.ts's getMetaItems
option types from the spec). That card's body asserts "Both verbs are already
declared in packages/spec". Re-measured on origin/main @ 301bf26be1:
that is true of getMetaItems and false of deletePackage, so #9846 was
scoped to the getMetaItems half and this is the other half, recorded rather
than acted on — minting a protocol verb declaration is a contract act for the
spec seat, not a typing cleanup.
The measurement
DeletePackageRequest, DeletePackageResponse and DeletePackageRequestSchema
return zero hits across the whole repo (--include=*.ts, excluding
node_modules). deletePackage is also absent from the declared protocol
interface in packages/spec/src/api/protocol.zod.ts. The only spec-side
mentions are prose in two semantic-migration entries
(migrations/entries/semantic/17.package-uninstall-explicit-all-tenants.ts and
the registry), which describe the surface without declaring it.
Why it is worth a card: the three hand-rolled shapes DISAGREE
This is not only "an undeclared verb". Each site states its own shape, and they
are not the same shape.
1. The implementation — packages/metadata-protocol/src/protocol.ts:15379,
itself an inline structural type rather than a named one:
asyncdeletePackage(request: {packageId: string;organizationId?: string;allTenants?: boolean;actor?: string;keepData?: boolean;}): Promise<{success;deletedCount;failedCount;deleted;failed;cleanups}>2. The REST direct-mount option — packages/rest/src/package-routes.ts:256:
deletePackage?(req: {packageId: string;actor?: string;allTenants?: boolean}): Promise<…>It names neither organizationId nor keepData, and its response omits
deleted.
3. The runtime dispatcher twin — packages/runtime/src/domains/packages.ts:895,
which does not type the seam at all:
if(protocol&&typeof(protocolasany).deletePackage==='function'){persisted=await(protocolasany).deletePackage({packageId: id,
...(organizationId ? { organizationId } : {}),
...(keepData ? {keepData: true} : {}),});So the runtime twin routinely sends exactly the two keys the REST option's type
cannot express, and the only reason that is not a compile error is the as any.
Not asserted: no defect today
The REST registrar calls deletePackage({ packageId, allTenants: true }) and
never passes organizationId or keepData, so no live call is currently
mistyped. What is recorded is that one verb has three independent statements of
its own contract, one of them cast away entirely — the exact blindness class
#9846 and #9805 were filed about, with no declared shape at the seam to name.
The tenant-scope semantics make it load-bearing rather than cosmetic: the
protocol refuses a call naming neither allTenants nor an organizationId
(TENANT_SCOPE_REQUIRED, 400), so organizationId is precisely the key whose
presence decides an uninstall's blast radius — and it is the key the REST
option's type does not name.
The judgement this does not make
Whether deletePackage should be declared in packages/spec (and if so,
whether it joins MetadataProtocol or a package-management protocol of its
own), or whether the three consumers should instead converge on one exported
type from @objectstack/metadata-protocol. Both are contract decisions for the
spec seat.
Repo: objectstack. Files: packages/spec/src/api/protocol.zod.ts (absence),
packages/metadata-protocol/src/protocol.ts:15379,
packages/rest/src/package-routes.ts:256,
packages/runtime/src/domains/packages.ts:895.
Related: #9846 (the getMetaItems half, implemented in #9959), #9805, #9741.
Generated by Claude Code
Measured while implementing #9846 (sourcing
package-routes.ts'sgetMetaItemsoption types from the spec). That card's body asserts "Both verbs are already
declared in
packages/spec". Re-measured onorigin/main@301bf26be1:that is true of
getMetaItemsand false ofdeletePackage, so #9846 wasscoped to the
getMetaItemshalf and this is the other half, recorded ratherthan acted on — minting a protocol verb declaration is a contract act for the
spec seat, not a typing cleanup.
The measurement
DeletePackageRequest,DeletePackageResponseandDeletePackageRequestSchemareturn zero hits across the whole repo (
--include=*.ts, excludingnode_modules).deletePackageis also absent from the declared protocolinterface in
packages/spec/src/api/protocol.zod.ts. The only spec-sidementions are prose in two semantic-migration entries
(
migrations/entries/semantic/17.package-uninstall-explicit-all-tenants.tsandthe registry), which describe the surface without declaring it.
Why it is worth a card: the three hand-rolled shapes DISAGREE
This is not only "an undeclared verb". Each site states its own shape, and they
are not the same shape.
1. The implementation —
packages/metadata-protocol/src/protocol.ts:15379,itself an inline structural type rather than a named one:
2. The REST direct-mount option —
packages/rest/src/package-routes.ts:256:It names neither
organizationIdnorkeepData, and its response omitsdeleted.3. The runtime dispatcher twin —
packages/runtime/src/domains/packages.ts:895,which does not type the seam at all:
So the runtime twin routinely sends exactly the two keys the REST option's type
cannot express, and the only reason that is not a compile error is the
as any.Not asserted: no defect today
The REST registrar calls
deletePackage({ packageId, allTenants: true })andnever passes
organizationIdorkeepData, so no live call is currentlymistyped. What is recorded is that one verb has three independent statements of
its own contract, one of them cast away entirely — the exact blindness class
#9846 and #9805 were filed about, with no declared shape at the seam to name.
The tenant-scope semantics make it load-bearing rather than cosmetic: the
protocol refuses a call naming neither
allTenantsnor anorganizationId(
TENANT_SCOPE_REQUIRED, 400), soorganizationIdis precisely the key whosepresence decides an uninstall's blast radius — and it is the key the REST
option's type does not name.
The judgement this does not make
Whether
deletePackageshould be declared inpackages/spec(and if so,whether it joins
MetadataProtocolor a package-management protocol of itsown), or whether the three consumers should instead converge on one exported
type from
@objectstack/metadata-protocol. Both are contract decisions for thespec seat.
Repo:
objectstack. Files:packages/spec/src/api/protocol.zod.ts(absence),packages/metadata-protocol/src/protocol.ts:15379,packages/rest/src/package-routes.ts:256,packages/runtime/src/domains/packages.ts:895.Related: #9846 (the
getMetaItemshalf, implemented in #9959), #9805, #9741.Generated by Claude Code