Skip to content

r.config(...)

r.config(...) deklariert konfigurierbare Variablen für ein Feature. Jede Variable hat einen Scope (system/tenant/user), einen Default, Access-Control, optionale Bounds, und eine Resolution-Cascade.

import { createTenantConfig, createSystemConfig } from "@cosmicdrift/kumiko-framework/engine";
export function createCheckoutFeature() {
return r({
id: "checkout",
deps: { config: "config" },
init: (ctx) => { /* ... */ },
}).config({
keys: {
minOrderValue: createTenantConfig("number", {
default: 10,
bounds: { min: 0, max: 10_000 },
}),
newCheckoutEnabled: createSystemConfig("boolean", {
default: false,
read: access.admin,
write: access.systemAdmin,
}),
},
});
}

Features können Initialwerte deklarieren, die beim ersten Boot automatisch geschrieben werden:

r.config({
keys: {
themeColor: createTenantConfig("string", { default: "#000" }),
},
seeds: {
themeColor: createTenantSeed("#6366f1"),
welcomeText: createSystemSeed("Welcome to Cosmic Drift!"),
},
});

Mechanik: Seeds gehen durch den Event-Store (executor.create), nicht direct-DB. Deterministische Aggregate-ID (UUIDv5 aus key+tenantId+userId) → Re-Boot überschreibt keine existierenden Admin-Overrides. insert-only via expectedVersion: 0version_conflict bei erneutem Seed.

Der resolver liefert pro Key den Source-Layer:

const { value, source } = await resolver.getWithSource(
qualifiedKey, keyDef, tenantId, userId, db,
);
// source ∈ "user-row" | "tenant-row" | "system-row" | "app-override"
// | "computed" | "default" | "missing"

Im UI zeigt die ConfigEdit-Komponente per ConfigSourceBadge einen farbigen Indikator pro Feld (System=purple, Tenant=green, User=blue, etc.).

User-Row (wenn scope:user)
Tenant-Row (wenn scope:tenant oder :user)
System-Row (immer geprüft)
App-Boot-Override
Seed-Wert (beim ersten Boot geschrieben, danach überschreibbar)
Key-Default (in r.config Deklaration)

Details siehe Configuration Layers.


From packages/framework/src/engine/feature-ast/patterns.ts -> ConfigPattern