Skip to content

[finding] VISIBILITY_STRICT_OPTIONS is in @objectstack/spec's public API but its type StrictObjectOptions is not — a published const no consumer can annotate #8213

Description

@os-zhuang

Filed unassigned by the domain:spec-surface seat (#6298) from PR #8199's dev report. Recording only — this one wants a decision, not a drive-by fix, which is why it is a finding rather than a follow-up chore.

What

shared/visibility.ts is re-exported wholesale by shared/index.ts, so VISIBILITY_STRICT_OPTIONS is part of the package's public API and is tracked by check:api-surface.

Its type is not. StrictObjectOptions lives in shared/strict-object.ts, which the barrel deliberately omits — as it omits alias-probe.ts and, since PR #8199, editability-boundary.ts.

So an external consumer can import the value and can do nothing with it: they cannot annotate a variable holding it, cannot type a function that takes it, cannot spread it into an options object of the right type. The export is reachable and unusable.

Why it looks accidental rather than intended

visibility.ts carries two different kinds of thing: the runtime helper normalizeVisibleWhen (which genuinely belongs to consumers — it implements the ADR-0089 fold) and the strict-object options table (schema-declaration machinery for use inside this package). The barrel exports the module, so the second rode along with the first. Every neighbouring module holding the same kind of machinery is unbarrelled.

Surfaced while landing PR #8199: that PR needed a sibling options table, and putting it in visibility.ts made check:api-surface red for a docs card. Moving it to an unbarrelled module fixed that and made the card's "nothing observable moves" claim true at the API level too — but it leaves the pre-existing export sitting there as the odd one out.

Why it is not obviously safe to just un-export

Removing it from the barrel is a breaking change to the published surface (check:api-surface counts it as removed/narrowed), even though the plausible number of external consumers is zero — nobody can be using it in a typed way, by the argument above. That combination — technically breaking, practically inert — is exactly the kind of call that should be made deliberately and recorded, not folded into an unrelated PR.

Options, in ascending cost: leave it and note why; un-export it in the next major with an ADR-0087 registry entry; or publish StrictObjectOptions too, if the options table is genuinely meant to be consumer-facing (nothing observed suggests it is).

Routing suggestion

domain:spec — it is a published-surface decision, not a text-face one. Low urgency, zero measured pull. If the answer is "un-export", the follow-through has a retirement process to go through (ADR-0087) and should ride a major.

Backlinks: PR #8199 (where it surfaced), #7887.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions