Skip to content

Enforce the extension API surface with an API report #2366

Description

@dex4er

Goal

Turn the v2 extension API surface from something described in prose into something CI
checks: a git-tracked API report, plus a mechanical gate against the class of defect
found in #2365.

Depends on #2363 — API Extractor has to be running first. Split out of it so this value
does not hide inside a build-fix issue; the two have different urgency and different
readers.

Why prose is not enough here

#2304 is meant to produce the normative specification of the extension API, and one of
its open contract items is "namespace enumeration" — what each of Common / Main /
Renderer actually provides. Written by hand, that list is stale the first time someone
adds an export.

The audit in #2360 and the gap in #2365 both came out of reading the surface manually.
That does not scale, and more importantly it does not repeat: nothing stops the next
export from reintroducing the same problem.

There is a structural reason this matters more for v2 than it would for a normal library.
Workspace packages are private and inlined into the bundled .d.ts (39 entries; the
runtime half is a four-line shim over globalThis.FreelensExtensionApi). With that model,
a symbol the API namespace does not re-export is unreachable by any means — there is no
package left for an author to install. Completeness of the re-export is therefore a
correctness property of the packaging model, not a convenience.

What API Extractor gives us

1. ae-forgotten-export — the mechanical check for #2365

Reported when an exported API references a declaration that is not itself exported from
the entry point. That is exactly the defect #2365 documents by hand:

Exported by the API Its signature needs Nameable by an extension?
KubeApi KubeApiOptions & ExternalKubeApiOptions ExternalKubeApiOptions yes, KubeApiOptions no
PodsApi, NodesApi, … DerivedKubeApiOptions no
KubeObjectStore KubeObjectStoreOptions no

By default this message goes to the report file rather than the console, so intentional
exceptions stay documented and reviewable instead of being silenced.

2. The .api.md report — a diffable contract

A git-tracked file containing the public API surface. From the API Extractor docs: "The
report file should be tracked by Git, so that changes to an API signature will appear as
diffs when a pull request (PR) is created."

This is the artifact #2304 actually wants. Instead of a hand-maintained namespace
enumeration that drifts, the enumeration is the checked-in file, and any change to it
shows up in review. The rushstack repository gates this with .github/CODEOWNERS so API
changes need a specific approval; worth considering once the report settles.

3. Release tags for the versioning contract

@public / @beta / @internal TSDoc tags plus trimmed rollup variants
(publicTrimmedFilePath, betaTrimmedFilePath) give a concrete mechanism for #2304's
"Versioning & compatibility policy" item — a way to ship something as unstable on purpose
rather than by omission.

Tasks

Risk notes

Depends on #2363. Closes the mechanical half of #2365. Feeds #2304. Carries the
external-import list left over from #2360.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions