TypeScript SDK¶
TypeScript packages consumed as SDKs or client libraries by other projects.
Charter status¶
| Charter status | Value |
|---|---|
| Maturity | Candidate rubric |
| What this state means | Numbered candidate rules carry severity, required evidence, and an exception policy. A versioned rubric can be cut from this page once its promotion criteria are met. |
| Full rubric | Not authored yet. This page is a charter, not a judgeable standard. |
| Reference implementation | vibecodeqa/ref-typescript-sdk (published) — see Reference implementation below. |
| Blocking promotion | Twelve candidate rules carry severity, evidence, and exception terms, and ref-typescript-sdk now exists, is published in the catalog, and carries a self-reported score with a green CI run (#14). Blocking v1: the reference repo's report evidences the required implementation but does not judge R-SDK-1 to R-SDK-12 one by one at a named commit, and no independent assessment of the repo exists. |
Maturity states are defined in Standards Authoring.
Metadata lives in standards/registry.json.
Full rubric¶
No full versioned rubric has been authored yet.
Reference implementation¶
| Score evidence | Value |
|---|---|
| Repository | vibecodeqa/ref-typescript-sdk (published) |
| VCQA report | A 98/100 |
| Verification | self-reported |
| Assessed commit | 2f6a285 |
| Assessed on | 2026-08-09 |
| CI run | success (2026-08-08) |
| Independent assessment | None published yet. The score above is the reference repo's own claim, not third-party proof. |
| Catalog entry last verified | 2026-08-09 |
Teaching focus¶
This standard teaches that an SDK is a compatibility promise, not just a compiled TypeScript package. Choosing this stack means maintaining a small public surface, shipping declarations that match runtime behavior, keeping generated API clients fresh, and giving consumers typed failure modes they can handle without reading implementation code.
Scope¶
TypeScript packages consumed as SDKs or client libraries by other projects.
Not in scope¶
- apps with no exported API
- private implementation packages
- untyped JavaScript packages
- CLIs where the command-line interface is the primary product contract
- deployed packages that declare an entry point for a host rather than for a consumer —
Firebase Cloud Functions codebases and VS Code extensions both declare
main, but they publish nothing and are deployed, not imported (#49)
Composes¶
Upstream references¶
- TypeScript declaration file publishing
- TypeScript TSConfig reference
- TypeScript module resolution reference
- TypeScript 4.7 Node ESM/CJS release notes
- Node.js package entry points and exports
- npm package.json docs
- npm trusted publishing
- OpenAPI Specification 3.1
- JSON Schema specification
- Semantic Versioning 2.0.0
- OWASP Secrets Management Cheat Sheet
VCQA-owned rule surface¶
- export map and public entrypoint quality.
- declaration output and declaration/runtime alignment.
- ESM/CJS and runtime support decisions.
- API contract freshness.
- generated client drift detection.
- typed error model.
- runtime validation at external boundaries.
- semantic versioning and compatibility tests.
- credential boundary and redaction policy.
- publish artifact and provenance policy.
Detection signals¶
package.jsondeclares both an entry point (exports,main,module) and a types declaration (types,typings,typesVersions) — resolver signal. The entry point alone is not enough: a deployed package has one too. The types declaration is what says the package is meant to be imported.package.jsonfilesdeclaration,emitDeclarationOnly, ordeclarationMapintsconfig.jsondist/*.d.ts,*.d.mts, or*.d.ctsartifacts- OpenAPI, JSON Schema, or generator config files
- generated client directories or checked-in API schemas
- public
Client,Error,Config,Credentials, orTokenProvidertypes - consumer fixture tests, package tarball tests, or matrix tests across TypeScript/module-resolution modes
Combination-born guidelines¶
- Export maps and declarations are compatibility gates, not packaging polish.
- Generated API clients must track the checked-in OpenAPI contract.
- Runtime errors need a typed model consumers can handle without string matching.
- TypeScript types describe the SDK API, but OpenAPI/JSON Schema/Zod-style validation must still guard untrusted API responses and user-provided config.
- ESM/CJS support is a product decision; each advertised condition or entrypoint must have matching JavaScript and declaration files.
- Credential helpers may make local development easier, but SDKs must not own application secrets or silently read unrelated ambient credentials.
- SemVer applies to runtime behavior, exported types, module entrypoints, error shapes, and documented side effects.
Candidate rules¶
- R-SDK-1: Public entrypoints are intentional.
package.jsonexposes only supported API entrypoints throughexportsor equivalent metadata, and deep imports into build internals are treated as unsupported. - R-SDK-2: Declarations are shipped and checked. Published packages include declaration files for every public entrypoint, and CI verifies declarations by compiling consumer fixtures against the packed artifact.
- R-SDK-3: Runtime and declaration modules agree. ESM-only, CJS-only, or dual-package support is
documented; conditional exports,
type, JavaScript extensions, and.d.ts/.d.mts/.d.ctsfiles match Node and TypeScript resolution rules. - R-SDK-4: Supported runtimes are explicit. Node, browser, worker, edge, or bundler support is named in docs and package metadata, with tests proving that unsupported runtime APIs are not pulled into supported entrypoints.
- R-SDK-5: API contracts stay fresh. SDK request and response types derived from OpenAPI or JSON Schema are regenerated or checked in CI whenever the source contract changes.
- R-SDK-6: Generated client drift fails builds. Generated files are reproducible from checked-in config, generator versions are pinned, and CI fails when generated output differs from the committed API contract.
- R-SDK-7: External data is validated at runtime. Unknown API responses, webhook payloads, config files, and user-provided JSON are parsed before being exposed as trusted domain types.
- R-SDK-8: Errors are typed. Consumers can branch on stable fields such as
name,code,status,retryable,details, andcause; they do not need to parse human-readable messages. - R-SDK-9: Credentials stay at the edge. SDKs accept credentials, token providers, or request-signing callbacks from the host application and redact them in logs/errors; they do not persist raw secrets or search broad ambient locations by default.
- R-SDK-10: Compatibility is tested as a consumer would use it. CI packs or links the SDK into fixture projects and tests import/require paths, tree-shakable subpaths, declarations, and representative runtime calls across supported TypeScript and Node versions.
- R-SDK-11: SemVer covers types. Removing exports, narrowing accepted input, changing error codes, changing default side effects, or breaking declaration compatibility is a breaking change even when JavaScript still runs.
- R-SDK-12: Publish artifacts are minimal and reproducible.
files, build output, source maps, declarations, provenance, and release scripts are controlled so consumers receive intended artifacts and no local secrets, fixtures, or generator caches.
Severity and evidence¶
Severities follow the shared rule contract. Severity belongs to the rule, not to the reviewer.
| Rules | Severity | Escalation |
|---|---|---|
| R-SDK-9 | blocker |
Already top severity. An SDK that persists raw secrets or harvests ambient production credentials makes every consuming application unsafe by installing it. |
| R-SDK-12 | high |
blocker when the packed tarball contains a secret, a local env file, or a credential cache. |
| R-SDK-2, R-SDK-3 | high |
blocker when the published artifact does not resolve at all for an advertised entrypoint: the package is broken for every consumer on that path. |
| R-SDK-7, R-SDK-8, R-SDK-11 | high |
blocker for R-SDK-7 when unvalidated API data reaches an authorization or tenant-scoping decision. |
| R-SDK-1, R-SDK-4, R-SDK-10 | medium |
high when a runtime is advertised in docs or package metadata but never tested. |
| R-SDK-5, R-SDK-6 | evidence-only |
high when the generated client is stale against the checked-in contract, and blocker when the drift is in an auth, payment, or tenant-boundary path. |
Required evidence:
evidence:
sourcePaths:
- "src/**"
- "dist/**"
configFiles:
- "package.json"
- "tsconfig.json"
- "openapi.yaml or the checked-in API contract"
- "generator config"
- ".github/workflows/*.yml"
ciArtifacts:
- "packed tarball file listing from a release-path job"
- "consumer fixture build logs for import and require, across supported TypeScript versions"
- "generated-client regeneration diff job output"
runtimeProof:
- "a fixture project that imports the packed artifact and makes one representative call"
- "a declaration-resolution check per advertised export condition"
negativeEvidence:
- "no secret, .env file, fixture credential, or generator cache in the packed tarball"
- "no unsupported-runtime API pulled into a supported entrypoint"
exceptionFormat: "accepted-exception"
CI expectations: compatibility evidence comes from the packed artifact, not the source
tree. A job that type-checks src/ proves nothing about exports, types, or conditional
declaration resolution, and does not satisfy R-SDK-2, R-SDK-3, or R-SDK-10.
Exception policy¶
Exceptions use the acceptedException record in the rule contract:
owner, scope, environment, reason, compensating controls, evidence, expiry, approval trail.
Stack-specific rulings:
- ESM-only or CJS-only is a documented decision, not an exception. Record it in package metadata and docs; R-SDK-3 then judges consistency with that decision.
- R-SDK-10 is exceptionable in breadth for an internal SDK — a reduced TypeScript/Node matrix, scoped to the named consuming repositories, with an expiry. It is not exceptionable in kind: at least one consumer fixture must exercise the packed artifact.
- R-SDK-6 is exceptionable for a hand-maintained client when the generator was abandoned deliberately; the compensating control is a contract-diff check that fails on drift.
- R-SDK-9 and the secret half of R-SDK-12 are not exceptionable. A published tarball containing a credential is closed by rotating it and republishing, not by an approval.
- An exception cannot change the archetype. A package whose real contract is a command line is not an SDK with an exception; judge it as Node CLI Internal Tool.
Anti-patterns¶
- Publishing
distJavaScript without matching declarations. - Allowing consumers to import undocumented
dist/internal/*paths. - Shipping
exportsfor JavaScript but relying on a single stale top-leveltypesfile. - Claiming both ESM and CJS support without testing
importandrequireconsumers against the published package. - Treating generated clients as hand-maintained files with no reproducible generator command.
- Representing every failure as
Errorwith only a message string. - Trusting API responses because the TypeScript type says they should be valid.
- Loading production tokens from
.env, global config, or cloud metadata automatically in a reusable SDK. - Making patch releases that remove fields, change error codes, or alter default retries/timeouts in observable ways.
Promotion criteria¶
This charter can be cut as typescript-sdk/v1 when all of the following are true.
- Every candidate rule is rewritten in the rule-contract rule template, with severity, why,
evidence, exception, a
vcqascanner or human-review signal, and a good/bad example. - Every candidate rule has been judged against
ref-typescript-sdkat a named commit, with the pass or fail recorded. The repo now exists and its score evidence is incompositions.json(#14), which closes half of this criterion; the remaining half is the binding gap, because its report evidences the required implementation without judging R-SDK-1 to R-SDK-12 one by one. - The packed-artifact evidence above is produced by a real job, so the resolution-matrix rules are checkable rather than aspirational.
- R-SDK-11's "SemVer covers types" claim has a concrete check — an API-surface snapshot or declaration diff — rather than reviewer judgement alone.
- A fresh independent assessment scores this page above the
draftband, replacing the dated report linked below. - The registry entry gains a
v1edition with reviewed, next-review, targets, and lifecycle metadata, and the page is rewritten to the authored charter bar in Standards Authoring.
Review cadence¶
While this charter is a candidate rubric it is reviewed:
- whenever TypeScript changes module resolution behaviour or declaration emit, which moves R-SDK-3 directly;
- whenever Node changes
exportscondition resolution or the supported LTS line; - whenever a reference implementation for this stack is created or scored;
- and in any case no later than six months after the date of the most recent assessment report linked below.
Benefits¶
- Cloudflare SaaS example SDK.
- future VCQA schema/client packages.
Independent Assessment¶
That report is a dated snapshot of this page on 2026-07-25, before it carried severity, an exception policy, promotion criteria, or a review cadence. It is not rewritten, and its score is not restated here as current; a fresh assessment is a promotion criterion above.