@cosmicdrift/kumiko-samples 0.365.0 → 0.366.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 +1 -1
- package/packages/bundled-features/src/admin-shell/feature.ts +9 -9
- package/packages/bundled-features/src/agent-tools/changes.json +6 -0
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +87 -5
- package/packages/bundled-features/src/audit/feature.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/changes.json +13 -0
- package/packages/bundled-features/src/auth-email-password/constants.ts +0 -2
- package/packages/bundled-features/src/auth-email-password/feature.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +1 -0
- package/packages/bundled-features/src/auth-mfa/feature.ts +4 -4
- package/packages/bundled-features/src/auth-mfa-user-data/index.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/feature.ts +1 -1
- package/packages/bundled-features/src/cap-counter/cap-reservation.ts +89 -28
- package/packages/bundled-features/src/cap-counter/changes.json +7 -0
- package/packages/bundled-features/src/cap-counter/constants.ts +3 -0
- package/packages/bundled-features/src/cap-counter/feature.ts +2 -2
- package/packages/bundled-features/src/cap-counter/tables.ts +5 -2
- package/packages/bundled-features/src/cap-overview/feature.ts +3 -3
- package/packages/bundled-features/src/channel-discord/feature.ts +2 -2
- package/packages/bundled-features/src/channel-email/feature.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/feature.ts +1 -1
- package/packages/bundled-features/src/channel-push/feature.ts +1 -1
- package/packages/bundled-features/src/channel-slack/feature.ts +2 -2
- package/packages/bundled-features/src/channel-teams/feature.ts +2 -2
- package/packages/bundled-features/src/channel-telegram/feature.ts +2 -2
- package/packages/bundled-features/src/compliance-profiles/feature.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles-ops/index.ts +3 -3
- package/packages/bundled-features/src/config/feature.ts +1 -1
- package/packages/bundled-features/src/crypto-shredding/changes.json +13 -0
- package/packages/bundled-features/src/custom-fields/feature.ts +2 -2
- package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +17 -13
- package/packages/bundled-features/src/data-retention/feature.ts +1 -1
- package/packages/bundled-features/src/data-retention/presets.ts +4 -4
- package/packages/bundled-features/src/delivery/changes.json +6 -0
- package/packages/bundled-features/src/delivery/db/queries/address-opt-outs.ts +6 -2
- package/packages/bundled-features/src/delivery/db/queries/preferences.ts +4 -4
- package/packages/bundled-features/src/delivery/delivery-service.ts +17 -2
- package/packages/bundled-features/src/delivery/feature.ts +9 -5
- package/packages/bundled-features/src/delivery/handlers/resubscribe-address.write.ts +12 -8
- package/packages/bundled-features/src/delivery/handlers/resubscribe-user.write.ts +3 -1
- package/packages/bundled-features/src/delivery/handlers/set-preference.write.ts +3 -1
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-address.write.ts +3 -1
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-user.write.ts +3 -1
- package/packages/bundled-features/src/delivery/notification-type-aliases.ts +13 -0
- package/packages/bundled-features/src/derivatives-sharp/feature.ts +1 -1
- package/packages/bundled-features/src/document-ingest-foundation/feature.ts +2 -2
- package/packages/bundled-features/src/file-derivatives/feature.ts +3 -3
- package/packages/bundled-features/src/file-foundation/feature.ts +1 -1
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +2 -2
- package/packages/bundled-features/src/file-provider-s3/feature.ts +3 -3
- package/packages/bundled-features/src/file-provider-s3-env/feature.ts +2 -2
- package/packages/bundled-features/src/files/README.md +1 -1
- package/packages/bundled-features/src/files-tenant-data/index.ts +1 -1
- package/packages/bundled-features/src/folders/feature.ts +2 -2
- package/packages/bundled-features/src/folders-user-data/index.ts +1 -1
- package/packages/bundled-features/src/form-draft/feature.ts +2 -2
- package/packages/bundled-features/src/form-draft-user-data/index.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/changes.json +13 -0
- package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +9 -1
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +19 -7
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +21 -2
- package/packages/bundled-features/src/inbound-provider-imap/feature.ts +2 -2
- package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +1 -1
- package/packages/bundled-features/src/ledger/feature.ts +5 -5
- package/packages/bundled-features/src/legal-pages/feature.ts +1 -1
- package/packages/bundled-features/src/mail-foundation/feature.ts +1 -1
- package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +2 -2
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +3 -3
- package/packages/bundled-features/src/managed-pages/css-gate.ts +1 -1
- package/packages/bundled-features/src/managed-pages/feature.ts +2 -2
- package/packages/bundled-features/src/metrics/feature.ts +2 -2
- package/packages/bundled-features/src/notes-history/feature.ts +2 -2
- package/packages/bundled-features/src/notes-history-user-data/index.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +15 -11
- package/packages/bundled-features/src/readiness/feature.ts +2 -2
- package/packages/bundled-features/src/renderer-foundation/README.md +1 -1
- package/packages/bundled-features/src/renderer-foundation/feature.ts +1 -1
- package/packages/bundled-features/src/renderer-pdf/feature.ts +1 -1
- package/packages/bundled-features/src/secrets/feature.ts +1 -1
- package/packages/bundled-features/src/seo/feature.ts +1 -1
- package/packages/bundled-features/src/sessions/feature.ts +17 -13
- package/packages/bundled-features/src/step-dispatcher/changes.json +8 -1
- package/packages/bundled-features/src/step-dispatcher/constants.ts +22 -0
- package/packages/bundled-features/src/step-dispatcher/deliver-dispatch-request.ts +236 -0
- package/packages/bundled-features/src/step-dispatcher/feature.ts +66 -119
- package/packages/bundled-features/src/step-dispatcher/webhook-runner.ts +40 -14
- package/packages/bundled-features/src/subscription-mollie/feature.ts +1 -1
- package/packages/bundled-features/src/subscription-stripe/feature.ts +3 -3
- package/packages/bundled-features/src/tags/feature.ts +2 -2
- package/packages/bundled-features/src/template-resolver/feature.ts +2 -2
- package/packages/bundled-features/src/template-resolver-user-data/index.ts +1 -1
- package/packages/bundled-features/src/tenant/feature.ts +4 -4
- package/packages/bundled-features/src/tenant/seeding.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +2 -3
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +6 -1
- package/packages/bundled-features/src/tenant-settings/feature.ts +1 -1
- package/packages/bundled-features/src/tier-engine/feature.ts +36 -27
- package/packages/bundled-features/src/user/feature.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/README.md +1 -1
- package/packages/bundled-features/src/user-data-rights/feature.ts +4 -4
- package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +2 -2
- package/packages/bundled-features/src/user-profile/feature.ts +4 -4
- package/packages/bundled-features/src/waitlist/feature.ts +2 -2
- package/samples/apps/cap-billing-demo/README.md +1 -1
- package/samples/apps/cap-billing-demo/src/feature.ts +4 -4
- package/samples/apps/cap-billing-demo/src/run-config.ts +1 -1
- package/samples/apps/config-demo/src/features/demo/feature.ts +2 -2
- package/samples/apps/styleguide/src/features/ai-settings/feature.ts +43 -28
- package/samples/apps/styleguide/src/features/demo/feature.ts +18 -18
- package/samples/apps/styleguide/src/features/widgets/ai-text-demo.ts +10 -12
- package/samples/apps/styleguide/src/features/widgets/feature.ts +90 -108
- package/samples/apps/ui-walkthrough/src/features/rental/feature.ts +36 -36
- package/samples/apps/ui-walkthrough/src/features/vehicles/feature.ts +6 -6
- package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +2 -2
- package/samples/apps/use-all-bundled/feature-manifest.json +1 -1
- package/samples/apps/use-all-bundled/scripts/gen-sample-index.ts +7 -7
- package/samples/apps/use-all-bundled/src/app/notes-feature.ts +3 -3
- package/samples/apps/use-all-bundled/src/app/screens-feature.ts +1 -1
- package/samples/apps/user-data-rights-demo/src/feature.ts +5 -5
- package/samples/recipes/access-control/src/feature.ts +21 -25
- package/samples/recipes/anonymous-access/src/feature.ts +36 -43
- package/samples/recipes/anonymous-access-multitenant/src/feature.ts +14 -16
- package/samples/recipes/auth-foundation-providers/src/feature.ts +1 -1
- package/samples/recipes/basic-entity/README.md +1 -1
- package/samples/recipes/boot-check/README.md +1 -1
- package/samples/recipes/boot-check/src/feature.ts +2 -2
- package/samples/recipes/chat-channels/src/feature.ts +1 -1
- package/samples/recipes/cross-feature-events/src/feature.ts +7 -7
- package/samples/recipes/currencies-global/src/feature.ts +3 -3
- package/samples/recipes/currencies-per-tenant/src/feature.ts +2 -2
- package/samples/recipes/custom-fields-basic/README.md +1 -1
- package/samples/recipes/custom-fields-basic/src/feature.ts +3 -2
- package/samples/recipes/custom-handlers/README.md +3 -3
- package/samples/recipes/custom-handlers/src/feature.ts +37 -41
- package/samples/recipes/dashboard-stats/src/feature.ts +6 -6
- package/samples/recipes/delivery-notifications/README.md +1 -1
- package/samples/recipes/delivery-notifications/src/feature.ts +8 -8
- package/samples/recipes/designer-demo/src/feature.ts +2 -1
- package/samples/recipes/embedded/src/feature.ts +1 -1
- package/samples/recipes/embedded-entity-form/src/feature.ts +13 -13
- package/samples/recipes/encrypted-tenant-config/src/feature.ts +1 -1
- package/samples/recipes/error-contract/src/feature.ts +25 -25
- package/samples/recipes/event-sourcing/src/feature.ts +70 -76
- package/samples/recipes/feature-toggles/src/feature.ts +28 -20
- package/samples/recipes/files-post-processing/src/feature.ts +22 -26
- package/samples/recipes/idempotency/src/feature.ts +16 -18
- package/samples/recipes/inbound-mail-triage/src/feature.ts +1 -1
- package/samples/recipes/lane-routing/src/feature.ts +10 -12
- package/samples/recipes/legal-pages/src/feature.ts +1 -1
- package/samples/recipes/lifecycle-hooks/README.md +4 -4
- package/samples/recipes/lifecycle-hooks/src/feature.ts +55 -35
- package/samples/recipes/managed-config/src/feature.ts +8 -8
- package/samples/recipes/managed-pages/src/feature.ts +1 -1
- package/samples/recipes/notes-history-basic/README.md +1 -1
- package/samples/recipes/notes-history-basic/src/feature.ts +2 -2
- package/samples/recipes/pdf-audit-export/src/feature.ts +7 -7
- package/samples/recipes/pipeline-basics/README.md +1 -1
- package/samples/recipes/pipeline-basics/src/feature.ts +7 -7
- package/samples/recipes/public-share-token/src/feature.ts +1 -1
- package/samples/recipes/rate-limiting/src/feature.ts +7 -9
- package/samples/recipes/record-detail-layout/src/feature.ts +18 -18
- package/samples/recipes/reference-data/src/feature.ts +1 -1
- package/samples/recipes/relations/src/feature.ts +2 -2
- package/samples/recipes/screens-nav/src/feature.ts +1 -1
- package/samples/recipes/search/src/feature.ts +17 -19
- package/samples/recipes/security-baseline/README.md +1 -1
- package/samples/recipes/state-machine/src/feature.ts +1 -1
- package/samples/recipes/tags-basic/README.md +1 -1
- package/samples/recipes/tags-basic/src/feature.ts +2 -2
- package/samples/recipes/tenant-settings/README.md +1 -1
- package/samples/recipes/tenant-settings/src/feature.ts +1 -1
- package/samples/recipes/timezones/src/feature.ts +12 -12
- package/samples/recipes/user-data-rights/README.md +2 -2
- package/samples/recipes/user-data-rights/src/feature.ts +1 -1
- package/samples/recipes/user-profile/src/feature.ts +1 -1
- package/samples/recipes/webhook-step/src/feature.ts +1 -1
- package/samples/recipes/writeform-section/src/feature.ts +12 -12
|
@@ -198,10 +198,10 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
198
198
|
],
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
-
r.queryHandler(
|
|
202
|
-
"metrics:portfolio-stat",
|
|
203
|
-
z.object({ region: z.string().optional() }),
|
|
204
|
-
async ({ payload: { region } }, ctx) => ({
|
|
201
|
+
r.queryHandler({
|
|
202
|
+
name: "metrics:portfolio-stat",
|
|
203
|
+
schema: z.object({ region: z.string().optional() }),
|
|
204
|
+
handler: async ({ payload: { region } }, ctx) => ({
|
|
205
205
|
value:
|
|
206
206
|
region === "us"
|
|
207
207
|
? demoMoney(38120, "USD", ctx.locale)
|
|
@@ -212,86 +212,76 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
212
212
|
deltaDirection: "up",
|
|
213
213
|
deltaTone: "positive",
|
|
214
214
|
}),
|
|
215
|
-
{
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
"tenant scoping; any signed-in user may query it",
|
|
221
|
-
},
|
|
215
|
+
access: {
|
|
216
|
+
openToAll: {
|
|
217
|
+
reason:
|
|
218
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
219
|
+
"tenant scoping; any signed-in user may query it",
|
|
222
220
|
},
|
|
223
221
|
},
|
|
224
|
-
);
|
|
225
|
-
r.queryHandler(
|
|
226
|
-
"metrics:net-worth-assets",
|
|
227
|
-
z.object({ region: z.string().optional() }),
|
|
228
|
-
async (_query, ctx) => ({ value: demoMoney(120000, "EUR", ctx.locale) }),
|
|
229
|
-
{
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
"tenant scoping; any signed-in user may query it",
|
|
235
|
-
},
|
|
222
|
+
});
|
|
223
|
+
r.queryHandler({
|
|
224
|
+
name: "metrics:net-worth-assets",
|
|
225
|
+
schema: z.object({ region: z.string().optional() }),
|
|
226
|
+
handler: async (_query, ctx) => ({ value: demoMoney(120000, "EUR", ctx.locale) }),
|
|
227
|
+
access: {
|
|
228
|
+
openToAll: {
|
|
229
|
+
reason:
|
|
230
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
231
|
+
"tenant scoping; any signed-in user may query it",
|
|
236
232
|
},
|
|
237
233
|
},
|
|
238
|
-
);
|
|
239
|
-
r.queryHandler(
|
|
240
|
-
"metrics:net-worth-debts",
|
|
241
|
-
z.object({ region: z.string().optional() }),
|
|
242
|
-
async (_query, ctx) => ({ value: demoMoney(65370, "EUR", ctx.locale) }),
|
|
243
|
-
{
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
"tenant scoping; any signed-in user may query it",
|
|
249
|
-
},
|
|
234
|
+
});
|
|
235
|
+
r.queryHandler({
|
|
236
|
+
name: "metrics:net-worth-debts",
|
|
237
|
+
schema: z.object({ region: z.string().optional() }),
|
|
238
|
+
handler: async (_query, ctx) => ({ value: demoMoney(65370, "EUR", ctx.locale) }),
|
|
239
|
+
access: {
|
|
240
|
+
openToAll: {
|
|
241
|
+
reason:
|
|
242
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
243
|
+
"tenant scoping; any signed-in user may query it",
|
|
250
244
|
},
|
|
251
245
|
},
|
|
252
|
-
);
|
|
253
|
-
r.queryHandler(
|
|
254
|
-
"metrics:response-times",
|
|
255
|
-
z.object({}),
|
|
256
|
-
async () => ({
|
|
246
|
+
});
|
|
247
|
+
r.queryHandler({
|
|
248
|
+
name: "metrics:response-times",
|
|
249
|
+
schema: z.object({}),
|
|
250
|
+
handler: async () => ({
|
|
257
251
|
points: RESPONSE_POINTS,
|
|
258
252
|
windowStartMs: 0,
|
|
259
253
|
windowEndMs: 24 * 60 * 60 * 1000,
|
|
260
254
|
}),
|
|
261
|
-
{
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
"tenant scoping; any signed-in user may query it",
|
|
267
|
-
},
|
|
255
|
+
access: {
|
|
256
|
+
openToAll: {
|
|
257
|
+
reason:
|
|
258
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
259
|
+
"tenant scoping; any signed-in user may query it",
|
|
268
260
|
},
|
|
269
261
|
},
|
|
270
|
-
);
|
|
271
|
-
r.queryHandler(
|
|
272
|
-
"metrics:loan",
|
|
273
|
-
z.object({}),
|
|
274
|
-
async () => ({
|
|
262
|
+
});
|
|
263
|
+
r.queryHandler({
|
|
264
|
+
name: "metrics:loan",
|
|
265
|
+
schema: z.object({}),
|
|
266
|
+
handler: async () => ({
|
|
275
267
|
series: LOAN_SERIES,
|
|
276
268
|
markers: LOAN_MARKERS,
|
|
277
269
|
windowStartMs: LOAN_START_MS,
|
|
278
270
|
windowEndMs: loanMonthMs(LOAN_MONTHS),
|
|
279
271
|
todayMs: LOAN_TODAY_MS,
|
|
280
272
|
}),
|
|
281
|
-
{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
"tenant scoping; any signed-in user may query it",
|
|
287
|
-
},
|
|
273
|
+
access: {
|
|
274
|
+
openToAll: {
|
|
275
|
+
reason:
|
|
276
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
277
|
+
"tenant scoping; any signed-in user may query it",
|
|
288
278
|
},
|
|
289
279
|
},
|
|
290
|
-
);
|
|
291
|
-
r.queryHandler(
|
|
292
|
-
"metrics:latest-items",
|
|
293
|
-
z.object({}),
|
|
294
|
-
async (_query, ctx) => ({
|
|
280
|
+
});
|
|
281
|
+
r.queryHandler({
|
|
282
|
+
name: "metrics:latest-items",
|
|
283
|
+
schema: z.object({}),
|
|
284
|
+
handler: async (_query, ctx) => ({
|
|
295
285
|
rows: [
|
|
296
286
|
{
|
|
297
287
|
id: "i1",
|
|
@@ -306,25 +296,23 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
306
296
|
],
|
|
307
297
|
nextCursor: null,
|
|
308
298
|
}),
|
|
309
|
-
{
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
"tenant scoping; any signed-in user may query it",
|
|
315
|
-
},
|
|
299
|
+
access: {
|
|
300
|
+
openToAll: {
|
|
301
|
+
reason:
|
|
302
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
303
|
+
"tenant scoping; any signed-in user may query it",
|
|
316
304
|
},
|
|
317
305
|
},
|
|
318
|
-
);
|
|
319
|
-
r.queryHandler(
|
|
320
|
-
"metrics:inbox-messages",
|
|
321
|
-
z.object({
|
|
306
|
+
});
|
|
307
|
+
r.queryHandler({
|
|
308
|
+
name: "metrics:inbox-messages",
|
|
309
|
+
schema: z.object({
|
|
322
310
|
cursor: z.coerce.number().int().min(0).optional(),
|
|
323
311
|
limit: z.number().int().min(1).max(100).optional(),
|
|
324
312
|
unreadOnly: z.boolean().optional(),
|
|
325
313
|
search: z.string().optional(),
|
|
326
314
|
}),
|
|
327
|
-
async ({ payload: { cursor, limit, unreadOnly, search } }) => {
|
|
315
|
+
handler: async ({ payload: { cursor, limit, unreadOnly, search } }) => {
|
|
328
316
|
const term = search?.trim().toLowerCase() ?? "";
|
|
329
317
|
const filtered = INBOX_MESSAGES.filter(
|
|
330
318
|
(m) =>
|
|
@@ -339,20 +327,18 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
339
327
|
const nextCursor = start + pageSize < filtered.length ? String(start + pageSize) : null;
|
|
340
328
|
return { rows, nextCursor };
|
|
341
329
|
},
|
|
342
|
-
{
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
"tenant scoping; any signed-in user may query it",
|
|
348
|
-
},
|
|
330
|
+
access: {
|
|
331
|
+
openToAll: {
|
|
332
|
+
reason:
|
|
333
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
334
|
+
"tenant scoping; any signed-in user may query it",
|
|
349
335
|
},
|
|
350
336
|
},
|
|
351
|
-
);
|
|
352
|
-
r.queryHandler(
|
|
353
|
-
"metrics:upcoming-events",
|
|
354
|
-
z.object({}),
|
|
355
|
-
async (_query, ctx) => ({
|
|
337
|
+
});
|
|
338
|
+
r.queryHandler({
|
|
339
|
+
name: "metrics:upcoming-events",
|
|
340
|
+
schema: z.object({}),
|
|
341
|
+
handler: async (_query, ctx) => ({
|
|
356
342
|
rows: [
|
|
357
343
|
{
|
|
358
344
|
primary: demoText("widgets:dashboard:demo-event-rate-adjustment", ctx.locale),
|
|
@@ -364,20 +350,18 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
364
350
|
},
|
|
365
351
|
],
|
|
366
352
|
}),
|
|
367
|
-
{
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
"tenant scoping; any signed-in user may query it",
|
|
373
|
-
},
|
|
353
|
+
access: {
|
|
354
|
+
openToAll: {
|
|
355
|
+
reason:
|
|
356
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
357
|
+
"tenant scoping; any signed-in user may query it",
|
|
374
358
|
},
|
|
375
359
|
},
|
|
376
|
-
);
|
|
377
|
-
r.queryHandler(
|
|
378
|
-
"metrics:goal-progress",
|
|
379
|
-
z.object({}),
|
|
380
|
-
async (_query, ctx) => ({
|
|
360
|
+
});
|
|
361
|
+
r.queryHandler({
|
|
362
|
+
name: "metrics:goal-progress",
|
|
363
|
+
schema: z.object({}),
|
|
364
|
+
handler: async (_query, ctx) => ({
|
|
381
365
|
rows: [
|
|
382
366
|
{
|
|
383
367
|
label: demoText("widgets:dashboard:demo-goal-mortgage", ctx.locale),
|
|
@@ -391,16 +375,14 @@ export const widgetsFeature = defineFeature("widgets", (r) => {
|
|
|
391
375
|
},
|
|
392
376
|
],
|
|
393
377
|
}),
|
|
394
|
-
{
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
"tenant scoping; any signed-in user may query it",
|
|
400
|
-
},
|
|
378
|
+
access: {
|
|
379
|
+
openToAll: {
|
|
380
|
+
reason:
|
|
381
|
+
"demo dashboard widget: returns static canned data with no per-user or " +
|
|
382
|
+
"tenant scoping; any signed-in user may query it",
|
|
401
383
|
},
|
|
402
384
|
},
|
|
403
|
-
);
|
|
385
|
+
});
|
|
404
386
|
|
|
405
387
|
r.translations({ keys: WIDGETS_I18N });
|
|
406
388
|
|
|
@@ -71,10 +71,10 @@ export const rentalFeature = defineFeature("rental", (r) => {
|
|
|
71
71
|
r.crud("leasePosition", leasePositionEntity, { write: open, read: open });
|
|
72
72
|
r.crud("leaseParty", leasePartyEntity, { write: open, read: open });
|
|
73
73
|
|
|
74
|
-
r.queryHandler(
|
|
75
|
-
"lease:akte",
|
|
76
|
-
idPayloadSchema,
|
|
77
|
-
async (query, ctx) => {
|
|
74
|
+
r.queryHandler({
|
|
75
|
+
name: "lease:akte",
|
|
76
|
+
schema: idPayloadSchema,
|
|
77
|
+
handler: async (query, ctx) => {
|
|
78
78
|
const row = await leaseExecutor.detail({ id: query.payload.id }, query.user, ctx.db);
|
|
79
79
|
if (!row) return failNotFound("lease", query.payload.id);
|
|
80
80
|
const lease = parseLeaseRow(row);
|
|
@@ -104,13 +104,13 @@ export const rentalFeature = defineFeature("rental", (r) => {
|
|
|
104
104
|
positionCount: await countChildren(positionExecutor),
|
|
105
105
|
};
|
|
106
106
|
},
|
|
107
|
-
open,
|
|
108
|
-
);
|
|
107
|
+
...open,
|
|
108
|
+
});
|
|
109
109
|
|
|
110
|
-
r.queryHandler(
|
|
111
|
-
"lease:positions",
|
|
112
|
-
idPayloadSchema,
|
|
113
|
-
async (query, ctx) => {
|
|
110
|
+
r.queryHandler({
|
|
111
|
+
name: "lease:positions",
|
|
112
|
+
schema: idPayloadSchema,
|
|
113
|
+
handler: async (query, ctx) => {
|
|
114
114
|
const page = await positionExecutor.list(
|
|
115
115
|
{ filter: { field: "lease", op: "eq", value: query.payload.id }, limit: 100 },
|
|
116
116
|
query.user,
|
|
@@ -132,13 +132,13 @@ export const rentalFeature = defineFeature("rental", (r) => {
|
|
|
132
132
|
}),
|
|
133
133
|
};
|
|
134
134
|
},
|
|
135
|
-
open,
|
|
136
|
-
);
|
|
135
|
+
...open,
|
|
136
|
+
});
|
|
137
137
|
|
|
138
|
-
r.queryHandler(
|
|
139
|
-
"lease:kennzahlen",
|
|
140
|
-
z.object({}),
|
|
141
|
-
async () => ({
|
|
138
|
+
r.queryHandler({
|
|
139
|
+
name: "lease:kennzahlen",
|
|
140
|
+
schema: z.object({}),
|
|
141
|
+
handler: async () => ({
|
|
142
142
|
debt: "123.456 €",
|
|
143
143
|
debtSub: "nach 10 Jahren",
|
|
144
144
|
debtDelta: "15 %",
|
|
@@ -146,13 +146,13 @@ export const rentalFeature = defineFeature("rental", (r) => {
|
|
|
146
146
|
rent: "48.200 €",
|
|
147
147
|
rentSub: "319 Verträge",
|
|
148
148
|
}),
|
|
149
|
-
open,
|
|
150
|
-
);
|
|
149
|
+
...open,
|
|
150
|
+
});
|
|
151
151
|
|
|
152
|
-
r.writeHandler(
|
|
153
|
-
"lease:terminate",
|
|
154
|
-
idPayloadSchema,
|
|
155
|
-
async (event, ctx) =>
|
|
152
|
+
r.writeHandler({
|
|
153
|
+
name: "lease:terminate",
|
|
154
|
+
schema: idPayloadSchema,
|
|
155
|
+
handler: async (event, ctx) =>
|
|
156
156
|
leaseExecutor.update(
|
|
157
157
|
{
|
|
158
158
|
id: event.payload.id,
|
|
@@ -165,13 +165,13 @@ export const rentalFeature = defineFeature("rental", (r) => {
|
|
|
165
165
|
ctx.db,
|
|
166
166
|
{ skipOptimisticLock: true },
|
|
167
167
|
),
|
|
168
|
-
open,
|
|
169
|
-
);
|
|
168
|
+
...open,
|
|
169
|
+
});
|
|
170
170
|
|
|
171
|
-
r.writeHandler(
|
|
172
|
-
"lease:record-positions",
|
|
173
|
-
recordPositionsPayloadSchema,
|
|
174
|
-
async (event, ctx) => {
|
|
171
|
+
r.writeHandler({
|
|
172
|
+
name: "lease:record-positions",
|
|
173
|
+
schema: recordPositionsPayloadSchema,
|
|
174
|
+
handler: async (event, ctx) => {
|
|
175
175
|
let created: Awaited<ReturnType<typeof positionExecutor.create>> | undefined;
|
|
176
176
|
const unitLabels = new Map<string, string | null | undefined>();
|
|
177
177
|
for (const unitId of new Set(event.payload.items.map((item) => item.unit))) {
|
|
@@ -189,13 +189,13 @@ export const rentalFeature = defineFeature("rental", (r) => {
|
|
|
189
189
|
}
|
|
190
190
|
return created ?? failNotFound("leasePosition", event.payload.lease);
|
|
191
191
|
},
|
|
192
|
-
open,
|
|
193
|
-
);
|
|
192
|
+
...open,
|
|
193
|
+
});
|
|
194
194
|
|
|
195
|
-
r.writeHandler(
|
|
196
|
-
"rent:adjust",
|
|
197
|
-
rentAdjustPayloadSchema,
|
|
198
|
-
async (event, ctx) => {
|
|
195
|
+
r.writeHandler({
|
|
196
|
+
name: "rent:adjust",
|
|
197
|
+
schema: rentAdjustPayloadSchema,
|
|
198
|
+
handler: async (event, ctx) => {
|
|
199
199
|
const { positionId, wirksamAb, neuerBetrag } = event.payload;
|
|
200
200
|
const current = await positionExecutor.detail({ id: positionId }, event.user, ctx.db);
|
|
201
201
|
if (!current) return failNotFound("leasePosition", positionId);
|
|
@@ -229,8 +229,8 @@ export const rentalFeature = defineFeature("rental", (r) => {
|
|
|
229
229
|
{ skipOptimisticLock: true },
|
|
230
230
|
);
|
|
231
231
|
},
|
|
232
|
-
open,
|
|
233
|
-
);
|
|
232
|
+
...open,
|
|
233
|
+
});
|
|
234
234
|
|
|
235
235
|
r.screen(leaseListScreen);
|
|
236
236
|
r.screen(leaseListShortScreen);
|
|
@@ -32,10 +32,10 @@ export const vehiclesFeature = defineFeature("vehicles", (r) => {
|
|
|
32
32
|
r.crud("campaign", campaignEntity, { write: open, read: open });
|
|
33
33
|
r.crud("campaignPost", campaignPostEntity, { write: open, read: open });
|
|
34
34
|
|
|
35
|
-
r.writeHandler(
|
|
36
|
-
"campaign-post:mark-posted",
|
|
37
|
-
markPostedPayloadSchema,
|
|
38
|
-
async (event, ctx) => {
|
|
35
|
+
r.writeHandler({
|
|
36
|
+
name: "campaign-post:mark-posted",
|
|
37
|
+
schema: markPostedPayloadSchema,
|
|
38
|
+
handler: async (event, ctx) => {
|
|
39
39
|
const current = await campaignPostExecutor.detail(
|
|
40
40
|
{ id: event.payload.id },
|
|
41
41
|
event.user,
|
|
@@ -62,8 +62,8 @@ export const vehiclesFeature = defineFeature("vehicles", (r) => {
|
|
|
62
62
|
{ skipOptimisticLock: true },
|
|
63
63
|
);
|
|
64
64
|
},
|
|
65
|
-
open,
|
|
66
|
-
);
|
|
65
|
+
...open,
|
|
66
|
+
});
|
|
67
67
|
|
|
68
68
|
r.screen(vehicleListScreen);
|
|
69
69
|
r.screen(vehicleEditScreen);
|
|
@@ -117,14 +117,14 @@ export const galleryProviderFeature: FeatureDefinition = defineFeature(
|
|
|
117
117
|
"gallery-mock-provider",
|
|
118
118
|
(r) => {
|
|
119
119
|
r.describe("E2E-only mock subscription provider for the consent/termination gallery.");
|
|
120
|
-
r.requires("billing-foundation");
|
|
120
|
+
r.requires({ features: ["billing-foundation"] });
|
|
121
121
|
r.useExtension("subscriptionProvider", GALLERY_PROVIDER, galleryProviderPlugin);
|
|
122
122
|
},
|
|
123
123
|
);
|
|
124
124
|
|
|
125
125
|
export const galleryScreensFeature: FeatureDefinition = defineFeature("gallery-screens", (r) => {
|
|
126
126
|
r.describe("E2E-only nav entry for the billing plans screen plus plan labels.");
|
|
127
|
-
r.requires("billing-foundation", "admin-shell");
|
|
127
|
+
r.requires({ features: ["billing-foundation", "admin-shell"] });
|
|
128
128
|
r.nav({
|
|
129
129
|
id: "billing",
|
|
130
130
|
label: "gallery:nav.billing",
|
|
@@ -2391,7 +2391,7 @@
|
|
|
2391
2391
|
},
|
|
2392
2392
|
{
|
|
2393
2393
|
"name": "step-dispatcher",
|
|
2394
|
-
"description": "Internal system feature that drains deferred Tier-2 side-effects (currently `webhook.send` and `mail.send`) after their originating transaction commits.
|
|
2394
|
+
"description": "Internal system feature that drains deferred Tier-2 side-effects (currently `webhook.send` and `mail.send`) after their originating transaction commits. An `r.multiStreamProjection` on the `kumiko:system:step.dispatch-requested` system event enqueues one `step-dispatcher:job:deliver` BullMQ job per dispatch (Redis carries only the stream id and tenant, never the request payload). The job performs the actual HTTP or mail delivery and appends `kumiko:system:step.dispatched` or `kumiko:system:step.dispatch-failed` back onto the same stream, so the outcome is recorded in the event log without a separate status table. Transient failures (network error, timeout, 5xx, 408, 429, any mail adapter failure) are retried 3 times with exponential backoff; the outcome is recorded after the final attempt and the payload key is erased only then. Permanent failures (invalid url, blocked host, other 4xx, unavailable auth secret) are recorded immediately. At most 2 deliveries per tenant run at once (`maxPerTenant` with `onLimit: \"defer\"`), so a slow receiver of one tenant does not delay other tenants. Requires a job runner (Redis) and a worker consuming the job's default `worker` lane; without a job runner the projection fails loudly. Mount this feature explicitly via `createStepDispatcherFeature()` in your app's feature list alongside any features that use `r.step.webhook.send` or `r.step.mail.send`. Requires the `secrets` feature (`createSecretsFeature()`) to be mounted — `webhook.send` auth resolves per-tenant through it, under `step-dispatcher:webhook-auth.<name>`. Every `webhook.send` request carries `Idempotency-Key: <dispatch stream id>`, stable across retries and redeliveries of the same dispatch request; an explicit `Idempotency-Key` in `headers` takes precedence.",
|
|
2395
2395
|
"toggleableDefault": null,
|
|
2396
2396
|
"requires": [
|
|
2397
2397
|
"secrets"
|
|
@@ -89,13 +89,13 @@ export function extractFeaturesFromText(rawText: string): Set<string> {
|
|
|
89
89
|
const name = m[1];
|
|
90
90
|
if (name) feats.add(name);
|
|
91
91
|
}
|
|
92
|
-
for (const m of text.matchAll(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
for (const m of text.matchAll(
|
|
93
|
+
/r\.(?:requires|optionalRequires)\(\s*\{\s*features:\s*\[([^\]]*)\]/g,
|
|
94
|
+
)) {
|
|
95
|
+
for (const quoted of (m[1] ?? "").matchAll(/["']([a-z0-9-]+)["']/g)) {
|
|
96
|
+
const name = quoted[1];
|
|
97
|
+
if (name) feats.add(name);
|
|
98
|
+
}
|
|
99
99
|
}
|
|
100
100
|
return feats;
|
|
101
101
|
}
|
|
@@ -120,9 +120,9 @@ export const notesFeature: FeatureDefinition = defineFeature("notes-demo", (r) =
|
|
|
120
120
|
r.describe(
|
|
121
121
|
"Dev-only host entity demonstrating tags, custom-fields, and folders on a real entityEdit screen.",
|
|
122
122
|
);
|
|
123
|
-
r.requires("tags");
|
|
124
|
-
r.requires("custom-fields");
|
|
125
|
-
r.requires("folders");
|
|
123
|
+
r.requires({ features: ["tags"] });
|
|
124
|
+
r.requires({ features: ["custom-fields"] });
|
|
125
|
+
r.requires({ features: ["folders"] });
|
|
126
126
|
|
|
127
127
|
wireCustomFieldsFor(r, "note", noteTable);
|
|
128
128
|
|
|
@@ -9,7 +9,7 @@ import { defineFeature, type FeatureDefinition } from "@cosmicdrift/kumiko-frame
|
|
|
9
9
|
|
|
10
10
|
export const appScreensFeature: FeatureDefinition = defineFeature("app-screens", (r) => {
|
|
11
11
|
r.describe("App-side nav placement for the user-profile self-service page.");
|
|
12
|
-
r.requires("user-profile");
|
|
12
|
+
r.requires({ features: ["user-profile"] });
|
|
13
13
|
r.nav({
|
|
14
14
|
id: "profile",
|
|
15
15
|
label: "screen:profile.title",
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
// DSGVO-Endpoints kommen vollstaendig aus user-data-rights.
|
|
7
7
|
//
|
|
8
8
|
// Dieses Feature zeigt:
|
|
9
|
-
// - r.entity("todo", todoEntity)
|
|
10
|
-
// - r.writeHandler("create")
|
|
11
|
-
// - r.queryHandler("list")
|
|
12
|
-
// - r.useExtension(EXT_USER_DATA, "todo")
|
|
9
|
+
// - r.entity({ name: "todo", ...todoEntity }) → Drizzle-Tabelle wird gebaut
|
|
10
|
+
// - r.writeHandler({ name: "create", … }) → User legt Todo an
|
|
11
|
+
// - r.queryHandler({ name: "list", … }) → User sieht seine Todos
|
|
12
|
+
// - r.useExtension(EXT_USER_DATA, "todo") → Forget + Export integration
|
|
13
13
|
//
|
|
14
14
|
// Was passiert wenn der User dann request-export aufruft:
|
|
15
15
|
// 1. user-data-rights.request-export.write triggert einen Job
|
|
@@ -122,7 +122,7 @@ const listTodosHandler = defineQueryHandler({
|
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
export const todosFeature = defineFeature(FEATURE_NAME, (r) => {
|
|
125
|
-
r.requires("user-data-rights");
|
|
125
|
+
r.requires({ features: ["user-data-rights"] });
|
|
126
126
|
|
|
127
127
|
// store_todos is a direct-write store: the create handler `insertOne`s and
|
|
128
128
|
// the forget hook `updateMany`/`deleteMany`s rows WITHOUT emitting lifecycle
|
|
@@ -64,8 +64,8 @@ export const taskTable = buildEntityTable("task", taskEntity, {
|
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
export const accessControlFeature = defineFeature("access-control", (r) => {
|
|
67
|
-
r.entity("project", projectEntity);
|
|
68
|
-
r.entity("task", taskEntity);
|
|
67
|
+
r.entity({ name: "project", ...projectEntity });
|
|
68
|
+
r.entity({ name: "task", ...taskEntity });
|
|
69
69
|
r.relation("task", "project", taskRelations.project);
|
|
70
70
|
|
|
71
71
|
// Admin-only: standard create — no business logic, helper handles schema +
|
|
@@ -80,14 +80,14 @@ export const accessControlFeature = defineFeature("access-control", (r) => {
|
|
|
80
80
|
// hand-write this handler instead of using the helper. The framework helpers
|
|
81
81
|
// are deliberately scope-limited — opt out the moment you need defaults.
|
|
82
82
|
const taskExecutor = createEventStoreExecutor(taskTable, taskEntity, { entityName: "task" });
|
|
83
|
-
r.writeHandler(
|
|
84
|
-
"task:create",
|
|
85
|
-
z.object({
|
|
83
|
+
r.writeHandler({
|
|
84
|
+
name: "task:create",
|
|
85
|
+
schema: z.object({
|
|
86
86
|
title: z.string().min(1),
|
|
87
87
|
projectId: z.uuid(),
|
|
88
88
|
assigneeId: z.uuid().optional(),
|
|
89
89
|
}),
|
|
90
|
-
async (event, ctx) =>
|
|
90
|
+
handler: async (event, ctx) =>
|
|
91
91
|
taskExecutor.create(
|
|
92
92
|
{
|
|
93
93
|
...event.payload,
|
|
@@ -96,22 +96,20 @@ export const accessControlFeature = defineFeature("access-control", (r) => {
|
|
|
96
96
|
event.user,
|
|
97
97
|
ctx.db,
|
|
98
98
|
),
|
|
99
|
-
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
"any signed-in tenant user may create a task; assigneeId defaults to the caller when omitted",
|
|
104
|
-
},
|
|
99
|
+
access: {
|
|
100
|
+
openToAll: {
|
|
101
|
+
reason:
|
|
102
|
+
"any signed-in tenant user may create a task; assigneeId defaults to the caller when omitted",
|
|
105
103
|
},
|
|
106
104
|
},
|
|
107
|
-
);
|
|
105
|
+
});
|
|
108
106
|
|
|
109
107
|
// Update requires version — optimistic locking is the default and this
|
|
110
108
|
// narrowed schema (only title + assigneeId mutable) is stricter than the
|
|
111
109
|
// helper's generic update schema, so we keep it hand-written.
|
|
112
|
-
r.writeHandler(
|
|
113
|
-
"task:update",
|
|
114
|
-
z.object({
|
|
110
|
+
r.writeHandler({
|
|
111
|
+
name: "task:update",
|
|
112
|
+
schema: z.object({
|
|
115
113
|
id: z.uuid(),
|
|
116
114
|
version: z.number(),
|
|
117
115
|
changes: z.object({
|
|
@@ -119,17 +117,15 @@ export const accessControlFeature = defineFeature("access-control", (r) => {
|
|
|
119
117
|
assigneeId: z.uuid().optional(),
|
|
120
118
|
}),
|
|
121
119
|
}),
|
|
122
|
-
async (event, ctx) => taskExecutor.update(event.payload, event.user, ctx.db),
|
|
123
|
-
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
"guards against concurrent overwrites, not caller identity",
|
|
129
|
-
},
|
|
120
|
+
handler: async (event, ctx) => taskExecutor.update(event.payload, event.user, ctx.db),
|
|
121
|
+
access: {
|
|
122
|
+
openToAll: {
|
|
123
|
+
reason:
|
|
124
|
+
"any signed-in tenant user may update a task; optimistic locking (version) " +
|
|
125
|
+
"guards against concurrent overwrites, not caller identity",
|
|
130
126
|
},
|
|
131
127
|
},
|
|
132
|
-
);
|
|
128
|
+
});
|
|
133
129
|
|
|
134
130
|
// Self-service list — no custom logic.
|
|
135
131
|
r.queryHandler(
|