Meta Overview
meta.svc distributes product definitions. A product on kis.ai is a git monorepo with one folder per service block (data/, iam/, pages/, …); each generic block fetches its folder through meta and morphs itself into the specific application. Git is the source of truth — meta is the gateway and distributor in front of it.
Meta is deliberately generic and content-agnostic: it serves files by path, as raw bytes, with ETags. Interpreting a file (parsing an entity YAML, a realm definition, a page) is the consuming block’s job, never meta’s. Type-aware endpoints still exist but are being retired in favor of the raw file surface.
Meta is not the configuration plane: config.svc configures how a block runs (ports, pools, credentials); meta distributes what the product is (entities, realms, pages, workflows).
Default port: 8080.
Sources
Section titled “Sources”A product repository can be backed by:
| Type | Behavior |
|---|---|
local | A git working tree on disk — filesystem-watched, full branch/tag support, writable |
remote | A remote git URL — cloned (in memory or to a filesystem cache), re-pulled on a poll interval |
| plain folder | A directory without git — served as-is |
| embedded | Products compiled into the binary with meta embed — for appliance-style distribution |
| federation | Another meta instance, reverse-proxied |
Local-dir and remote-git sit behind the same read contract, so blocks behave identically in development and production.
One binary, three roles via -m/--mode:
meta— platform bring-up repositories.product— forge-authored product repositories (the common case).marketplace— marketplace components plus a search index.
Multi-tenancy
Section titled “Multi-tenancy”Repositories are registered per customer, each customer holding a set of products. The X-Customer header (or JWT claims) selects the customer; the product name is in the URL path. Per-repo access rules (JS expressions over the caller’s identity) and license entitlements gate access.
Change propagation
Section titled “Change propagation”- Server side — remote repos are re-pulled on a per-repo ticker (jittered); local repos are filesystem-watched. A HEAD change publishes a repo event to all SSE subscribers.
- Client side — every chassis service polls its
service/{service}/configendpoint every 15 seconds usinglastupdatedbookmarks; the response saysload: trueonly when something actually changed. Services that need file-level reactions subscribe to the SSE watch stream instead. - Reads are version-addressable: any read can pin
?version=<name>&versionType=branch|tag, validated against the repo’s allow-list.
How a block consumes meta
Section titled “How a block consumes meta”Every service block ships with the meta client built into the chassis. Per served tenant, the chassis reads meta.url (or meta.localdir for local development) from tenant config, then:
- Calls
GET /product/{id}/service/{service}/configuntil it succeeds — this returns the merged envelope: service config, product config, datastore definitions, versions, and timestamps. - Polls it every 15s; on
load: truethe block rebuilds the affected tenant. - Reads individual files through the generic byte surface (
/product/{id}/file/{path}), with a 5-minute ETag-revalidated content cache and stale-serve on transient outage.
For local development without a running meta.svc, meta.localdir points the client at a folder mirroring the same URL structure on disk.
Continue with:
- Product repository layout — what goes in the monorepo
- HTTP API — the file, git, and stream surface
- Operations — running,
meta serve, caching, failure modes