@cosmicdrift/kumiko-samples 0.351.0 → 0.353.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/bundled-features/package.json +2 -2
- package/packages/bundled-features/src/agent-tools/agent-manifest.ts +15 -2
- package/packages/bundled-features/src/agent-tools/changes.json +12 -0
- package/packages/bundled-features/src/agent-tools/manifest-deny-qns.ts +25 -0
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +4 -1
- package/packages/bundled-features/src/audit/changes.json +6 -0
- package/packages/bundled-features/src/audit/handlers/list.query.ts +20 -10
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +2 -3
- package/packages/bundled-features/src/auth-mfa/screens.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +3 -4
- package/packages/bundled-features/src/billing-foundation/checkout-core.ts +14 -2
- package/packages/bundled-features/src/billing-foundation/handlers/start-plan-checkout.write.ts +7 -1
- package/packages/bundled-features/src/cap-counter/book-cap-usage.ts +95 -54
- package/packages/bundled-features/src/cap-counter/cap-reservation.ts +247 -0
- package/packages/bundled-features/src/cap-counter/changes.json +28 -0
- package/packages/bundled-features/src/cap-counter/constants.ts +8 -0
- package/packages/bundled-features/src/cap-counter/feature.ts +7 -0
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +5 -0
- package/packages/bundled-features/src/cap-counter/index.ts +9 -0
- package/packages/bundled-features/src/cap-counter/payload-field.ts +10 -0
- package/packages/bundled-features/src/cap-counter/reservation-chain.ts +51 -0
- package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +3 -0
- package/packages/bundled-features/src/cap-counter/tables.ts +53 -0
- package/packages/bundled-features/src/cap-counter/value-cap-guard.ts +70 -0
- package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +63 -70
- package/packages/bundled-features/src/cap-overview/access.ts +2 -9
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +5 -2
- package/packages/bundled-features/src/cap-overview/handlers/tenant-options.query.ts +6 -9
- package/packages/bundled-features/src/channel-discord/feature.ts +1 -0
- package/packages/bundled-features/src/channel-slack/feature.ts +1 -0
- package/packages/bundled-features/src/channel-teams/feature.ts +1 -0
- package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +5 -4
- package/packages/bundled-features/src/config/handlers/values.query.ts +7 -2
- package/packages/bundled-features/src/delivery/attempt-log-retention.ts +40 -0
- package/packages/bundled-features/src/delivery/attempt-log.ts +26 -3
- package/packages/bundled-features/src/delivery/changes.json +12 -0
- package/packages/bundled-features/src/delivery/constants.ts +1 -0
- package/packages/bundled-features/src/delivery/events.ts +3 -0
- package/packages/bundled-features/src/delivery/feature.ts +50 -2
- package/packages/bundled-features/src/delivery/index.ts +6 -0
- package/packages/bundled-features/src/delivery/mask-recipient-address.ts +40 -0
- package/packages/bundled-features/src/delivery/public-names.ts +6 -1
- package/packages/bundled-features/src/delivery/types.ts +12 -2
- package/packages/bundled-features/src/derivatives-sharp/changes.json +6 -0
- package/packages/bundled-features/src/files-tenant-data/hooks.ts +3 -2
- package/packages/bundled-features/src/folders/feature.ts +2 -12
- package/packages/bundled-features/src/form-draft/changes.json +7 -1
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +4 -2
- package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +18 -6
- package/packages/bundled-features/src/jobs/handlers/list.query.ts +44 -11
- package/packages/bundled-features/src/jobs/i18n.ts +1 -0
- package/packages/bundled-features/src/ledger/entity.ts +4 -0
- package/packages/bundled-features/src/ledger/schemas.ts +8 -2
- package/packages/bundled-features/src/legal-pages/README.md +3 -3
- package/packages/bundled-features/src/legal-pages/changes.json +6 -0
- package/packages/bundled-features/src/managed-pages/changes.json +6 -0
- package/packages/bundled-features/src/managed-pages/feature.ts +24 -11
- package/packages/bundled-features/src/notes-history/feature.ts +2 -12
- package/packages/bundled-features/src/personal-access-tokens/screens.ts +24 -3
- package/packages/bundled-features/src/renderer-foundation/types.ts +1 -1
- package/packages/bundled-features/src/renderer-simple/changes.json +6 -0
- package/packages/bundled-features/src/renderer-simple/feature.ts +4 -6
- package/packages/bundled-features/src/renderer-simple/index.ts +1 -0
- package/packages/bundled-features/src/renderer-simple/mail-blocks.ts +138 -0
- package/packages/bundled-features/src/renderer-simple/simple-renderer.ts +33 -4
- package/packages/bundled-features/src/seo/changes.json +5 -0
- package/packages/bundled-features/src/seo/feature.ts +23 -7
- package/packages/bundled-features/src/shared/assert-no-where-rule-in-ownership-write.ts +25 -0
- package/packages/bundled-features/src/shared/index.ts +2 -1
- package/packages/bundled-features/src/shared/rate-limited-text-response.ts +11 -0
- package/packages/bundled-features/src/tags/feature.ts +2 -12
- package/packages/bundled-features/src/tenant/changes.json +7 -0
- package/packages/bundled-features/src/tenant/decrypt-tenant-names.ts +17 -0
- package/packages/bundled-features/src/tenant/handlers/me.query.ts +4 -1
- package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +7 -3
- package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +11 -5
- package/packages/bundled-features/src/tenant/index.ts +1 -0
- package/packages/bundled-features/src/tenant/schema/tenant.ts +4 -6
- package/packages/bundled-features/src/tenant/screens.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/changes.json +6 -0
- package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +12 -19
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -0
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +5 -0
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +23 -1
- package/packages/bundled-features/src/tier-engine/changes.json +6 -0
- package/packages/bundled-features/src/tier-engine/index.ts +7 -0
- package/packages/bundled-features/src/tier-engine/tier-option-gate.ts +148 -0
- package/packages/bundled-features/src/user/handlers/list.query.ts +5 -2
- package/packages/bundled-features/src/user-data-rights/boot-checks.ts +7 -0
- package/packages/bundled-features/src/user-data-rights/deletion-token.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +2 -2
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +36 -6
- package/packages/bundled-features/src/workflow-runner/changes.json +5 -0
- package/packages/bundled-features/src/workflow-runner/event-trigger.ts +11 -3
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +5 -0
- package/samples/apps/marketing-demo/src/app/seed-data.ts +2 -2
- package/samples/apps/showcase/src/features/items/schema/item.ts +0 -1
- package/samples/apps/styleguide/src/app/shell.tsx +1 -1
- package/samples/apps/styleguide/src/features/gallery/web/Gallery.tsx +9 -3
- package/samples/apps/styleguide/src/features/widgets/demo-locale.ts +47 -0
- package/samples/apps/styleguide/src/features/widgets/feature.ts +48 -15
- package/samples/apps/styleguide/src/features/widgets/i18n.ts +28 -0
- package/samples/apps/styleguide/src/features/widgets/web/DashboardFilterEcho.tsx +5 -4
- package/samples/apps/ui-walkthrough/src/app/assistant-action.tsx +6 -5
- package/samples/apps/ui-walkthrough/src/app/shell.tsx +3 -2
- package/samples/apps/ui-walkthrough/src/features/tasks/i18n.ts +8 -0
- package/samples/recipes/files-post-processing/package.json +1 -1
- package/samples/recipes/public-share-token/README.md +4 -5
- package/samples/recipes/public-share-token/src/feature.ts +1 -1
- package/samples/recipes/security-baseline/README.md +6 -0
- package/samples/recipes/seed-migration/README.md +13 -1
- package/samples/recipes/tenant-settings/README.md +1 -1
- package/packages/bundled-features/src/shared/has-where-rule.ts +0 -11
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
+
import { demoMoney, demoMonthYear, demoPercent, demoText } from "./demo-locale";
|
|
8
9
|
import { WIDGETS_I18N } from "./i18n";
|
|
9
10
|
|
|
10
11
|
// Statische Demo-Zeitreihe (48 Punkte à 30 Minuten) — kein Date-API,
|
|
@@ -33,6 +34,13 @@ const INBOX_MESSAGES = Array.from({ length: 18 }, (_, i) => ({
|
|
|
33
34
|
unread: i % 4 === 0,
|
|
34
35
|
}));
|
|
35
36
|
|
|
37
|
+
function openAmount(amount: number, locale: string): string {
|
|
38
|
+
return demoText("widgets:dashboard:demo-amount-open", locale).replace(
|
|
39
|
+
"{amount}",
|
|
40
|
+
demoMoney(amount, "EUR", locale),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
37
45
|
r.screen({ id: "widgets", type: "custom", renderer: { react: { __component: "widgets" } } });
|
|
38
46
|
r.screen({
|
|
@@ -129,11 +137,14 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
129
137
|
r.queryHandler(
|
|
130
138
|
"metrics:portfolio-stat",
|
|
131
139
|
z.object({ region: z.string().optional() }),
|
|
132
|
-
async ({ payload: { region } }) => ({
|
|
133
|
-
value:
|
|
134
|
-
|
|
140
|
+
async ({ payload: { region } }, ctx) => ({
|
|
141
|
+
value:
|
|
142
|
+
region === "us"
|
|
143
|
+
? demoMoney(38120, "USD", ctx.locale)
|
|
144
|
+
: demoMoney(region === "eu" ? 54630 : 92753, "EUR", ctx.locale),
|
|
145
|
+
sub: demoText("widgets:catalog:portfolio-sub", ctx.locale),
|
|
135
146
|
tone: "positive",
|
|
136
|
-
delta:
|
|
147
|
+
delta: demoPercent(0.12, ctx.locale),
|
|
137
148
|
deltaDirection: "up",
|
|
138
149
|
deltaTone: "positive",
|
|
139
150
|
}),
|
|
@@ -150,7 +161,7 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
150
161
|
r.queryHandler(
|
|
151
162
|
"metrics:net-worth-assets",
|
|
152
163
|
z.object({ region: z.string().optional() }),
|
|
153
|
-
async () => ({ value: "
|
|
164
|
+
async (_query, ctx) => ({ value: demoMoney(120000, "EUR", ctx.locale) }),
|
|
154
165
|
{
|
|
155
166
|
access: {
|
|
156
167
|
openToAll: {
|
|
@@ -164,7 +175,7 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
164
175
|
r.queryHandler(
|
|
165
176
|
"metrics:net-worth-debts",
|
|
166
177
|
z.object({ region: z.string().optional() }),
|
|
167
|
-
async () => ({ value: "
|
|
178
|
+
async (_query, ctx) => ({ value: demoMoney(65370, "EUR", ctx.locale) }),
|
|
168
179
|
{
|
|
169
180
|
access: {
|
|
170
181
|
openToAll: {
|
|
@@ -196,10 +207,18 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
196
207
|
r.queryHandler(
|
|
197
208
|
"metrics:latest-items",
|
|
198
209
|
z.object({}),
|
|
199
|
-
async () => ({
|
|
210
|
+
async (_query, ctx) => ({
|
|
200
211
|
rows: [
|
|
201
|
-
{
|
|
202
|
-
|
|
212
|
+
{
|
|
213
|
+
id: "i1",
|
|
214
|
+
name: demoText("widgets:dashboard:demo-incident-timeout", ctx.locale),
|
|
215
|
+
status: "resolved",
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: "i2",
|
|
219
|
+
name: demoText("widgets:dashboard:demo-incident-certificate", ctx.locale),
|
|
220
|
+
status: "done",
|
|
221
|
+
},
|
|
203
222
|
],
|
|
204
223
|
nextCursor: null,
|
|
205
224
|
}),
|
|
@@ -249,10 +268,16 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
249
268
|
r.queryHandler(
|
|
250
269
|
"metrics:upcoming-events",
|
|
251
270
|
z.object({}),
|
|
252
|
-
async () => ({
|
|
271
|
+
async (_query, ctx) => ({
|
|
253
272
|
rows: [
|
|
254
|
-
{
|
|
255
|
-
|
|
273
|
+
{
|
|
274
|
+
primary: demoText("widgets:dashboard:demo-event-rate-adjustment", ctx.locale),
|
|
275
|
+
trailing: demoMonthYear(2026, 8, ctx.locale),
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
primary: demoText("widgets:dashboard:demo-event-savings-contract", ctx.locale),
|
|
279
|
+
trailing: demoMonthYear(2026, 10, ctx.locale),
|
|
280
|
+
},
|
|
256
281
|
],
|
|
257
282
|
}),
|
|
258
283
|
{
|
|
@@ -268,10 +293,18 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
268
293
|
r.queryHandler(
|
|
269
294
|
"metrics:goal-progress",
|
|
270
295
|
z.object({}),
|
|
271
|
-
async () => ({
|
|
296
|
+
async (_query, ctx) => ({
|
|
272
297
|
rows: [
|
|
273
|
-
{
|
|
274
|
-
|
|
298
|
+
{
|
|
299
|
+
label: demoText("widgets:dashboard:demo-goal-mortgage", ctx.locale),
|
|
300
|
+
value: openAmount(42000, ctx.locale),
|
|
301
|
+
fraction: 0.71,
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
label: demoText("widgets:dashboard:demo-goal-car-loan", ctx.locale),
|
|
305
|
+
value: openAmount(3200, ctx.locale),
|
|
306
|
+
fraction: 0.92,
|
|
307
|
+
},
|
|
275
308
|
],
|
|
276
309
|
}),
|
|
277
310
|
{
|
|
@@ -27,6 +27,34 @@ export const WIDGETS_I18N = {
|
|
|
27
27
|
"widgets:dashboard:filter-region": { de: "Region", en: "Region" },
|
|
28
28
|
"widgets:dashboard:filter-region-eu": { de: "Europa", en: "Europe" },
|
|
29
29
|
"widgets:dashboard:filter-region-us": { de: "USA", en: "USA" },
|
|
30
|
+
"widgets:dashboard:filter-echo-title": { de: "Custom-Panel", en: "Custom panel" },
|
|
31
|
+
"widgets:dashboard:filter-echo-filtered": {
|
|
32
|
+
de: "Gefiltert nach Region: {region}",
|
|
33
|
+
en: "Filtered by region: {region}",
|
|
34
|
+
},
|
|
35
|
+
"widgets:dashboard:filter-echo-unfiltered": {
|
|
36
|
+
de: "Ungefiltert (alle Regionen)",
|
|
37
|
+
en: "Unfiltered (all regions)",
|
|
38
|
+
},
|
|
39
|
+
"widgets:dashboard:demo-incident-timeout": {
|
|
40
|
+
de: "API-Timeout eu-central",
|
|
41
|
+
en: "API timeout eu-central",
|
|
42
|
+
},
|
|
43
|
+
"widgets:dashboard:demo-incident-certificate": {
|
|
44
|
+
de: "Zertifikat erneuert",
|
|
45
|
+
en: "Certificate renewed",
|
|
46
|
+
},
|
|
47
|
+
"widgets:dashboard:demo-event-rate-adjustment": {
|
|
48
|
+
de: "Zinsanpassung Baudarlehen",
|
|
49
|
+
en: "Mortgage rate adjustment",
|
|
50
|
+
},
|
|
51
|
+
"widgets:dashboard:demo-event-savings-contract": {
|
|
52
|
+
de: "Bausparvertrag zuteilungsreif",
|
|
53
|
+
en: "Building savings contract ready for allocation",
|
|
54
|
+
},
|
|
55
|
+
"widgets:dashboard:demo-goal-mortgage": { de: "Baudarlehen", en: "Mortgage" },
|
|
56
|
+
"widgets:dashboard:demo-goal-car-loan": { de: "Autokredit", en: "Car loan" },
|
|
57
|
+
"widgets:dashboard:demo-amount-open": { de: "{amount} offen", en: "{amount} outstanding" },
|
|
30
58
|
"widgets:catalog:portfolio": { de: "Portfolio", en: "Portfolio" },
|
|
31
59
|
"widgets:catalog:portfolio-sub": { de: "über 4 Konten", en: "across 4 accounts" },
|
|
32
60
|
"widgets:catalog:remaining-debt": { de: "Restschuld", en: "Remaining debt" },
|
|
@@ -3,18 +3,19 @@
|
|
|
3
3
|
// gewählten Screen-Filter-Wert über `filterParams` sieht (siehe
|
|
4
4
|
// DashboardFilterDefinition in feature.ts).
|
|
5
5
|
|
|
6
|
-
import type
|
|
6
|
+
import { type ExtensionSectionProps, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
7
7
|
import { SectionCard } from "@cosmicdrift/kumiko-renderer-web";
|
|
8
8
|
import type { ReactNode } from "react";
|
|
9
9
|
|
|
10
10
|
export function DashboardFilterEcho({ filterParams }: ExtensionSectionProps): ReactNode {
|
|
11
|
+
const t = useTranslation();
|
|
11
12
|
const region = filterParams?.["region"];
|
|
12
13
|
return (
|
|
13
|
-
<SectionCard title="
|
|
14
|
+
<SectionCard title={t("widgets:dashboard:filter-echo-title")}>
|
|
14
15
|
<p className="text-sm text-muted-foreground">
|
|
15
16
|
{typeof region === "string"
|
|
16
|
-
?
|
|
17
|
-
: "
|
|
17
|
+
? t("widgets:dashboard:filter-echo-filtered", { region })
|
|
18
|
+
: t("widgets:dashboard:filter-echo-unfiltered")}
|
|
18
19
|
</p>
|
|
19
20
|
</SectionCard>
|
|
20
21
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { usePrimitives } from "@cosmicdrift/kumiko-renderer";
|
|
1
|
+
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
2
2
|
import { WandSparkles } from "lucide-react";
|
|
3
3
|
import { type ReactNode, useEffect, useState } from "react";
|
|
4
4
|
|
|
@@ -6,6 +6,7 @@ const noop = (): void => {};
|
|
|
6
6
|
|
|
7
7
|
export function AssistantAction(): ReactNode {
|
|
8
8
|
const { Dialog } = usePrimitives();
|
|
9
|
+
const t = useTranslation();
|
|
9
10
|
const [open, setOpen] = useState(false);
|
|
10
11
|
|
|
11
12
|
// Registered here on purpose: an overflow menu that unmounts this component
|
|
@@ -30,7 +31,7 @@ export function AssistantAction(): ReactNode {
|
|
|
30
31
|
className="inline-flex h-9 items-center gap-2 rounded-md border border-border bg-card px-3 text-sm font-medium text-foreground hover:bg-accent"
|
|
31
32
|
>
|
|
32
33
|
<WandSparkles className="h-4 w-4" aria-hidden="true" />
|
|
33
|
-
|
|
34
|
+
{t("tasks.assistant.label")}
|
|
34
35
|
<kbd className="rounded border border-border px-1 font-sans text-xs text-muted-foreground">
|
|
35
36
|
⌘K
|
|
36
37
|
</kbd>
|
|
@@ -38,9 +39,9 @@ export function AssistantAction(): ReactNode {
|
|
|
38
39
|
<Dialog
|
|
39
40
|
open={open}
|
|
40
41
|
onOpenChange={setOpen}
|
|
41
|
-
title="
|
|
42
|
-
description="
|
|
43
|
-
confirmLabel="
|
|
42
|
+
title={t("tasks.assistant.label")}
|
|
43
|
+
description={t("tasks.assistant.description")}
|
|
44
|
+
confirmLabel={t("tasks.assistant.close")}
|
|
44
45
|
onConfirm={noop}
|
|
45
46
|
testId="assistant-dialog"
|
|
46
47
|
/>
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
SidebarBrand,
|
|
14
14
|
ThemeMenuItem,
|
|
15
15
|
ThemeToggle,
|
|
16
|
+
useTranslation,
|
|
16
17
|
} from "@cosmicdrift/kumiko-renderer-web";
|
|
17
18
|
import { MoonStar, Sun } from "lucide-react";
|
|
18
19
|
import type { ReactNode } from "react";
|
|
@@ -20,7 +21,6 @@ import { AssistantAction } from "./assistant-action";
|
|
|
20
21
|
import { BETA_TENANT_ID, DEV_TENANT_ID } from "./auth-constants";
|
|
21
22
|
|
|
22
23
|
const APP_NAME = "Kumiko Walkthrough";
|
|
23
|
-
const APP_TAGLINE = "Design-Referenz";
|
|
24
24
|
|
|
25
25
|
const tenantName = (tenantId: string): string => {
|
|
26
26
|
if (tenantId === DEV_TENANT_ID) return "Dev Tenant";
|
|
@@ -40,9 +40,10 @@ export function AppShell({
|
|
|
40
40
|
readonly children: ReactNode;
|
|
41
41
|
readonly schema: AppSchema;
|
|
42
42
|
}): ReactNode {
|
|
43
|
+
const t = useTranslation();
|
|
43
44
|
return (
|
|
44
45
|
<DefaultAppShell
|
|
45
|
-
brand={<SidebarBrand name={APP_NAME} plan={
|
|
46
|
+
brand={<SidebarBrand name={APP_NAME} plan={t("tasks.shell.tagline")} />}
|
|
46
47
|
schema={schema}
|
|
47
48
|
headerActions={
|
|
48
49
|
<>
|
|
@@ -5,6 +5,10 @@ import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
|
5
5
|
|
|
6
6
|
export const tasksTranslations: TranslationsByLocale = {
|
|
7
7
|
de: {
|
|
8
|
+
"tasks.shell.tagline": "Design-Referenz",
|
|
9
|
+
"tasks.assistant.label": "Assistent",
|
|
10
|
+
"tasks.assistant.description": "Der Assistent ist im Walkthrough nicht angebunden.",
|
|
11
|
+
"tasks.assistant.close": "Schließen",
|
|
8
12
|
"tasks.nav.group": "Allgemein",
|
|
9
13
|
"tasks.nav.list": "Aufgaben",
|
|
10
14
|
"tasks.nav.new": "Neue Aufgabe",
|
|
@@ -21,6 +25,10 @@ export const tasksTranslations: TranslationsByLocale = {
|
|
|
21
25
|
"tasks:entity:task:field:notes": "Notizen",
|
|
22
26
|
},
|
|
23
27
|
en: {
|
|
28
|
+
"tasks.shell.tagline": "Design reference",
|
|
29
|
+
"tasks.assistant.label": "Assistant",
|
|
30
|
+
"tasks.assistant.description": "The assistant is not connected in the walkthrough.",
|
|
31
|
+
"tasks.assistant.close": "Close",
|
|
24
32
|
"tasks.nav.group": "General",
|
|
25
33
|
"tasks.nav.list": "Tasks",
|
|
26
34
|
"tasks.nav.new": "New task",
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
Minimal pattern for **tokenized anonymous read surfaces**: authenticated users
|
|
4
4
|
mint a link; visitors resolve it without login.
|
|
5
5
|
|
|
6
|
-
Domain-agnostic — no credit/folder logic.
|
|
7
|
-
|
|
8
|
-
(`share-by-token` + 5 layout templates).
|
|
6
|
+
Domain-agnostic — no credit/folder logic. A full consumer adds snapshots,
|
|
7
|
+
layout templates and tier gates on top.
|
|
9
8
|
|
|
10
9
|
## What it shows
|
|
11
10
|
|
|
@@ -16,8 +15,8 @@ Domain-agnostic — no credit/folder logic. Full consumer:
|
|
|
16
15
|
- **`anonymousAccess`** on test stack (see integration test)
|
|
17
16
|
|
|
18
17
|
Client wiring: [`recipes/apex-surface-auth`](../apex-surface-auth/) or a gate
|
|
19
|
-
before `createKumikoApp` (
|
|
20
|
-
|
|
18
|
+
before `createKumikoApp` (a small gate component that renders the public view when
|
|
19
|
+
the URL carries a share token).
|
|
21
20
|
|
|
22
21
|
## Handlers
|
|
23
22
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Pattern: authenticated create → plain token show-once → anonymous
|
|
4
4
|
// read-by-token with SHA-256 lookup. Revoke sets revokedAt via executor.
|
|
5
5
|
//
|
|
6
|
-
//
|
|
6
|
+
// A full consumer adds domain snapshots, layouts and tier gates on top.
|
|
7
7
|
|
|
8
8
|
import { generateToken } from "@cosmicdrift/kumiko-framework/api";
|
|
9
9
|
import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
@@ -54,6 +54,12 @@ export const APP_FEATURES = [
|
|
|
54
54
|
For an app that does not mount `dsgvoSelfServiceFeatures()`, use
|
|
55
55
|
`securityBaselineFeatures()` with its default options, as this recipe does.
|
|
56
56
|
|
|
57
|
+
Dedupe keeps the first mounted instance. Late-bound state such as
|
|
58
|
+
`bindAutoRevokeOnPasswordChange` must be bound on the instance returned by
|
|
59
|
+
`composeFeatures`/`createApp`, not on a locally held handle to the dropped one:
|
|
60
|
+
the dropped instance's hooks never run and password changes silently stop
|
|
61
|
+
revoking sessions.
|
|
62
|
+
|
|
57
63
|
A `createSessionsFeature({ ... })` mounted with different options than the
|
|
58
64
|
preset's own no-arg instance still produces a clear boot error — dedupe only
|
|
59
65
|
collapses provably interchangeable instances, never silently picks one:
|
|
@@ -5,7 +5,7 @@ File-based migrations for Event-Sourcing operations — like `kumiko schema appl
|
|
|
5
5
|
## What it shows
|
|
6
6
|
|
|
7
7
|
- **`seedsDir`-Option** in `runProdApp({ seedsDir: "./seeds" })` — beim Boot werden pending Files in chronologischer Reihenfolge angewendet und in `kumiko_es_operations` markiert.
|
|
8
|
-
- **`SeedMigration`-Interface** — default-Export einer seed-File mit `description` + `run(ctx)`. ctx liefert `systemWriteAs` (System-User bypassed Access-Check) + Read-Helpers (`findUserByEmail`, `findMembershipsOfUser`, `findTenants`).
|
|
8
|
+
- **`SeedMigration`-Interface** — default-Export einer seed-File mit `description` + `run(ctx)`. ctx liefert `systemWriteAs` (System-User bypassed Access-Check) + Read-Helpers (`findUserByEmail`, `findMembershipsOfUser`, `findTenants`, `findTemplateResources`).
|
|
9
9
|
- **Idempotency** — Marker landet nach Erfolg in der Tracking-Tabelle, zweiter Boot skipped applied Seeds.
|
|
10
10
|
- **Tx-Atomicity** — Jede Migration läuft in eigener Transaction; Failure rollt zurück + bricht Boot ab (kein Partial-Apply).
|
|
11
11
|
- **Chronologische File-IDs** — Filename `<date>-<slug>.ts` (z.B. `2026-05-20-fix-admin-roles.ts`) ist die ID.
|
|
@@ -35,6 +35,18 @@ seed: 2026-05-20-fix-admin-roles.ts
|
|
|
35
35
|
|
|
36
36
|
Bei typo / drift fail-t mit klarer message + exit-code 1 — CI nutzt es als prä-build-step. App-Author muss in `smoke.ts` den `features`-Array gegen die eigene App-Feature-Set tauschen (siehe TODO im File).
|
|
37
37
|
|
|
38
|
+
### Archive template rows
|
|
39
|
+
|
|
40
|
+
`findTemplateResources({ slug?, kind?, status?, locale?, tenantId? })` replaces a raw `SELECT … FROM read_template_resources`. It defaults to the system tenant and returns `[]` when template-resolver is not mounted:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
for (const t of await ctx.findTemplateResources({ kind: "notification", status: "active" })) {
|
|
44
|
+
await ctx.systemWriteAs("template-resolver:write:archive", { id: t.id }, SYSTEM_TENANT_ID, [
|
|
45
|
+
"SystemAdmin",
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
38
50
|
## When to reach for it
|
|
39
51
|
|
|
40
52
|
Du hast einen idempotent-Seeder der bei initialer Erstellung „Insert wenn nicht existiert" macht (z.B. `auth.admin.memberships`), und dann ändern sich die Soll-Daten — neue Rolle, anderer Tier, korrigierte Bezeichnung. Idempotent-Seeder skippen die existing Rows → DB driftet vom Code-Stand ab.
|
|
@@ -20,7 +20,7 @@ import { defineCreateWithTenantDefaults } from "@cosmicdrift/kumiko-bundled-feat
|
|
|
20
20
|
export const invoiceEntity = createEntity({
|
|
21
21
|
table: "read_invoices",
|
|
22
22
|
fields: {
|
|
23
|
-
title: createTextField({ required: true }),
|
|
23
|
+
title: createTextField({ personal: false, reason: "is_business_data", required: true }),
|
|
24
24
|
amount: createMoneyField({ required: true }),
|
|
25
25
|
language: createSelectField({ options: ["en", "de", "fr"] as const }),
|
|
26
26
|
},
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { OwnershipMap } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
|
|
3
|
-
// `where`-rules are read-path only (buildOwnershipClause). The write path
|
|
4
|
-
// decides in memory against the concrete row, so a where-rule there can only
|
|
5
|
-
// ever deny — boot validation rejects the shape (fw#2626). Feature factories
|
|
6
|
-
// that accept an `ownership` option reject it earlier, at build time, so the
|
|
7
|
-
// author gets the option name in the message instead of an entity scope.
|
|
8
|
-
export function hasWhereRule(map: OwnershipMap | undefined): boolean {
|
|
9
|
-
if (!map) return false;
|
|
10
|
-
return Object.values(map).some((rule) => rule !== "all" && rule.kind === "where");
|
|
11
|
-
}
|