@cosmicdrift/kumiko-samples 0.344.0 → 0.346.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.
Files changed (36) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +1 -1
  3. package/packages/bundled-features/src/audit/changes.json +12 -0
  4. package/packages/bundled-features/src/audit/constants.ts +5 -0
  5. package/packages/bundled-features/src/audit/feature.ts +1 -1
  6. package/packages/bundled-features/src/audit/handlers/details.query.ts +14 -3
  7. package/packages/bundled-features/src/audit/handlers/list.query.ts +11 -2
  8. package/packages/bundled-features/src/audit/handlers/resolve-audit-tenant.ts +22 -0
  9. package/packages/bundled-features/src/audit/i18n.ts +3 -0
  10. package/packages/bundled-features/src/audit/run-escape-hatch-retention.ts +31 -12
  11. package/packages/bundled-features/src/auth-email-password/changes.json +24 -0
  12. package/packages/bundled-features/src/auth-email-password/constants.ts +1 -0
  13. package/packages/bundled-features/src/auth-email-password/feature.ts +9 -2
  14. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +33 -10
  15. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +32 -15
  16. package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +60 -0
  17. package/packages/bundled-features/src/auth-email-password/handlers/token-request-handler.ts +8 -1
  18. package/packages/bundled-features/src/auth-email-password/i18n.ts +2 -0
  19. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +20 -7
  20. package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +11 -1
  21. package/packages/bundled-features/src/billing-foundation/changes.json +6 -0
  22. package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +31 -11
  23. package/packages/bundled-features/src/step-dispatcher/changes.json +31 -0
  24. package/packages/bundled-features/src/step-dispatcher/dispatch-payload.ts +144 -0
  25. package/packages/bundled-features/src/step-dispatcher/feature.ts +32 -152
  26. package/packages/bundled-features/src/step-dispatcher/webhook-runner.ts +30 -3
  27. package/packages/bundled-features/src/tier-engine/constants.ts +7 -0
  28. package/packages/bundled-features/src/tier-engine/entity.ts +2 -4
  29. package/packages/bundled-features/src/tier-engine/feature.ts +7 -2
  30. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +10 -4
  31. package/packages/bundled-features/src/tier-engine/index.ts +6 -1
  32. package/samples/apps/use-all-bundled/feature-manifest.json +3 -2
  33. package/samples/recipes/i18n/README.md +1 -1
  34. package/samples/recipes/rate-limiting/README.md +1 -1
  35. package/samples/recipes/webhook-step/README.md +9 -2
  36. package/samples/recipes/webhook-step/package.json +1 -1
@@ -7,6 +7,7 @@ import {
7
7
  import { defineWriteHandler, type TenantId } from "@cosmicdrift/kumiko-framework/engine";
8
8
  import * as z from "zod";
9
9
  import { tierAssignmentAggregateId } from "../aggregate-id.js";
10
+ import { TierAssignmentSources } from "../constants.js";
10
11
  import { type TierAssignmentRow, tierAssignmentEntity } from "../entity.js";
11
12
 
12
13
  // SystemAdmin setzt das Tier eines BELIEBIGEN Tenants — manueller Grant ohne
@@ -21,8 +22,8 @@ import { type TierAssignmentRow, tierAssignmentEntity } from "../entity.js";
21
22
  // funktioniert nur für SYSTEM_TENANT_ID (immer im IN-Filter). Dies ist das
22
23
  // auto-default-Hook-Muster (feature.ts), generalisiert auf einen Request-Handler.
23
24
  //
24
- // `source: "manual"` markiert den Grant, damit ein späterer Stripe→Tier-Sync ihn
25
- // nicht plättet. Upsert: ein Aggregat pro Tenant (deterministische aggregate-id).
25
+ // `source: TierAssignmentSources.manual` marks the grant so the billing sync skips it.
26
+ // Upsert: one aggregate per tenant (deterministic aggregate id).
26
27
  //
27
28
  // Effective-set invalidation: the executor write does not fire the
28
29
  // `tier-assignment:postSave` entity hook, and a per-handler postSave would not
@@ -90,7 +91,7 @@ export function createSetTenantTierWrite(opts: SetTenantTierOptions = {}) {
90
91
  {
91
92
  id: existing.id,
92
93
  version: existing.version,
93
- changes: { tier, source: "manual" },
94
+ changes: { tier, source: TierAssignmentSources.manual },
94
95
  },
95
96
  systemUser,
96
97
  tdb,
@@ -101,7 +102,12 @@ export function createSetTenantTierWrite(opts: SetTenantTierOptions = {}) {
101
102
  }
102
103
 
103
104
  const result = await executor.create(
104
- { id: tierAssignmentAggregateId(tenantId), tier, source: "manual", tenantId },
105
+ {
106
+ id: tierAssignmentAggregateId(tenantId),
107
+ tier,
108
+ source: TierAssignmentSources.manual,
109
+ tenantId,
110
+ },
105
111
  systemUser,
106
112
  tdb,
107
113
  );
@@ -17,7 +17,12 @@ export {
17
17
  type TierDefinition,
18
18
  type TierMap,
19
19
  } from "./compose-app.js";
20
- export { TIER_ENGINE_FEATURE, TierEngineHandlers, TierEngineQueries } from "./constants.js";
20
+ export {
21
+ TIER_ENGINE_FEATURE,
22
+ TierAssignmentSources,
23
+ TierEngineHandlers,
24
+ TierEngineQueries,
25
+ } from "./constants.js";
21
26
  export { tierAssignmentEntity } from "./entity.js";
22
27
  export {
23
28
  type CreateTierEngineOptions,
@@ -51,7 +51,7 @@
51
51
  },
52
52
  {
53
53
  "name": "audit",
54
- "description": "Exposes the framework's event store as a paginated, filterable audit log via the `audit:query:list` handler (accessible to `Admin` and `SystemAdmin` roles). No separate table or projection — the event store is the audit trail by construction: every entity write already records who, when, what entity, and the event payload with PII stripped. Filter by `aggregateType`, `aggregateId`, `eventType`, `userId`, or time range. Also records `audit:event:escape-hatch-used` whenever a handler uses one of the framework's escape hatches (unsafeRaw, acknowledgeCrossTenant, db.global() writes, or a granted identity switch).",
54
+ "description": "Exposes the framework's event store as a paginated, filterable audit log via the `audit:query:list` handler (accessible to `Admin` and `SystemAdmin` roles). No separate table or projection — the event store is the audit trail by construction: every entity write already records who, when, what entity, and the event payload with PII stripped. A SystemAdmin can pass `scope: \"system\"` to read the app-instance system events such as `app.started`. Filter by `aggregateType`, `aggregateId`, `eventType`, `userId`, or time range. Also records `audit:event:escape-hatch-used` whenever a handler uses one of the framework's escape hatches (unsafeRaw, acknowledgeCrossTenant, db.global() writes, or a granted identity switch).",
55
55
  "toggleableDefault": null,
56
56
  "requires": [
57
57
  "tenant",
@@ -127,6 +127,7 @@
127
127
  "auth-email-password:write:reset-password",
128
128
  "auth-email-password:write:signup-confirm",
129
129
  "auth-email-password:write:signup-request",
130
+ "auth-email-password:write:switch-tenant-mfa-gate",
130
131
  "auth-email-password:write:system-invite-create",
131
132
  "auth-email-password:write:verify-email"
132
133
  ],
@@ -2301,7 +2302,7 @@
2301
2302
  },
2302
2303
  {
2303
2304
  "name": "step-dispatcher",
2304
- "description": "Internal system feature that drains deferred Tier-2 side-effects (currently `webhook.send` and `mail.send`) after their originating transaction commits. Listens via `r.multiStreamProjection` on the `kumiko:system:step.dispatch-requested` system event, performs the actual HTTP or mail delivery, then 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. 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>`.",
2305
+ "description": "Internal system feature that drains deferred Tier-2 side-effects (currently `webhook.send` and `mail.send`) after their originating transaction commits. Listens via `r.multiStreamProjection` on the `kumiko:system:step.dispatch-requested` system event, performs the actual HTTP or mail delivery, then 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. 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 redeliveries of the same dispatch request; an explicit `Idempotency-Key` in `headers` takes precedence.",
2305
2306
  "toggleableDefault": null,
2306
2307
  "requires": [
2307
2308
  "secrets"
@@ -13,7 +13,7 @@ A translation value can be a CLDR plural-forms object instead of a plain
13
13
  string. `other` is required; the rest (`zero`/`one`/`two`/`few`/`many`) only
14
14
  exist where the locale's grammar needs them:
15
15
 
16
- ```ts
16
+ ```ts illustration
17
17
  "greeting.unread_count": {
18
18
  de: { one: "{count} ungelesene Nachricht", other: "{count} ungelesene Nachrichten" },
19
19
  en: { one: "{count} unread message", other: "{count} unread messages" },
@@ -12,7 +12,7 @@ End-to-end rate limiting: L1 global-IP + L2 auth + L3 handler opt-in.
12
12
  A public write handler that mails an address typed by the caller is also limited per
13
13
  address, so rotating IPs does not help against mail flooding. Declare it next to `rateLimit`:
14
14
 
15
- ```ts
15
+ ```ts illustration
16
16
  r.writeHandler({
17
17
  // ...
18
18
  access: { roles: ["anonymous"] },
@@ -5,7 +5,7 @@ Workflow / pipeline step that calls an HTTP webhook.
5
5
  ## What it shows
6
6
 
7
7
  - Webhook step registration in a workflow
8
- - Retry / failure surface for outbound HTTP
8
+ - Failure surface for outbound HTTP (one delivery attempt per request)
9
9
  - Authenticated webhooks via a tenant-owned secret (`incident:open-authenticated`)
10
10
 
11
11
  ## Auth secret
@@ -16,7 +16,7 @@ never a process-wide env var. The `secrets` feature must be mounted
16
16
  (`createSecretsFeature()` + a `MasterKeyProvider`) alongside
17
17
  `step-dispatcher`. Set the secret per tenant before dispatching:
18
18
 
19
- ```ts
19
+ ```ts illustration
20
20
  await stack.http.writeOk(
21
21
  "secrets:write:set",
22
22
  { key: "step-dispatcher:webhook-auth.incident-hook", value: "<token>" },
@@ -33,6 +33,13 @@ Never combine `auth.secret` with a caller-controlled `url`: the caller would
33
33
  receive the secret as the `Authorization` header. `incident:open-authenticated`
34
34
  therefore posts to a fixed URL.
35
35
 
36
+ ## Idempotency-Key
37
+
38
+ Every webhook request carries `Idempotency-Key: <dispatch stream id>`. The
39
+ value is the same when the same dispatch request is delivered again, so a
40
+ receiver can deduplicate redelivered calls. An `Idempotency-Key` set explicitly in
41
+ `headers` (any casing) wins.
42
+
36
43
  ## Source
37
44
 
38
45
  Feature entry point: `src/feature.ts`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-sample-webhook-step",
3
- "description": "Tier-2 r.step.webhook.send showcase: deferred webhook dispatch via step-dispatcher subscription, no outbox table, retry from event-stream.",
3
+ "description": "Tier-2 r.step.webhook.send showcase: deferred webhook dispatch via step-dispatcher subscription, no outbox table.",
4
4
  "private": true,
5
5
  "dependencies": {
6
6
  "@cosmicdrift/kumiko-bundled-features": "workspace:*",