Skip to content

[finding] Plugin.type is typed string on a published surface — the eight-value set is enforced by prose only, though packages/core already depends on spec #13925

Description

@claude

Recorded while fixing #13762 (the Plugin.type TSDoc under-enumeration). Out of that card's scope — filed for triage, no assignee.

The observation

Plugin.type in packages/core/src/types.ts is declared type?: string. Nothing type-checks a plugin author against the eight values the platform actually accepts, so the TSDoc comment beside it carries the entire enumeration on its own. That is exactly why the comment drifting was worth a card: prose was doing a type's job.

While verifying that assumption for #13762 I measured something the card did not claim:

  • There is no PluginType alias and no typeof CORE_PLUGIN_TYPES derived type anywhere in packages/**. The enumeration exists only as the Zod enum in packages/spec/src/kernel/plugin.zod.ts and as prose.
  • packages/core already declares @objectstack/spec as a workspace:* dependency. So a type-level narrowing is reachable today without adding a dependency edge.

Sketch of the shape, not a proposal to land as-is:

import type { CORE_PLUGIN_TYPES } from '@objectstack/spec';
type PluginType = 'standard' | (typeof CORE_PLUGIN_TYPES)[number];
type?: PluginType;

Why it needs a decision rather than a patch

This narrows a published type on @objectstack/core. Anything today assigning a computed or third-party string to Plugin.type stops compiling, so it is an accept/reject change on a public surface, not a cleanup — it needs the contract-review path and a deliberate call on whether plugin type is a closed set for external authors or an open one the runtime merely recognises some members of.

It is also worth weighing against #13678, which would close the same drift class mechanically with a gate. These are alternative remedies for one defect, and the type-level one is narrower but stronger: it makes the wrong value unwritable rather than detectable. Whether the platform wants type closed is the real question, and it is a maintainer call.

How it was settled

Read against the implementation on origin/main at 5c34b7e26b: the type?: string declaration in packages/core/src/types.ts, a repo-wide search for a PluginType-shaped alias returning nothing, and packages/core/package.json showing the existing @objectstack/spec dependency.

Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions