@cosmicdrift/kumiko-bundled-features 0.14.0 → 0.16.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 +2 -2
- package/src/__tests__/env-schemas.test.ts +1 -1
- package/src/__tests__/es-ops-e2e.integration.ts +10 -9
- package/src/audit/__tests__/audit.integration.ts +3 -3
- package/src/audit/handlers/list.query.ts +39 -51
- package/src/auth-email-password/__tests__/account-lockout-no-redis.integration.ts +4 -3
- package/src/auth-email-password/__tests__/account-lockout.integration.ts +4 -3
- package/src/auth-email-password/__tests__/auth-claims.integration.ts +5 -4
- package/src/auth-email-password/__tests__/auth.integration.ts +4 -3
- package/src/auth-email-password/__tests__/confirm-token-flow.test.ts +1 -1
- package/src/auth-email-password/__tests__/email-templates.test.ts +1 -1
- package/src/auth-email-password/__tests__/email-verification.integration.ts +7 -10
- package/src/auth-email-password/__tests__/identity-v3-hash.test.ts +1 -1
- package/src/auth-email-password/__tests__/identity-v3-login.integration.ts +4 -3
- package/src/auth-email-password/__tests__/invite-flow.integration.ts +16 -43
- package/src/auth-email-password/__tests__/multi-roles.integration.ts +6 -9
- package/src/auth-email-password/__tests__/password-reset.integration.ts +8 -7
- package/src/auth-email-password/__tests__/public-routes-rate-limit.integration.ts +4 -3
- package/src/auth-email-password/__tests__/seed-admin.integration.ts +19 -32
- package/src/auth-email-password/__tests__/session-callbacks.integration.ts +6 -5
- package/src/auth-email-password/__tests__/session-strict-mode.integration.ts +1 -1
- package/src/auth-email-password/__tests__/signed-token.test.ts +1 -1
- package/src/auth-email-password/__tests__/signup-flow.integration.ts +11 -15
- package/src/auth-email-password/handlers/invite-accept-with-login.write.ts +26 -26
- package/src/auth-email-password/handlers/invite-accept.write.ts +24 -21
- package/src/auth-email-password/handlers/invite-create.write.ts +3 -8
- package/src/auth-email-password/handlers/invite-signup-complete.write.ts +20 -17
- package/src/auth-email-password/handlers/signup-confirm.write.ts +3 -7
- package/src/auth-email-password/seeding.ts +1 -1
- package/src/auth-email-password/web/__tests__/auth-gate.test.tsx +1 -2
- package/src/auth-email-password/web/__tests__/forgot-password-screen.test.tsx +10 -19
- package/src/auth-email-password/web/__tests__/login-screen.test.tsx +12 -18
- package/src/auth-email-password/web/__tests__/reset-password-screen.test.tsx +12 -17
- package/src/auth-email-password/web/__tests__/session-roles.test.ts +1 -1
- package/src/auth-email-password/web/__tests__/tenant-switcher.test.tsx +1 -8
- package/src/auth-email-password/web/__tests__/test-utils.tsx +4 -8
- package/src/auth-email-password/web/__tests__/user-menu.test.tsx +2 -8
- package/src/auth-email-password/web/__tests__/verify-email-screen.test.tsx +10 -15
- package/src/billing-foundation/__tests__/billing-foundation.integration.ts +1 -1
- package/src/billing-foundation/__tests__/feature.test.ts +1 -1
- package/src/billing-foundation/__tests__/webhook-handler.test.ts +6 -5
- package/src/billing-foundation/db/queries/subscription-projection.ts +15 -0
- package/src/billing-foundation/get-subscription-for-tenant.ts +2 -6
- package/src/billing-foundation/handlers/create-portal-session.write.ts +2 -2
- package/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -1
- package/src/billing-foundation/projection.ts +32 -13
- package/src/cap-counter/__tests__/cap-counter.integration.ts +1 -1
- package/src/cap-counter/__tests__/enforce-cap.test.ts +37 -32
- package/src/cap-counter/__tests__/with-cap-enforcement.integration.ts +1 -1
- package/src/cap-counter/enforce-cap.ts +14 -20
- package/src/cap-counter/handlers/get-counter.query.ts +7 -13
- package/src/cap-counter/handlers/increment.write.ts +2 -2
- package/src/cap-counter/handlers/mark-soft-warned.write.ts +2 -2
- package/src/channel-in-app/handlers/inbox.query.ts +7 -13
- package/src/channel-in-app/handlers/mark-all-read.write.ts +7 -9
- package/src/channel-in-app/handlers/mark-read.write.ts +8 -14
- package/src/channel-in-app/handlers/unread-count.query.ts +10 -9
- package/src/channel-in-app/in-app-channel.ts +10 -12
- package/src/channel-in-app/tables.ts +1 -1
- package/src/compliance-profiles/__tests__/compliance-profiles.integration.ts +1 -1
- package/src/compliance-profiles/__tests__/seeding.integration.ts +1 -1
- package/src/compliance-profiles/_internal/parse-override.ts +19 -0
- package/src/compliance-profiles/handlers/for-tenant.query.ts +10 -32
- package/src/compliance-profiles/handlers/needs-profile.query.ts +4 -7
- package/src/compliance-profiles/handlers/set-profile.write.ts +5 -7
- package/src/compliance-profiles/resolve-for-tenant.ts +11 -27
- package/src/compliance-profiles/schema/profile-selection.ts +2 -2
- package/src/compliance-profiles/seeding.ts +4 -7
- package/src/config/__tests__/app-overrides.test.ts +1 -1
- package/src/config/__tests__/cascade.integration.ts +1 -1
- package/src/config/__tests__/config.integration.ts +8 -27
- package/src/config/db/queries/resolver.ts +47 -0
- package/src/config/handlers/__tests__/prepare-config-write.test.ts +1 -1
- package/src/config/resolver.ts +14 -62
- package/src/config/table.ts +4 -4
- package/src/config/write-helpers.ts +7 -11
- package/src/custom-fields/__tests__/audit-integration.integration.ts +6 -6
- package/src/custom-fields/__tests__/custom-fields.integration.ts +7 -7
- package/src/custom-fields/__tests__/feature.test.ts +1 -1
- package/src/custom-fields/__tests__/field-access.integration.ts +6 -6
- package/src/custom-fields/__tests__/quota.integration.ts +6 -6
- package/src/custom-fields/__tests__/retention.integration.ts +12 -10
- package/src/custom-fields/__tests__/user-data-rights.integration.ts +27 -17
- package/src/custom-fields/__tests__/wire-for-entity.test.ts +5 -5
- package/src/custom-fields/db/queries/field-access.ts +16 -0
- package/src/custom-fields/db/queries/projection.ts +43 -0
- package/src/custom-fields/db/queries/quota.ts +14 -0
- package/src/custom-fields/db/queries/retention.ts +39 -0
- package/src/custom-fields/db/queries/user-data-rights.ts +54 -0
- package/src/custom-fields/lib/field-access.ts +2 -41
- package/src/custom-fields/lib/quota.ts +2 -25
- package/src/custom-fields/run-retention.ts +19 -21
- package/src/custom-fields/wire-for-entity.ts +30 -23
- package/src/custom-fields/wire-user-data-rights.ts +33 -85
- package/src/data-retention/__tests__/data-retention.integration.ts +1 -1
- package/src/data-retention/__tests__/keep-for.test.ts +1 -1
- package/src/data-retention/__tests__/override-schema.test.ts +1 -1
- package/src/data-retention/__tests__/policy-for.integration.ts +1 -1
- package/src/data-retention/__tests__/resolver.test.ts +1 -1
- package/src/data-retention/handlers/policy-for.query.ts +5 -8
- package/src/data-retention/resolve-for-tenant.ts +6 -8
- package/src/data-retention/schema/tenant-retention-override.ts +2 -2
- package/src/delivery/__tests__/delivery-events.integration.ts +8 -21
- package/src/delivery/__tests__/delivery.integration.ts +100 -190
- package/src/delivery/db/queries/preferences.ts +30 -0
- package/src/delivery/delivery-service.ts +8 -36
- package/src/delivery/feature.ts +10 -2
- package/src/delivery/handlers/log.query.ts +5 -7
- package/src/delivery/handlers/preferences.query.ts +2 -5
- package/src/delivery/tables.ts +26 -1
- package/src/delivery/upsert-preference.ts +8 -14
- package/src/feature-toggles/__tests__/feature-toggles.integration.ts +30 -30
- package/src/feature-toggles/__tests__/registered-system-tenant.test.ts +7 -6
- package/src/feature-toggles/db/queries/toggle-state.ts +25 -0
- package/src/feature-toggles/feature.ts +16 -2
- package/src/feature-toggles/global-feature-state-table.ts +1 -1
- package/src/feature-toggles/handlers/list.query.ts +9 -2
- package/src/feature-toggles/handlers/registered.query.ts +3 -7
- package/src/feature-toggles/handlers/set.write.ts +37 -25
- package/src/feature-toggles/toggle-runtime.ts +3 -6
- package/src/file-foundation/__tests__/feature.test.ts +1 -1
- package/src/file-foundation/__tests__/file-foundation.integration.ts +1 -1
- package/src/file-provider-inmemory/__tests__/feature.test.ts +1 -1
- package/src/file-provider-s3/__tests__/feature.test.ts +1 -1
- package/src/files/__tests__/files.integration.ts +18 -7
- package/src/files/schema/file-ref.ts +1 -1
- package/src/files-provider-s3/__tests__/env-helper.test.ts +1 -1
- package/src/files-provider-s3/__tests__/s3-provider.integration.ts +1 -1
- package/src/files-provider-s3/__tests__/s3-provider.test.ts +1 -1
- package/src/jobs/__tests__/job-system-user.integration.ts +1 -1
- package/src/jobs/__tests__/jobs-events.integration.ts +8 -21
- package/src/jobs/__tests__/jobs-feature.integration.ts +1 -1
- package/src/jobs/feature.ts +26 -15
- package/src/jobs/handlers/detail.query.ts +10 -8
- package/src/jobs/handlers/list.query.ts +9 -21
- package/src/jobs/handlers/retry.write.ts +2 -7
- package/src/jobs/job-run-logger.ts +3 -9
- package/src/jobs/job-run-table.ts +49 -17
- package/src/legal-pages/__tests__/legal-pages.integration.ts +1 -1
- package/src/mail-foundation/__tests__/feature.test.ts +1 -1
- package/src/mail-foundation/__tests__/mail-foundation.integration.ts +1 -1
- package/src/mail-transport-inmemory/__tests__/feature.test.ts +1 -1
- package/src/mail-transport-smtp/__tests__/feature.test.ts +1 -1
- package/src/rate-limiting/__tests__/rate-limiting.integration.ts +1 -1
- package/src/renderer-foundation/__tests__/api.test.ts +2 -2
- package/src/renderer-foundation/__tests__/collect-plugins.integration.ts +1 -1
- package/src/renderer-simple/__tests__/adapter.test.ts +2 -2
- package/src/renderer-simple/__tests__/simple-renderer.test.ts +1 -1
- package/src/secrets/__tests__/require-secrets-context.test.ts +6 -5
- package/src/secrets/__tests__/rotate.integration.ts +6 -9
- package/src/secrets/__tests__/secrets-events.integration.ts +6 -12
- package/src/secrets/__tests__/secrets.integration.ts +6 -11
- package/src/secrets/db/queries/read.ts +16 -0
- package/src/secrets/handlers/list.query.ts +16 -17
- package/src/secrets/handlers/rotate.job.ts +8 -12
- package/src/secrets/secrets-context.ts +9 -21
- package/src/secrets/table.ts +1 -1
- package/src/sessions/__tests__/cleanup.integration.ts +8 -6
- package/src/sessions/__tests__/password-auto-revoke.integration.ts +7 -6
- package/src/sessions/__tests__/sessions.integration.ts +23 -38
- package/src/sessions/__tests__/test-helpers.ts +1 -1
- package/src/sessions/db/queries/cleanup.ts +21 -0
- package/src/sessions/handlers/cleanup.job.ts +6 -29
- package/src/sessions/handlers/list.query.ts +24 -24
- package/src/sessions/handlers/mine.query.ts +24 -23
- package/src/sessions/handlers/revoke-all-for-user.write.ts +7 -11
- package/src/sessions/handlers/revoke-all-others.write.ts +7 -12
- package/src/sessions/handlers/revoke.write.ts +11 -18
- package/src/sessions/schema/user-session.ts +2 -2
- package/src/sessions/session-callbacks.ts +19 -21
- package/src/subscription-mollie/__tests__/feature.test.ts +1 -1
- package/src/subscription-mollie/__tests__/mollie-foundation.integration.ts +1 -1
- package/src/subscription-mollie/__tests__/verify-webhook.test.ts +8 -7
- package/src/subscription-stripe/__tests__/feature.test.ts +1 -1
- package/src/subscription-stripe/__tests__/plugin-methods.test.ts +14 -15
- package/src/subscription-stripe/__tests__/stripe-foundation.integration.ts +1 -1
- package/src/subscription-stripe/__tests__/verify-webhook.test.ts +14 -14
- package/src/subscription-stripe/verify-webhook.ts +1 -1
- package/src/template-resolver/__tests__/handlers.integration.ts +1 -1
- package/src/template-resolver/__tests__/template-resolver.integration.ts +3 -2
- package/src/template-resolver/api.ts +7 -13
- package/src/template-resolver/handlers/archive.write.ts +4 -7
- package/src/template-resolver/handlers/find-by-id.query.ts +4 -7
- package/src/template-resolver/handlers/list.query.ts +13 -21
- package/src/template-resolver/handlers/publish.write.ts +4 -7
- package/src/template-resolver/handlers/upsert-system.write.ts +7 -10
- package/src/template-resolver/handlers/upsert-tenant.write.ts +7 -10
- package/src/template-resolver/table.ts +2 -5
- package/src/tenant/__tests__/multi-tenant.integration.ts +1 -1
- package/src/tenant/__tests__/seed-testing.integration.ts +19 -45
- package/src/tenant/__tests__/tenant.integration.ts +1 -1
- package/src/tenant/handlers/active-tenant-ids.query.ts +3 -8
- package/src/tenant/handlers/add-member.write.ts +6 -8
- package/src/tenant/handlers/cancel-invitation.write.ts +5 -7
- package/src/tenant/handlers/invitations.query.ts +5 -10
- package/src/tenant/handlers/me.query.ts +2 -3
- package/src/tenant/handlers/members.query.ts +4 -5
- package/src/tenant/handlers/memberships.query.ts +2 -5
- package/src/tenant/handlers/remove-member.write.ts +6 -8
- package/src/tenant/handlers/resolve-user-ids.query.ts +6 -16
- package/src/tenant/handlers/update-member-roles.write.ts +6 -8
- package/src/tenant/invitation-table.ts +2 -5
- package/src/tenant/membership-table.ts +3 -6
- package/src/tenant/schema/tenant.ts +2 -2
- package/src/tenant/seeding.ts +12 -18
- package/src/text-content/README.md +1 -1
- package/src/text-content/__tests__/text-content.integration.ts +2 -2
- package/src/text-content/api.ts +2 -9
- package/src/text-content/handlers/by-slug.query.ts +6 -9
- package/src/text-content/handlers/by-tenant.query.ts +2 -2
- package/src/text-content/handlers/set.write.ts +7 -9
- package/src/text-content/seeding.ts +6 -9
- package/src/text-content/table.ts +2 -2
- package/src/text-content/web/__tests__/editor-read-only.test.tsx +31 -45
- package/src/text-content/web/__tests__/group-blocks.test.ts +1 -18
- package/src/text-content/web/client-plugin.tsx +11 -23
- package/src/tier-engine/__tests__/auto-default-tier.integration.ts +10 -16
- package/src/tier-engine/__tests__/compose-app.test.ts +1 -1
- package/src/tier-engine/__tests__/drift.test.ts +1 -1
- package/src/tier-engine/__tests__/resolver.integration.ts +6 -6
- package/src/tier-engine/__tests__/tier-engine.integration.ts +1 -1
- package/src/tier-engine/feature.ts +9 -16
- package/src/user/__tests__/seed-testing.integration.ts +10 -22
- package/src/user/__tests__/user-status.test.ts +1 -1
- package/src/user/__tests__/user.integration.ts +6 -5
- package/src/user/handlers/create.write.ts +5 -7
- package/src/user/handlers/find-for-auth.query.ts +5 -7
- package/src/user/schema/user.ts +2 -2
- package/src/user/seeding.ts +2 -3
- package/src/user-data-rights/__tests__/audit-log.integration.ts +24 -12
- package/src/user-data-rights/__tests__/cross-data-matrix.integration.ts +64 -37
- package/src/user-data-rights/__tests__/download.integration.ts +29 -46
- package/src/user-data-rights/__tests__/export-job-idempotency.integration.ts +35 -28
- package/src/user-data-rights/__tests__/export-job-schema.test.ts +2 -2
- package/src/user-data-rights/__tests__/policy-to-strategy.test.ts +1 -1
- package/src/user-data-rights/__tests__/request-cancel-deletion.integration.ts +11 -15
- package/src/user-data-rights/__tests__/request-deletion-callback.integration.ts +10 -12
- package/src/user-data-rights/__tests__/request-export.integration.ts +23 -16
- package/src/user-data-rights/__tests__/restriction-flow.integration.ts +24 -32
- package/src/user-data-rights/__tests__/run-export-jobs.integration.ts +142 -137
- package/src/user-data-rights/__tests__/run-forget-cleanup.integration.ts +46 -28
- package/src/user-data-rights/__tests__/run-user-export.integration.ts +20 -14
- package/src/user-data-rights/__tests__/token-helpers.test.ts +1 -1
- package/src/user-data-rights/__tests__/user-data-rights.integration.ts +1 -1
- package/src/user-data-rights/__tests__/zip-path.test.ts +1 -1
- package/src/user-data-rights/audit-download.ts +3 -3
- package/src/user-data-rights/db/queries/export-jobs.ts +23 -0
- package/src/user-data-rights/db/queries/forget-cleanup.ts +13 -0
- package/src/user-data-rights/handlers/cancel-deletion.write.ts +28 -22
- package/src/user-data-rights/handlers/download-by-job.query.ts +11 -21
- package/src/user-data-rights/handlers/download-by-token.query.ts +20 -35
- package/src/user-data-rights/handlers/export-status.query.ts +19 -33
- package/src/user-data-rights/handlers/lift-restriction.write.ts +7 -12
- package/src/user-data-rights/handlers/list-download-attempts.query.ts +14 -23
- package/src/user-data-rights/handlers/my-audit-log.query.ts +33 -23
- package/src/user-data-rights/handlers/request-deletion.write.ts +15 -15
- package/src/user-data-rights/handlers/request-export.write.ts +7 -11
- package/src/user-data-rights/handlers/restrict-account.write.ts +12 -12
- package/src/user-data-rights/run-export-jobs.ts +20 -60
- package/src/user-data-rights/run-forget-cleanup.ts +19 -33
- package/src/user-data-rights/run-user-export.ts +4 -6
- package/src/user-data-rights/schema/download-attempt.ts +2 -2
- package/src/user-data-rights/schema/download-token.ts +2 -2
- package/src/user-data-rights/schema/export-job.ts +2 -3
- package/src/user-data-rights-defaults/__tests__/user-data-rights-defaults.integration.ts +37 -30
- package/src/user-data-rights-defaults/db/queries/user-hook.ts +17 -0
- package/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +12 -27
- package/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +16 -18
- package/CHANGELOG.md +0 -689
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
// User-Explicit-Anforderung "exporte + fristen" — der Frist-Set-Pfad ist
|
|
10
10
|
// hier; der Frist-Ablauf-Cleanup folgt mit S2.U5b.
|
|
11
11
|
|
|
12
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
13
|
+
import { asRawClient, insertOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
12
14
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
13
15
|
import {
|
|
14
16
|
createTestUser,
|
|
@@ -19,8 +21,6 @@ import {
|
|
|
19
21
|
unsafeCreateEntityTable,
|
|
20
22
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
21
23
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
22
|
-
import { eq, sql } from "drizzle-orm";
|
|
23
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
24
24
|
import {
|
|
25
25
|
createComplianceProfilesFeature,
|
|
26
26
|
tenantComplianceProfileEntity,
|
|
@@ -71,9 +71,9 @@ afterAll(async () => {
|
|
|
71
71
|
beforeEach(async () => {
|
|
72
72
|
// Hard-clean User-Rows fuer einen sauberen Start je Test. softDelete
|
|
73
73
|
// wuerde sonst row-state aus voherigen Tests einschleppen.
|
|
74
|
-
await stack.db.
|
|
75
|
-
await stack.db.
|
|
76
|
-
await stack.db.
|
|
74
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM "${userTable.tableName}"`);
|
|
75
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_tenant_compliance_profiles`);
|
|
76
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM kumiko_events`);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
// gracePeriodEnd ist `instant()` (Temporal.Instant in JS). Nicht JS-Date —
|
|
@@ -91,7 +91,7 @@ async function seedAlice(
|
|
|
91
91
|
gracePeriodEnd: Instant | null;
|
|
92
92
|
}> = {},
|
|
93
93
|
): Promise<void> {
|
|
94
|
-
await stack.db
|
|
94
|
+
await insertOne(stack.db, userTable, {
|
|
95
95
|
id: aliceUser.id,
|
|
96
96
|
tenantId: tenantA,
|
|
97
97
|
email: "alice@example.com",
|
|
@@ -109,14 +109,10 @@ async function fetchAlice(): Promise<{
|
|
|
109
109
|
status: string;
|
|
110
110
|
gracePeriodEnd: Instant | null;
|
|
111
111
|
} | null> {
|
|
112
|
-
const rows = (await stack.db
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
})
|
|
117
|
-
.from(userTable)
|
|
118
|
-
.where(eq(userTable["id"], aliceUser.id))
|
|
119
|
-
.limit(1)) as Array<{ status: string; gracePeriodEnd: Instant | null }>;
|
|
112
|
+
const rows = (await selectMany(stack.db, userTable, { id: aliceUser.id })) as Array<{
|
|
113
|
+
status: string;
|
|
114
|
+
gracePeriodEnd: Instant | null;
|
|
115
|
+
}>;
|
|
120
116
|
return rows[0] ?? null;
|
|
121
117
|
}
|
|
122
118
|
|
|
@@ -348,7 +344,7 @@ describe("Cross-User-Isolation", () => {
|
|
|
348
344
|
tenantId: tenantA,
|
|
349
345
|
roles: ["Member"],
|
|
350
346
|
});
|
|
351
|
-
await stack.db
|
|
347
|
+
await insertOne(stack.db, userTable, {
|
|
352
348
|
id: testUserId(43),
|
|
353
349
|
tenantId: tenantA,
|
|
354
350
|
email: "bob@example.com",
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
// Der Code-Comment in handlers/request-deletion.write.ts behauptet beide
|
|
8
8
|
// Properties — dieser Test verifiziert sie end-to-end.
|
|
9
9
|
|
|
10
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
11
|
+
import { asRawClient, insertOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
10
12
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
11
13
|
import {
|
|
12
14
|
createTestUser,
|
|
@@ -15,8 +17,6 @@ import {
|
|
|
15
17
|
testTenantId,
|
|
16
18
|
unsafeCreateEntityTable,
|
|
17
19
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
18
|
-
import { eq, sql } from "drizzle-orm";
|
|
19
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
20
20
|
import {
|
|
21
21
|
createComplianceProfilesFeature,
|
|
22
22
|
tenantComplianceProfileEntity,
|
|
@@ -76,13 +76,13 @@ afterAll(async () => {
|
|
|
76
76
|
beforeEach(async () => {
|
|
77
77
|
state.calls = [];
|
|
78
78
|
state.shouldThrow = false;
|
|
79
|
-
await stack.db.
|
|
80
|
-
await stack.db.
|
|
81
|
-
await stack.db.
|
|
79
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM "${userTable.tableName}"`);
|
|
80
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_tenant_compliance_profiles`);
|
|
81
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM kumiko_events`);
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
async function seedAlice(email: string = "alice@example.com"): Promise<void> {
|
|
85
|
-
await stack.db
|
|
85
|
+
await insertOne(stack.db, userTable, {
|
|
86
86
|
id: aliceUser.id,
|
|
87
87
|
tenantId: tenantA,
|
|
88
88
|
email,
|
|
@@ -137,11 +137,9 @@ describe("request-deletion :: sendDeletionRequestedEmail callback", () => {
|
|
|
137
137
|
// DB-State ist tatsaechlich geflipt — der zentrale "best-effort"-
|
|
138
138
|
// Beweis. Wenn das Write die Email-Failure-Exception bubbelt, waere
|
|
139
139
|
// der Status hier noch Active.
|
|
140
|
-
const rows = (await stack.db
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.where(eq(userTable["id"], aliceUser.id))
|
|
144
|
-
.limit(1)) as Array<{ status: string }>;
|
|
140
|
+
const rows = (await selectMany(stack.db, userTable, { id: aliceUser.id })) as Array<{
|
|
141
|
+
status: string;
|
|
142
|
+
}>;
|
|
145
143
|
expect(rows[0]?.status).toBe(USER_STATUS.DeletionRequested);
|
|
146
144
|
});
|
|
147
145
|
|
|
@@ -152,7 +150,7 @@ describe("request-deletion :: sendDeletionRequestedEmail callback", () => {
|
|
|
152
150
|
});
|
|
153
151
|
|
|
154
152
|
test("422 user_not_in_active_state → callback NICHT gefeuert", async () => {
|
|
155
|
-
await stack.db
|
|
153
|
+
await insertOne(stack.db, userTable, {
|
|
156
154
|
id: aliceUser.id,
|
|
157
155
|
tenantId: tenantA,
|
|
158
156
|
email: "alice@example.com",
|
|
@@ -17,6 +17,13 @@
|
|
|
17
17
|
// - Status-Polling: User sieht eigene Jobs, Cross-User-Isolation,
|
|
18
18
|
// hasJob=false wenn nichts da
|
|
19
19
|
|
|
20
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
21
|
+
import {
|
|
22
|
+
asRawClient,
|
|
23
|
+
insertOne,
|
|
24
|
+
selectMany,
|
|
25
|
+
updateMany,
|
|
26
|
+
} from "@cosmicdrift/kumiko-framework/bun-db";
|
|
20
27
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
21
28
|
import {
|
|
22
29
|
createTestUser,
|
|
@@ -26,8 +33,6 @@ import {
|
|
|
26
33
|
unsafeCreateEntityTable,
|
|
27
34
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
28
35
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
29
|
-
import { sql } from "drizzle-orm";
|
|
30
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
31
36
|
import { createComplianceProfilesFeature } from "../../compliance-profiles";
|
|
32
37
|
import { createDataRetentionFeature } from "../../data-retention";
|
|
33
38
|
import { createUserFeature } from "../../user";
|
|
@@ -63,8 +68,8 @@ afterAll(async () => {
|
|
|
63
68
|
});
|
|
64
69
|
|
|
65
70
|
beforeEach(async () => {
|
|
66
|
-
await stack.db.
|
|
67
|
-
await stack.db.
|
|
71
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM "${exportJobsTable.tableName}"`);
|
|
72
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM kumiko_events`);
|
|
68
73
|
});
|
|
69
74
|
|
|
70
75
|
type RequestExportResponse = {
|
|
@@ -81,7 +86,7 @@ describe("request-export :: happy path", () => {
|
|
|
81
86
|
expect(result.status).toBe(EXPORT_JOB_STATUS.Pending);
|
|
82
87
|
expect(result.jobId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-/);
|
|
83
88
|
|
|
84
|
-
const rows = await stack.db
|
|
89
|
+
const rows = await selectMany(stack.db, exportJobsTable);
|
|
85
90
|
expect(rows).toHaveLength(1);
|
|
86
91
|
// biome-ignore lint/suspicious/noExplicitAny: drizzle-row typing
|
|
87
92
|
expect((rows[0] as any).userId).toBe(aliceUser.id);
|
|
@@ -94,7 +99,7 @@ describe("request-export :: happy path", () => {
|
|
|
94
99
|
test("Event 'export-job.created' im Stream", async () => {
|
|
95
100
|
await stack.http.writeOk(REQUEST_EXPORT, {}, aliceUser);
|
|
96
101
|
|
|
97
|
-
const events = await stack.db.
|
|
102
|
+
const events = await asRawClient(stack.db).unsafe(`
|
|
98
103
|
SELECT type FROM kumiko_events WHERE aggregate_type = 'export-job'
|
|
99
104
|
`);
|
|
100
105
|
// biome-ignore lint/suspicious/noExplicitAny: drizzle-execute typing
|
|
@@ -114,10 +119,10 @@ describe("request-export :: App-side-Idempotency (primaerer Pfad)", () => {
|
|
|
114
119
|
expect(second.jobId).toBe(first.jobId);
|
|
115
120
|
expect(second.status).toBe(EXPORT_JOB_STATUS.Pending);
|
|
116
121
|
|
|
117
|
-
const rows = await stack.db
|
|
122
|
+
const rows = await selectMany(stack.db, exportJobsTable);
|
|
118
123
|
expect(rows).toHaveLength(1);
|
|
119
124
|
|
|
120
|
-
const events = await stack.db.
|
|
125
|
+
const events = await asRawClient(stack.db).unsafe(`
|
|
121
126
|
SELECT type FROM kumiko_events WHERE aggregate_type = 'export-job'
|
|
122
127
|
`);
|
|
123
128
|
// biome-ignore lint/suspicious/noExplicitAny: drizzle-execute typing
|
|
@@ -128,16 +133,18 @@ describe("request-export :: App-side-Idempotency (primaerer Pfad)", () => {
|
|
|
128
133
|
test("Klick nach done-Job ist NEUER Job (Audit-Historie wird nicht blockiert)", async () => {
|
|
129
134
|
const first = await stack.http.writeOk<RequestExportResponse>(REQUEST_EXPORT, {}, aliceUser);
|
|
130
135
|
// Worker-Simulation: status auf done flippen (direct-update OK in Test)
|
|
131
|
-
await
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
await updateMany(
|
|
137
|
+
stack.db,
|
|
138
|
+
exportJobsTable,
|
|
139
|
+
{ status: EXPORT_JOB_STATUS.Done },
|
|
140
|
+
{ id: first.jobId },
|
|
141
|
+
);
|
|
135
142
|
|
|
136
143
|
const second = await stack.http.writeOk<RequestExportResponse>(REQUEST_EXPORT, {}, aliceUser);
|
|
137
144
|
expect(second.isExisting).toBe(false);
|
|
138
145
|
expect(second.jobId).not.toBe(first.jobId);
|
|
139
146
|
|
|
140
|
-
const rows = await stack.db
|
|
147
|
+
const rows = await selectMany(stack.db, exportJobsTable);
|
|
141
148
|
expect(rows).toHaveLength(2);
|
|
142
149
|
});
|
|
143
150
|
});
|
|
@@ -154,7 +161,7 @@ describe("request-export :: Cross-Tenant (Plan-Doc-Pflicht-Test)", () => {
|
|
|
154
161
|
expect(fromB.jobId).toBe(fromA.jobId);
|
|
155
162
|
|
|
156
163
|
// Genau 1 Job (kein 2. fuer Tenant B)
|
|
157
|
-
const rows = await stack.db
|
|
164
|
+
const rows = await selectMany(stack.db, exportJobsTable);
|
|
158
165
|
expect(rows).toHaveLength(1);
|
|
159
166
|
// requestedFromTenantId = Tenant aus 1. Klick (= A), nicht B
|
|
160
167
|
// biome-ignore lint/suspicious/noExplicitAny: drizzle-row typing
|
|
@@ -183,7 +190,7 @@ describe("request-export :: Race-Schutz (Promise.all parallel)", () => {
|
|
|
183
190
|
const winners = [a, b].filter((r) => r.isExisting === false);
|
|
184
191
|
expect(winners).toHaveLength(1);
|
|
185
192
|
|
|
186
|
-
const rows = await stack.db
|
|
193
|
+
const rows = await selectMany(stack.db, exportJobsTable);
|
|
187
194
|
expect(rows).toHaveLength(1);
|
|
188
195
|
});
|
|
189
196
|
|
|
@@ -241,7 +248,7 @@ describe("export-status :: User-Polling", () => {
|
|
|
241
248
|
const T = getTemporal();
|
|
242
249
|
// 1. Job done in der Vergangenheit
|
|
243
250
|
const oldJobId = "11111111-1111-4111-8111-111111111111";
|
|
244
|
-
await stack.db
|
|
251
|
+
await insertOne(stack.db, exportJobsTable, {
|
|
245
252
|
id: oldJobId,
|
|
246
253
|
tenantId: tenantA,
|
|
247
254
|
userId: aliceUser.id,
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
// - State-Transition-Matrix: Active↔Restricted, andere Uebergaenge
|
|
11
11
|
// fehlgeschlagen mit klaren error codes
|
|
12
12
|
|
|
13
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
13
14
|
import { randomBytes } from "node:crypto";
|
|
15
|
+
import { asRawClient, selectMany, updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
14
16
|
import { createEncryptionProvider } from "@cosmicdrift/kumiko-framework/db";
|
|
15
17
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
16
18
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
@@ -23,8 +25,6 @@ import {
|
|
|
23
25
|
unsafePushTables,
|
|
24
26
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
25
27
|
import { createLateBoundHolder } from "@cosmicdrift/kumiko-framework/testing";
|
|
26
|
-
import { eq, sql } from "drizzle-orm";
|
|
27
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
28
28
|
import { AuthErrors, AuthHandlers } from "../../auth-email-password/constants";
|
|
29
29
|
import { createAuthEmailPasswordFeature } from "../../auth-email-password/feature";
|
|
30
30
|
import { hashPassword } from "../../auth-email-password/password-hashing";
|
|
@@ -97,11 +97,11 @@ afterAll(async () => {
|
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
beforeEach(async () => {
|
|
100
|
-
await stack.db.
|
|
101
|
-
await stack.db.
|
|
102
|
-
await stack.db.
|
|
103
|
-
await stack.db.
|
|
104
|
-
await stack.db.
|
|
100
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM "${userSessionTable.tableName}"`);
|
|
101
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM "${userTable.tableName}"`);
|
|
102
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM "${tenantMembershipsTable.tableName}"`);
|
|
103
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM read_tenant_compliance_profiles`);
|
|
104
|
+
await asRawClient(stack.db).unsafe(`DELETE FROM kumiko_events`);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
async function seedAliceWithMembership(
|
|
@@ -114,7 +114,7 @@ async function seedAliceWithMembership(
|
|
|
114
114
|
TestUsers.systemAdmin,
|
|
115
115
|
);
|
|
116
116
|
if (status !== USER_STATUS.Active) {
|
|
117
|
-
await stack.db
|
|
117
|
+
await updateMany(stack.db, userTable, { status }, { id: created.id });
|
|
118
118
|
}
|
|
119
119
|
await seedTenantMembership(stack.db, {
|
|
120
120
|
userId: created.id,
|
|
@@ -141,10 +141,7 @@ describe("S2.U6 :: restrict-account state-transitions", () => {
|
|
|
141
141
|
expect(loginRes.status).toBe(200);
|
|
142
142
|
|
|
143
143
|
// Session-Row vorhanden + live (revokedAt=null).
|
|
144
|
-
const sessionsBefore = (await stack.db
|
|
145
|
-
.select({ id: userSessionTable["id"], revokedAt: userSessionTable["revokedAt"] })
|
|
146
|
-
.from(userSessionTable)
|
|
147
|
-
.where(eq(userSessionTable["userId"], userId))) as Array<{
|
|
144
|
+
const sessionsBefore = (await selectMany(stack.db, userSessionTable, { userId })) as Array<{
|
|
148
145
|
id: string;
|
|
149
146
|
revokedAt: unknown;
|
|
150
147
|
}>;
|
|
@@ -166,17 +163,15 @@ describe("S2.U6 :: restrict-account state-transitions", () => {
|
|
|
166
163
|
expect(result.userId).toBe(userId);
|
|
167
164
|
|
|
168
165
|
// DB-State: status=Restricted.
|
|
169
|
-
const userRow = (await stack.db
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
.where(eq(userTable["id"], userId))) as Array<{ status: string }>;
|
|
166
|
+
const userRow = (await selectMany(stack.db, userTable, { id: userId })) as Array<{
|
|
167
|
+
status: string;
|
|
168
|
+
}>;
|
|
173
169
|
expect(userRow[0]?.status).toBe(USER_STATUS.Restricted);
|
|
174
170
|
|
|
175
171
|
// Alle Sessions revoked (revokedAt != null).
|
|
176
|
-
const sessionsAfter = (await stack.db
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
.where(eq(userSessionTable["userId"], userId))) as Array<{ revokedAt: unknown }>;
|
|
172
|
+
const sessionsAfter = (await selectMany(stack.db, userSessionTable, { userId })) as Array<{
|
|
173
|
+
revokedAt: unknown;
|
|
174
|
+
}>;
|
|
180
175
|
expect(sessionsAfter.every((s) => s.revokedAt !== null)).toBe(true);
|
|
181
176
|
});
|
|
182
177
|
|
|
@@ -204,10 +199,9 @@ describe("S2.U6 :: lift-restriction state-transitions", () => {
|
|
|
204
199
|
const result = await stack.http.writeOk<{ status: string }>(LIFT, {}, aliceUser);
|
|
205
200
|
expect(result.status).toBe(USER_STATUS.Active);
|
|
206
201
|
|
|
207
|
-
const userRow = (await stack.db
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
.where(eq(userTable["id"], userId))) as Array<{ status: string }>;
|
|
202
|
+
const userRow = (await selectMany(stack.db, userTable, { id: userId })) as Array<{
|
|
203
|
+
status: string;
|
|
204
|
+
}>;
|
|
211
205
|
expect(userRow[0]?.status).toBe(USER_STATUS.Active);
|
|
212
206
|
});
|
|
213
207
|
|
|
@@ -279,10 +273,9 @@ describe("S2.U6 :: Cross-Feature sessions.revokeAllForUser direct", () => {
|
|
|
279
273
|
expect(a.status).toBe(200);
|
|
280
274
|
expect(b.status).toBe(200);
|
|
281
275
|
|
|
282
|
-
const liveBefore = (await stack.db
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
.where(eq(userSessionTable["userId"], userId))) as Array<{ id: string }>;
|
|
276
|
+
const liveBefore = (await selectMany(stack.db, userSessionTable, { userId })) as Array<{
|
|
277
|
+
id: string;
|
|
278
|
+
}>;
|
|
286
279
|
expect(liveBefore.length).toBe(2);
|
|
287
280
|
|
|
288
281
|
// System-Caller.
|
|
@@ -300,10 +293,9 @@ describe("S2.U6 :: Cross-Feature sessions.revokeAllForUser direct", () => {
|
|
|
300
293
|
expect(result.userId).toBe(userId);
|
|
301
294
|
|
|
302
295
|
// Alle revoked.
|
|
303
|
-
const revoked = (await stack.db
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
.where(eq(userSessionTable["userId"], userId))) as Array<{ revokedAt: unknown }>;
|
|
296
|
+
const revoked = (await selectMany(stack.db, userSessionTable, { userId })) as Array<{
|
|
297
|
+
revokedAt: unknown;
|
|
298
|
+
}>;
|
|
307
299
|
expect(revoked.every((s) => s.revokedAt !== null)).toBe(true);
|
|
308
300
|
});
|
|
309
301
|
});
|