@cosmicdrift/kumiko-samples 0.403.0 → 0.404.1
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 +25 -25
- package/packages/bundled-features/src/account-security/README.md +7 -5
- package/packages/bundled-features/src/audit/feature.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +4 -0
- package/packages/bundled-features/src/data-retention/feature.ts +1 -1
- package/packages/bundled-features/src/delivery/feature.ts +1 -1
- package/packages/bundled-features/src/documents/changes.json +8 -0
- package/packages/bundled-features/src/feature-toggles/changes.json +6 -0
- package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +6 -2
- package/packages/bundled-features/src/form-draft/feature.ts +1 -1
- package/packages/bundled-features/src/host-routing/README.md +10 -10
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/thread-rollup.ts +1 -0
- package/packages/bundled-features/src/inbound-mail-foundation/retention-job.ts +1 -1
- package/packages/bundled-features/src/jobs/changes.json +6 -0
- package/packages/bundled-features/src/jobs/feature.ts +6 -7
- package/packages/bundled-features/src/legal-pages/README.md +21 -13
- package/packages/bundled-features/src/renderer-foundation/README.md +6 -4
- package/packages/bundled-features/src/renderer-pdf/README.md +5 -1
- package/packages/bundled-features/src/template-resolver/README.md +29 -29
- package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +3 -2
- package/packages/bundled-features/src/template-resolver/web/collection-entry-create-form.tsx +1 -0
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +1 -0
- package/packages/bundled-features/src/user-data-rights/COMPLIANCE.md +36 -36
- package/packages/bundled-features/src/user-data-rights/README.md +33 -33
- package/packages/bundled-features/src/user-data-rights/feature.ts +3 -3
- package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +1 -0
- package/samples/apps/admin-console/README.md +5 -5
- package/samples/apps/admin-console/package.json +3 -3
- package/samples/apps/cap-billing-demo/README.md +15 -15
- package/samples/apps/config-demo/README.md +7 -7
- package/samples/apps/config-demo/package.json +2 -2
- package/samples/apps/marketing-demo/README.md +2 -2
- package/samples/apps/marketing-demo/package.json +2 -2
- package/samples/apps/showcase/package.json +3 -3
- package/samples/apps/styleguide/package.json +2 -2
- package/samples/apps/ui-walkthrough/README.md +8 -9
- package/samples/apps/ui-walkthrough/package.json +2 -2
- package/samples/apps/use-all-bundled/README.md +2 -2
- package/samples/apps/use-all-bundled/package.json +2 -2
- package/samples/apps/use-all-bundled/scripts/gen-sample-index.ts +18 -1
- package/samples/apps/user-data-rights-demo/README.md +12 -12
- package/samples/apps/workspaces/package.json +2 -2
- package/samples/recipes/apex-landing/README.md +3 -3
- package/samples/recipes/apex-landing/package.json +1 -1
- package/samples/recipes/apex-surface-auth/README.md +13 -9
- package/samples/recipes/auth-mfa/README.md +2 -4
- package/samples/recipes/auth-mfa/package.json +2 -2
- package/samples/recipes/boot-check/README.md +2 -2
- package/samples/recipes/compliance-profiles-demo/README.md +5 -5
- package/samples/recipes/compose-stacks/README.md +8 -8
- package/samples/recipes/cross-feature-events/README.md +1 -0
- package/samples/recipes/crypto-shredding-hr/README.md +3 -3
- package/samples/recipes/custom-fields-basic/README.md +1 -1
- package/samples/recipes/documents/README.md +25 -0
- package/samples/recipes/embedded-entity-form/package.json +2 -2
- package/samples/recipes/encrypted-tenant-config/README.md +8 -8
- package/samples/recipes/env-composition/README.md +10 -10
- package/samples/recipes/error-contract/README.md +9 -9
- package/samples/recipes/event-sourcing/README.md +9 -9
- package/samples/recipes/lane-routing/README.md +1 -0
- package/samples/recipes/lane-routing/src/feature.ts +8 -0
- package/samples/recipes/ledger-invoicing/README.md +6 -6
- package/samples/recipes/legal-pages/README.md +16 -16
- package/samples/recipes/managed-config/README.md +15 -11
- package/samples/recipes/managed-pages/README.md +7 -7
- package/samples/recipes/pdf-audit-export/package.json +1 -1
- package/samples/recipes/pipeline-basics/README.md +13 -13
- package/samples/recipes/public-share-token/README.md +4 -4
- package/samples/recipes/record-detail-layout/package.json +3 -3
- package/samples/recipes/security-baseline/README.md +4 -1
- package/samples/recipes/session-revocation/README.md +1 -1
- package/samples/recipes/tenant-settings/README.md +4 -4
- package/samples/recipes/tier-admin/README.md +2 -2
- package/samples/recipes/user-data-rights/README.md +21 -19
- package/samples/recipes/wizard-form/package.json +3 -3
- package/samples/recipes/writeform-section/package.json +3 -3
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@cosmicdrift/kumiko-framework": "workspace:*",
|
|
11
11
|
"@cosmicdrift/kumiko-renderer": "workspace:*",
|
|
12
|
-
"react": "^19.
|
|
12
|
+
"react": "^19.3.1"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@cosmicdrift/kumiko-server-runtime": "workspace:*",
|
|
16
16
|
"@cosmicdrift/kumiko-testing": "workspace:*",
|
|
17
|
-
"@playwright/test": "^1.
|
|
17
|
+
"@playwright/test": "^1.64.1",
|
|
18
18
|
"@tailwindcss/cli": "^4.3.3",
|
|
19
|
-
"@types/react": "^19.
|
|
19
|
+
"@types/react": "^19.3.0",
|
|
20
20
|
"tailwindcss": "^4.3.3"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -45,7 +45,10 @@ mounts `sessions` as part of its own require-chain. Combine both directly;
|
|
|
45
45
|
`dedupeFeatures()` collapses the two identical `sessions` instances at boot:
|
|
46
46
|
|
|
47
47
|
```ts illustration
|
|
48
|
-
import {
|
|
48
|
+
import {
|
|
49
|
+
composeGdprStack,
|
|
50
|
+
composeSecurityStack,
|
|
51
|
+
} from "@cosmicdrift/kumiko-dev-server/compose-stacks";
|
|
49
52
|
|
|
50
53
|
export const APP_FEATURES = [
|
|
51
54
|
// ...config, user, tenant, auth-foundation...
|
|
@@ -56,12 +56,12 @@ role vocabulary overrides those instead of forking the feature.
|
|
|
56
56
|
|
|
57
57
|
## Why the schema needs a special case
|
|
58
58
|
|
|
59
|
-
`buildInsertSchema` always makes `currency` required
|
|
59
|
+
`buildInsertSchema` always makes `currency` required _inside_ a money field's
|
|
60
60
|
value object, even when the field itself is optional — a caller literally
|
|
61
61
|
cannot submit `{ amount: 1000 }` against the plain `defineEntityCreateHandler`.
|
|
62
62
|
`defineCreateWithTenantDefaults` swaps in its own schema (`.extend()` over the
|
|
63
63
|
same `buildInsertSchema` output, with just the declared `currencyFields`
|
|
64
|
-
relaxed) so the caller
|
|
64
|
+
relaxed) so the caller _can_ omit `currency`, then fills it from
|
|
65
65
|
`ctx.config(TenantSettingsConfig.currency)` before delegating to the same
|
|
66
66
|
`executor.create()` the generic factory uses.
|
|
67
67
|
|
|
@@ -74,13 +74,13 @@ changes them from **Settings → Tenant → Default Currency / Default Locale**.
|
|
|
74
74
|
|
|
75
75
|
## Flow
|
|
76
76
|
|
|
77
|
-
1. No tenant override yet → a new invoice gets the
|
|
77
|
+
1. No tenant override yet → a new invoice gets the _feature's own_ default
|
|
78
78
|
(`"EUR"`/`"en"`, set via `createTenantSettingsFeature()`'s own defaults).
|
|
79
79
|
2. Tenant sets `currency` to `"CHF"` and `locale` to `"de"` via the
|
|
80
80
|
Settings-Hub (or `config:write:set` directly).
|
|
81
81
|
3. A new invoice that doesn't specify `amount.currency`/`language` picks up
|
|
82
82
|
`"CHF"`/`"de"` — no entity code changed, no second migration.
|
|
83
|
-
4. A caller that
|
|
83
|
+
4. A caller that _does_ specify `amount.currency` still wins — the tenant
|
|
84
84
|
setting only fills gaps, it never overrides an explicit value.
|
|
85
85
|
|
|
86
86
|
## Tests
|
|
@@ -9,7 +9,7 @@ toggleable features unlock in the same request.
|
|
|
9
9
|
## What it shows
|
|
10
10
|
|
|
11
11
|
- **`tier-engine:write:set-tenant-tier`** — a SystemAdmin assigns a tier
|
|
12
|
-
to
|
|
12
|
+
to _any_ tenant, cross-tenant. Stamps `source: "manual"` so a future
|
|
13
13
|
Stripe → tier sync won't overwrite the grant.
|
|
14
14
|
- **`tier-engine:query:get-tenant-tier`** — SystemAdmin reads back which
|
|
15
15
|
tier a tenant is on plus its source (`"manual"` vs `"billing"`).
|
|
@@ -50,7 +50,7 @@ notes-export → r.toggleable() domain feature unlocked by pro tier
|
|
|
50
50
|
path bypasses the `postSave` entity-hook the resolver normally uses to
|
|
51
51
|
invalidate the cache after a tier-assignment change. Without an explicit
|
|
52
52
|
cache update the grant would persist (next request would see it) but
|
|
53
|
-
|
|
53
|
+
_this_ request still sees the old tier — surprising for an operator who
|
|
54
54
|
just clicked "set tier to pro".
|
|
55
55
|
|
|
56
56
|
The feature wires `onAssigned` into `createSetTenantTierWrite` for
|
|
@@ -17,13 +17,13 @@ defineFeature("notes", (r) => {
|
|
|
17
17
|
r.useExtension(EXT_USER_DATA, "note", {
|
|
18
18
|
export: async (ctx) => ({
|
|
19
19
|
entity: "note",
|
|
20
|
-
rows: await ctx.db
|
|
21
|
-
.
|
|
22
|
-
|
|
20
|
+
rows: await ctx.db
|
|
21
|
+
.select()
|
|
22
|
+
.from(notesTable)
|
|
23
|
+
.where(and(eq(notesTable.tenantId, ctx.tenantId), eq(notesTable.authorId, ctx.userId))),
|
|
23
24
|
}),
|
|
24
25
|
delete: async (ctx, strategy) => {
|
|
25
|
-
const where = and(eq(notesTable.tenantId, ctx.tenantId),
|
|
26
|
-
eq(notesTable.authorId, ctx.userId));
|
|
26
|
+
const where = and(eq(notesTable.tenantId, ctx.tenantId), eq(notesTable.authorId, ctx.userId));
|
|
27
27
|
if (strategy === "anonymize") {
|
|
28
28
|
await ctx.db.update(notesTable).set({ authorId: null }).where(where);
|
|
29
29
|
} else {
|
|
@@ -36,21 +36,21 @@ defineFeature("notes", (r) => {
|
|
|
36
36
|
|
|
37
37
|
## What runs automatically
|
|
38
38
|
|
|
39
|
-
| Article
|
|
40
|
-
|
|
39
|
+
| Article | What happens | Trigger |
|
|
40
|
+
| ------------ | ---------------------------------------------- | -------------------------------------- |
|
|
41
41
|
| Art. 15 + 20 | Notes snippet in export ZIP + magic-link email | `runUserExport` (via `request-export`) |
|
|
42
|
-
| Art. 17
|
|
43
|
-
| Art. 18
|
|
44
|
-
| Operator
|
|
42
|
+
| Art. 17 | Notes deleted or anonymized after grace | `runForgetCleanup` cron |
|
|
43
|
+
| Art. 18 | Restriction blocks login while active | Auth middleware |
|
|
44
|
+
| Operator | Brute-force detection on magic-link endpoint | Edge rate-limit + audit log |
|
|
45
45
|
|
|
46
46
|
## Strategy-aware delete
|
|
47
47
|
|
|
48
48
|
`retention.policyFor("note")` resolves per entity:
|
|
49
49
|
|
|
50
|
-
| Profile
|
|
51
|
-
|
|
52
|
-
| `eu-dsgvo` (default) | `delete`
|
|
53
|
-
| `de-hr-dsgvo-hgb`
|
|
50
|
+
| Profile | Strategy | Effect |
|
|
51
|
+
| -------------------- | --------------------------- | --------------------------------------------- |
|
|
52
|
+
| `eu-dsgvo` (default) | `delete` | Notes hard-deleted |
|
|
53
|
+
| `de-hr-dsgvo-hgb` | `anonymize` for HR entities | `authorId=null`, row kept for multi-user refs |
|
|
54
54
|
|
|
55
55
|
The integration test pins both paths.
|
|
56
56
|
|
|
@@ -91,7 +91,9 @@ const result = await runRetentionCleanup({
|
|
|
91
91
|
registry: stack.registry,
|
|
92
92
|
tenantId,
|
|
93
93
|
preloadedTenantPreset: null,
|
|
94
|
-
now: getTemporal()
|
|
94
|
+
now: getTemporal()
|
|
95
|
+
.Now.instant()
|
|
96
|
+
.add({ hours: 31 * 24 }), // keepFor 30d + 1 day
|
|
95
97
|
files: createFileContext(() => Promise.resolve(provider)), // the stack's storage provider
|
|
96
98
|
});
|
|
97
99
|
// result.hardDeleted === 1, bytes and file_refs row gone
|
|
@@ -99,10 +101,10 @@ const result = await runRetentionCleanup({
|
|
|
99
101
|
|
|
100
102
|
## Full app vs this recipe
|
|
101
103
|
|
|
102
|
-
|
|
|
103
|
-
|
|
104
|
-
| Scope | One hook pattern
|
|
105
|
-
| Boot
|
|
104
|
+
| | This recipe | [user-data-rights-demo](/en/samples/apps-user-data-rights-demo/) |
|
|
105
|
+
| ----- | --------------------- | ---------------------------------------------------------------- |
|
|
106
|
+
| Scope | One hook pattern | Runnable app + todos + files |
|
|
107
|
+
| Boot | Integration test only | `bun dev` on port 4291 |
|
|
106
108
|
|
|
107
109
|
## Dependencies
|
|
108
110
|
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
"@cosmicdrift/kumiko-bundled-features": "workspace:*",
|
|
11
11
|
"@cosmicdrift/kumiko-framework": "workspace:*",
|
|
12
12
|
"@cosmicdrift/kumiko-renderer": "workspace:*",
|
|
13
|
-
"react": "^19.
|
|
13
|
+
"react": "^19.3.1"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@cosmicdrift/kumiko-server-runtime": "workspace:*",
|
|
17
17
|
"@cosmicdrift/kumiko-testing": "workspace:*",
|
|
18
|
-
"@playwright/test": "^1.
|
|
18
|
+
"@playwright/test": "^1.64.1",
|
|
19
19
|
"@tailwindcss/cli": "^4.3.3",
|
|
20
|
-
"@types/react": "^19.
|
|
20
|
+
"@types/react": "^19.3.0",
|
|
21
21
|
"tailwindcss": "^4.3.3"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@cosmicdrift/kumiko-framework": "workspace:*",
|
|
12
12
|
"@cosmicdrift/kumiko-renderer": "workspace:*",
|
|
13
|
-
"react": "^19.
|
|
13
|
+
"react": "^19.3.1"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@cosmicdrift/kumiko-server-runtime": "workspace:*",
|
|
17
17
|
"@cosmicdrift/kumiko-testing": "workspace:*",
|
|
18
|
-
"@playwright/test": "^1.
|
|
18
|
+
"@playwright/test": "^1.64.1",
|
|
19
19
|
"@tailwindcss/cli": "^4.3.3",
|
|
20
|
-
"@types/react": "^19.
|
|
20
|
+
"@types/react": "^19.3.0",
|
|
21
21
|
"tailwindcss": "^4.3.3"
|
|
22
22
|
}
|
|
23
23
|
}
|