@uplink-code/vocabulary
v0.2.0
Published
Uplink semantic vocabulary — zod schemas + TS types + JSON Schema + JSON-LD context for connector output types (Paystub, Employment, Coverage, Policy, Route, Vehicle, SportsActivity, Claim, AggregateStat).
Readme
Uplink Semantic Vocabulary
Canonical entity types that connector bundles emit. Consumers (Trove, chatbots, dashboards, ETL, whatever) reason about output at the level of what a thing is rather than how a specific connector shaped its response.
Type identifiers use the uplink: URI prefix. Arrays are
denoted by [] suffix — e.g. uplink:Route[].
Design
- Semantic, not presentational. Types describe entities — no guidance about rendering. That's the consumer's decision.
- Additive. New types don't break older consumers; older consumers simply don't know about the new type and fall back to whatever their default handler is (raw JSON, drop, etc.).
- Versioned. Once a type ships, its shape is frozen at
v1. Breaking changes bump touplink:Route/v2— consumers can support multiple versions during migration. - Bundle-declared. A connector's action manifest declares
outputType: 'uplink:Route[]'so consumers can discover typed outputs without executing the action.
Layout
vocabulary/
package.json @uplink-code/vocabulary (npm package)
tsconfig.build.json
README.md this file
schemas/
AggregateStat.json uplink:AggregateStat v1
Claim.json uplink:Claim v1
Coverage.json uplink:Coverage v1
Employment.json uplink:Employment v1
Paystub.json uplink:Paystub v1
Policy.json uplink:Policy v1
Route.json uplink:Route v1
SportsActivity.json uplink:SportsActivity v1
Vehicle.json uplink:Vehicle v1
src/
<type>.ts zod schema + inferred TS type per vocabulary type
context.ts JSON-LD @context map
ld.ts annotate() helper
index.ts re-exports
dist/ built JS + .d.ts (gitignored)Each schemas/*.json file is a JSON Schema
(draft 2020-12); the $id field is the canonical type identifier.
The src/ directory carries the same shapes as zod schemas + inferred
TS types for runtime consumers — bundles import them via the published
package rather than re-declaring, so a change to a vocabulary type
lands in one place.
The two representations are kept in sync by hand today. When the vocabulary surface stabilizes, we'll pick one (zod or JSON Schema) as the source of truth and derive the other.
Consuming from a bundle
import { PaystubSchema, type Paystub, annotate } from "@uplink/vocabulary";
const paystub: Paystub = PaystubSchema.parse(raw);
return annotate(paystub, "uplink:Paystub/v1"); // stamps @context/@typeBundles resolve @uplink/vocabulary via their deno.json imports map
to npm:@uplink-code/vocabulary@^0.1.0 — same pattern as
@uplink/connector.
annotate() is optional. It embeds the JSON-LD @context + @type
on the wire payload so downstream consumers (LLMs, partners, stored
records) can identify the type without side-channel metadata. If
ctx.transform() already tags the transform event with a
semanticModel, embedding is duplicative — skip it unless the payload
will be consumed outside the invocation context.
Consuming from other repos
Any Node / TS repo installs @uplink-code/vocabulary from npm:
import { PaystubSchema, type Paystub } from "@uplink-code/vocabulary";Consumers that only need the JSON Schemas (validators, code-gen for
other languages, docs) can point at
node_modules/@uplink-code/vocabulary/schemas/*.json.
Where this lives
The vocabulary is a package inside the connectors repo, published to
npm and GitHub Packages as @uplink-code/vocabulary. Bundles import
it via the @uplink/vocabulary alias (mapped in each bundle's
deno.json), matching the @uplink/connector pattern. Other repos
(fishbone, console, docs, iOS SDK) install @uplink-code/vocabulary
directly.
Adding a type
- Draft the JSON Schema at
schemas/{Name}.jsonwith$id: "uplink:{Name}/v1". - Add the zod schema + TS type at
src/{name}.ts, mirroring the JSON Schema. - Re-export from
src/index.ts. Add the type tocontext.ts. - Bump
package.jsonversion. Merge to main → publish workflow ships it. - Update any connector bundles that should emit the new type in their
outputType. - Consumers add renderers/handlers for the new type at their own pace.
