Ship toolbelt KCL fragments; reshape the example to compose them; validate at runtime #17

Closed
opened 2026-08-06 21:34:12 +00:00 by ginjiruu · 1 comment
Owner

Parent

#14 — Spec: Per-package KCL config fragments — service-owned defaults (db, embeddednats, embeddedfga)

What to build

The platform owns its config defaults in exactly one place. Each service package ships its own KCL fragment declaring that service's schema and its service-neutral defaults (db/schema.k, embeddednats/schema.k, embeddedfga/schema.k), and a toolbelt-owned core fragment (app/schema.k) owns app identity (name), Log, Session, Rebuild, and addr. The FGA File/Tuple tuple-sync schemas and the FGA-URI validate directive ride the embeddedfga fragment. Schema names (NATS, DB, FGA, Log) are preserved.

An app author composes a service's config with a one-line KCL import and never re-declares its fields: the example's schema becomes a composition under the canonical keys (nats: embeddednats.NATS = embeddednats.NATS {}, db: DB = DB { path = "data/sqlite/kanban.db" } for the app-owned filename, and so on), resolved through the example's kcl.mod. The generated field registry and typed config struct are field-for-field identical to today's, so existing app wiring keeps working, and the check-kcl drift guard stays green.

Runtime validation resolves the composed schema through the same kcl.mod path as codegen, so the schema the app authors is the schema that is validated when a .k config loads — proven by a test driving a config file → schema → fragment-import chain at runtime load.

Acceptance criteria

  • The four fragment files ship in the toolbelt, each declaring its schema(s) with service-neutral defaults; the app fragment owns Log (the universal schema), Session, Rebuild, addr, and app identity.
  • The example's schema is a canonical-key composition importing the fragments; the app-owned defaults (SQLite filename, FGA store id) are explicit composition values.
  • The example's kcl.mod wires the toolbelt fragments; codegen and runtime load resolve them.
  • Generated fields and the typed config struct are name-identical to today (no wiring churn); task check-kcl passes unchanged.
  • The FGA File/Tuple schemas and the #@kcl:validate FGA-URI directive ride the embeddedfga fragment.
  • A test proves a config file → schema.k → fragment import chain resolves at runtime load and validates against the authored schema.
  • go test ./... passes from the repo root, the tools module, and the example.

Blocked by

  • #16 — kcl-generate: resolve fragment imports and enforce the composition contract
## Parent #14 — Spec: Per-package KCL config fragments — service-owned defaults (db, embeddednats, embeddedfga) ## What to build The platform owns its config defaults in exactly one place. Each service package ships its own KCL fragment declaring that service's schema and its service-neutral defaults (`db/schema.k`, `embeddednats/schema.k`, `embeddedfga/schema.k`), and a toolbelt-owned core fragment (`app/schema.k`) owns app identity (`name`), `Log`, `Session`, `Rebuild`, and `addr`. The FGA `File`/`Tuple` tuple-sync schemas and the FGA-URI validate directive ride the embeddedfga fragment. Schema names (`NATS`, `DB`, `FGA`, `Log`) are preserved. An app author composes a service's config with a one-line KCL import and never re-declares its fields: the example's schema becomes a composition under the canonical keys (`nats: embeddednats.NATS = embeddednats.NATS {}`, `db: DB = DB { path = "data/sqlite/kanban.db" }` for the app-owned filename, and so on), resolved through the example's kcl.mod. The generated field registry and typed config struct are field-for-field identical to today's, so existing app wiring keeps working, and the `check-kcl` drift guard stays green. Runtime validation resolves the composed schema through the same kcl.mod path as codegen, so the schema the app authors is the schema that is validated when a `.k` config loads — proven by a test driving a config file → schema → fragment-import chain at runtime load. ## Acceptance criteria - [ ] The four fragment files ship in the toolbelt, each declaring its schema(s) with service-neutral defaults; the app fragment owns `Log` (the universal schema), `Session`, `Rebuild`, `addr`, and app identity. - [ ] The example's schema is a canonical-key composition importing the fragments; the app-owned defaults (SQLite filename, FGA store id) are explicit composition values. - [ ] The example's kcl.mod wires the toolbelt fragments; codegen and runtime load resolve them. - [ ] Generated fields and the typed config struct are name-identical to today (no wiring churn); `task check-kcl` passes unchanged. - [ ] The FGA `File`/`Tuple` schemas and the `#@kcl:validate` FGA-URI directive ride the embeddedfga fragment. - [ ] A test proves a config file → schema.k → fragment import chain resolves at runtime load and validates against the authored schema. - [ ] `go test ./...` passes from the repo root, the tools module, and the example. ## Blocked by - #16 — kcl-generate: resolve fragment imports and enforce the composition contract
Author
Owner

Implemented, verified (go test green in root/tools/example, task check-kcl green), and reviewed via /code-review. Landed in commit f3cbcd0 on master.

Implemented, verified (go test green in root/tools/example, task check-kcl green), and reviewed via /code-review. Landed in commit f3cbcd0 on master.
ginjiruu 2026-08-06 22:42:41 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ginjiruu/toolbelt#17
No description provided.