@cosmicdrift/kumiko-bundled-features 0.15.0 → 0.18.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 (111) hide show
  1. package/package.json +1 -1
  2. package/src/billing-foundation/get-subscription-for-tenant.ts +2 -2
  3. package/src/cap-counter/__tests__/{cap-counter.integration.ts → cap-counter.integration.test.ts} +14 -3
  4. package/src/cap-counter/__tests__/enforce-cap.test.ts +8 -4
  5. package/src/cap-counter/__tests__/{with-cap-enforcement.integration.ts → with-cap-enforcement.integration.test.ts} +14 -3
  6. package/src/cap-counter/enforce-cap.ts +2 -4
  7. package/src/cap-counter/handlers/get-counter.query.ts +1 -3
  8. package/src/cap-counter/handlers/increment.write.ts +1 -2
  9. package/src/cap-counter/handlers/mark-soft-warned.write.ts +1 -2
  10. package/src/channel-in-app/in-app-channel.ts +1 -3
  11. package/src/compliance-profiles/_internal/parse-override.ts +19 -0
  12. package/src/compliance-profiles/handlers/for-tenant.query.ts +6 -25
  13. package/src/compliance-profiles/resolve-for-tenant.ts +6 -20
  14. package/src/custom-fields/__tests__/cross-tenant-field-delete.integration.test.ts +177 -0
  15. package/src/custom-fields/__tests__/{custom-fields.integration.ts → custom-fields.integration.test.ts} +105 -0
  16. package/src/custom-fields/db/queries/projection.ts +33 -4
  17. package/src/custom-fields/db/queries/retention.ts +2 -2
  18. package/src/custom-fields/db/queries/user-data-rights.ts +6 -3
  19. package/src/custom-fields/feature.ts +10 -4
  20. package/src/custom-fields/handlers/delete-system-field.write.ts +5 -1
  21. package/src/custom-fields/handlers/delete-tenant-field.write.ts +1 -1
  22. package/src/custom-fields/handlers/set-custom-field.write.ts +33 -17
  23. package/src/custom-fields/lib/field-access.ts +39 -14
  24. package/src/custom-fields/lib/value-schema.ts +45 -0
  25. package/src/custom-fields/run-retention.ts +1 -1
  26. package/src/custom-fields/wire-for-entity.ts +22 -4
  27. package/src/custom-fields/wire-user-data-rights.ts +3 -2
  28. package/src/delivery/delivery-service.ts +1 -1
  29. package/src/delivery/feature.ts +8 -1
  30. package/src/delivery/types.ts +2 -2
  31. package/src/feature-toggles/__tests__/{feature-toggles.integration.ts → feature-toggles.integration.test.ts} +6 -6
  32. package/src/feature-toggles/handlers/set.write.ts +10 -8
  33. package/src/jobs/feature.ts +4 -1
  34. package/src/subscription-stripe/__tests__/{stripe-foundation.integration.ts → stripe-foundation.integration.test.ts} +7 -10
  35. package/src/tier-engine/__tests__/{resolver.integration.ts → resolver.integration.test.ts} +4 -3
  36. package/src/user-data-rights/__tests__/{audit-log.integration.ts → audit-log.integration.test.ts} +12 -5
  37. package/src/user-data-rights/__tests__/{cross-data-matrix.integration.ts → cross-data-matrix.integration.test.ts} +29 -12
  38. package/src/user-data-rights/__tests__/{download.integration.ts → download.integration.test.ts} +15 -7
  39. package/src/user-data-rights/__tests__/{export-job-idempotency.integration.ts → export-job-idempotency.integration.test.ts} +13 -11
  40. package/src/user-data-rights/__tests__/{request-cancel-deletion.integration.ts → request-cancel-deletion.integration.test.ts} +8 -7
  41. package/src/user-data-rights/__tests__/{request-deletion-callback.integration.ts → request-deletion-callback.integration.test.ts} +8 -5
  42. package/src/user-data-rights/__tests__/{request-export.integration.ts → request-export.integration.test.ts} +6 -3
  43. package/src/user-data-rights/__tests__/{restriction-flow.integration.ts → restriction-flow.integration.test.ts} +11 -8
  44. package/src/user-data-rights/__tests__/{run-export-jobs.integration.ts → run-export-jobs.integration.test.ts} +25 -13
  45. package/src/user-data-rights/__tests__/{run-forget-cleanup.integration.ts → run-forget-cleanup.integration.test.ts} +6 -3
  46. package/src/user-data-rights/__tests__/{run-user-export.integration.ts → run-user-export.integration.test.ts} +6 -3
  47. package/src/user-data-rights/__tests__/{user-data-rights.integration.ts → user-data-rights.integration.test.ts} +3 -1
  48. package/src/user-data-rights/db/queries/export-jobs.ts +6 -5
  49. package/src/user-data-rights/db/queries/forget-cleanup.ts +11 -6
  50. package/src/user-data-rights/handlers/cancel-deletion.write.ts +5 -10
  51. package/src/user-data-rights/handlers/export-status.query.ts +12 -12
  52. package/src/user-data-rights/run-export-jobs.ts +2 -5
  53. package/src/user-data-rights/run-forget-cleanup.ts +0 -1
  54. package/src/user-data-rights-defaults/__tests__/{user-data-rights-defaults.integration.ts → user-data-rights-defaults.integration.test.ts} +2 -0
  55. /package/src/__tests__/{es-ops-e2e.integration.ts → es-ops-e2e.integration.test.ts} +0 -0
  56. /package/src/audit/__tests__/{audit.integration.ts → audit.integration.test.ts} +0 -0
  57. /package/src/auth-email-password/__tests__/{account-lockout-no-redis.integration.ts → account-lockout-no-redis.integration.test.ts} +0 -0
  58. /package/src/auth-email-password/__tests__/{account-lockout.integration.ts → account-lockout.integration.test.ts} +0 -0
  59. /package/src/auth-email-password/__tests__/{auth-claims.integration.ts → auth-claims.integration.test.ts} +0 -0
  60. /package/src/auth-email-password/__tests__/{auth.integration.ts → auth.integration.test.ts} +0 -0
  61. /package/src/auth-email-password/__tests__/{email-verification.integration.ts → email-verification.integration.test.ts} +0 -0
  62. /package/src/auth-email-password/__tests__/{identity-v3-login.integration.ts → identity-v3-login.integration.test.ts} +0 -0
  63. /package/src/auth-email-password/__tests__/{invite-flow.integration.ts → invite-flow.integration.test.ts} +0 -0
  64. /package/src/auth-email-password/__tests__/{multi-roles.integration.ts → multi-roles.integration.test.ts} +0 -0
  65. /package/src/auth-email-password/__tests__/{password-reset.integration.ts → password-reset.integration.test.ts} +0 -0
  66. /package/src/auth-email-password/__tests__/{public-routes-rate-limit.integration.ts → public-routes-rate-limit.integration.test.ts} +0 -0
  67. /package/src/auth-email-password/__tests__/{seed-admin.integration.ts → seed-admin.integration.test.ts} +0 -0
  68. /package/src/auth-email-password/__tests__/{session-callbacks.integration.ts → session-callbacks.integration.test.ts} +0 -0
  69. /package/src/auth-email-password/__tests__/{session-strict-mode.integration.ts → session-strict-mode.integration.test.ts} +0 -0
  70. /package/src/auth-email-password/__tests__/{signup-flow.integration.ts → signup-flow.integration.test.ts} +0 -0
  71. /package/src/billing-foundation/__tests__/{billing-foundation.integration.ts → billing-foundation.integration.test.ts} +0 -0
  72. /package/src/compliance-profiles/__tests__/{compliance-profiles.integration.ts → compliance-profiles.integration.test.ts} +0 -0
  73. /package/src/compliance-profiles/__tests__/{seeding.integration.ts → seeding.integration.test.ts} +0 -0
  74. /package/src/config/__tests__/{cascade.integration.ts → cascade.integration.test.ts} +0 -0
  75. /package/src/config/__tests__/{config.integration.ts → config.integration.test.ts} +0 -0
  76. /package/src/custom-fields/__tests__/{audit-integration.integration.ts → audit-integration.integration.test.ts} +0 -0
  77. /package/src/custom-fields/__tests__/{field-access.integration.ts → field-access.integration.test.ts} +0 -0
  78. /package/src/custom-fields/__tests__/{quota.integration.ts → quota.integration.test.ts} +0 -0
  79. /package/src/custom-fields/__tests__/{retention.integration.ts → retention.integration.test.ts} +0 -0
  80. /package/src/custom-fields/__tests__/{user-data-rights.integration.ts → user-data-rights.integration.test.ts} +0 -0
  81. /package/src/data-retention/__tests__/{data-retention.integration.ts → data-retention.integration.test.ts} +0 -0
  82. /package/src/data-retention/__tests__/{policy-for.integration.ts → policy-for.integration.test.ts} +0 -0
  83. /package/src/delivery/__tests__/{delivery-events.integration.ts → delivery-events.integration.test.ts} +0 -0
  84. /package/src/delivery/__tests__/{delivery.integration.ts → delivery.integration.test.ts} +0 -0
  85. /package/src/file-foundation/__tests__/{file-foundation.integration.ts → file-foundation.integration.test.ts} +0 -0
  86. /package/src/files/__tests__/{files.integration.ts → files.integration.test.ts} +0 -0
  87. /package/src/files-provider-s3/__tests__/{s3-provider.integration.ts → s3-provider.integration.test.ts} +0 -0
  88. /package/src/jobs/__tests__/{job-system-user.integration.ts → job-system-user.integration.test.ts} +0 -0
  89. /package/src/jobs/__tests__/{jobs-events.integration.ts → jobs-events.integration.test.ts} +0 -0
  90. /package/src/jobs/__tests__/{jobs-feature.integration.ts → jobs-feature.integration.test.ts} +0 -0
  91. /package/src/legal-pages/__tests__/{legal-pages.integration.ts → legal-pages.integration.test.ts} +0 -0
  92. /package/src/mail-foundation/__tests__/{mail-foundation.integration.ts → mail-foundation.integration.test.ts} +0 -0
  93. /package/src/rate-limiting/__tests__/{rate-limiting.integration.ts → rate-limiting.integration.test.ts} +0 -0
  94. /package/src/renderer-foundation/__tests__/{collect-plugins.integration.ts → collect-plugins.integration.test.ts} +0 -0
  95. /package/src/secrets/__tests__/{rotate.integration.ts → rotate.integration.test.ts} +0 -0
  96. /package/src/secrets/__tests__/{secrets-events.integration.ts → secrets-events.integration.test.ts} +0 -0
  97. /package/src/secrets/__tests__/{secrets.integration.ts → secrets.integration.test.ts} +0 -0
  98. /package/src/sessions/__tests__/{cleanup.integration.ts → cleanup.integration.test.ts} +0 -0
  99. /package/src/sessions/__tests__/{password-auto-revoke.integration.ts → password-auto-revoke.integration.test.ts} +0 -0
  100. /package/src/sessions/__tests__/{sessions.integration.ts → sessions.integration.test.ts} +0 -0
  101. /package/src/subscription-mollie/__tests__/{mollie-foundation.integration.ts → mollie-foundation.integration.test.ts} +0 -0
  102. /package/src/template-resolver/__tests__/{handlers.integration.ts → handlers.integration.test.ts} +0 -0
  103. /package/src/template-resolver/__tests__/{template-resolver.integration.ts → template-resolver.integration.test.ts} +0 -0
  104. /package/src/tenant/__tests__/{multi-tenant.integration.ts → multi-tenant.integration.test.ts} +0 -0
  105. /package/src/tenant/__tests__/{seed-testing.integration.ts → seed-testing.integration.test.ts} +0 -0
  106. /package/src/tenant/__tests__/{tenant.integration.ts → tenant.integration.test.ts} +0 -0
  107. /package/src/text-content/__tests__/{text-content.integration.ts → text-content.integration.test.ts} +0 -0
  108. /package/src/tier-engine/__tests__/{auto-default-tier.integration.ts → auto-default-tier.integration.test.ts} +0 -0
  109. /package/src/tier-engine/__tests__/{tier-engine.integration.ts → tier-engine.integration.test.ts} +0 -0
  110. /package/src/user/__tests__/{seed-testing.integration.ts → seed-testing.integration.test.ts} +0 -0
  111. /package/src/user/__tests__/{user.integration.ts → user.integration.test.ts} +0 -0
@@ -1,6 +1,7 @@
1
- import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
+ import { exportJobsTable } from "../../schema/export-job";
4
5
 
5
6
  export type ExportJobCleanupCandidate = {
6
7
  readonly id: string;
@@ -16,8 +17,8 @@ export async function selectExportJobsForStorageCleanup(
16
17
  doneStatus: string,
17
18
  failedStatus: string,
18
19
  ): Promise<readonly ExportJobCleanupCandidate[]> {
19
- return asRawClient(db).unsafe<ExportJobCleanupCandidate>(
20
- `SELECT id, version, status, requested_from_tenant_id AS "requestedFromTenantId", download_storage_key AS "downloadStorageKey", expires_at AS "expiresAt" FROM read_export_jobs WHERE status IN ($1, $2) AND download_storage_key IS NOT NULL`,
21
- [doneStatus, failedStatus],
22
- );
20
+ return selectMany<ExportJobCleanupCandidate>(db, exportJobsTable, {
21
+ status: { in: [doneStatus, failedStatus] },
22
+ downloadStorageKey: { ne: null },
23
+ });
23
24
  }
@@ -1,13 +1,18 @@
1
- import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
3
+ import { userTable } from "../../../user";
3
4
 
4
5
  export async function selectUsersDueForForgetCleanup(
5
6
  db: DbConnection,
6
7
  status: string,
7
- gracePeriodEnd: string,
8
+ gracePeriodEndCutoff: Temporal.Instant | string,
8
9
  ): Promise<readonly { id: string }[]> {
9
- return asRawClient(db).unsafe<{ id: string }>(
10
- `SELECT id FROM read_users WHERE status = $1 AND grace_period_end <= $2`,
11
- [status, gracePeriodEnd],
12
- );
10
+ const cutoff =
11
+ typeof gracePeriodEndCutoff === "string"
12
+ ? Temporal.Instant.from(gracePeriodEndCutoff)
13
+ : gracePeriodEndCutoff;
14
+ return selectMany<{ id: string }>(db, userTable, {
15
+ status,
16
+ gracePeriodEnd: { lte: cutoff },
17
+ });
13
18
  }
@@ -23,7 +23,7 @@ export const cancelDeletionWrite = defineWriteHandler({
23
23
  // ctx.db.raw (kein TenantDb-Wrapper) weil User-Entity tenant-agnostisch
24
24
  // ist — siehe request-deletion.write.ts fuer die Begruendung. Cancel
25
25
  // muss aus jedem Tenant-Mode den User finden + zuruecksetzen koennen.
26
- const row = await fetchOne<{ status: string; grace_period_end: Date | null }>(
26
+ const row = await fetchOne<{ status: string; gracePeriodEnd: Temporal.Instant | null }>(
27
27
  ctx.db.raw,
28
28
  userTable,
29
29
  { id: event.user.id },
@@ -37,26 +37,21 @@ export const cancelDeletionWrite = defineWriteHandler({
37
37
  );
38
38
  }
39
39
 
40
- if (row["status"] !== USER_STATUS.DeletionRequested) {
40
+ if (row.status !== USER_STATUS.DeletionRequested) {
41
41
  return writeFailure(
42
42
  new UnprocessableError("no_pending_deletion", {
43
43
  details: {
44
44
  reason: "no_pending_deletion",
45
- currentStatus: row["status"],
45
+ currentStatus: row.status,
46
46
  },
47
47
  }),
48
48
  );
49
49
  }
50
50
 
51
- // inGrace computed JS-side: compare grace_period_end (Temporal.Instant
52
- // from bun-db boundary) against current server clock.
53
- const gracePeriodEnd = row["grace_period_end"];
51
+ const gracePeriodEnd = row.gracePeriodEnd;
54
52
  const inGrace =
55
53
  gracePeriodEnd != null &&
56
- Temporal.Instant.compare(
57
- gracePeriodEnd as unknown as Temporal.Instant,
58
- Temporal.Now.instant(),
59
- ) > 0;
54
+ Temporal.Instant.compare(gracePeriodEnd, Temporal.Now.instant()) > 0;
60
55
 
61
56
  if (!inGrace) {
62
57
  return writeFailure(
@@ -22,11 +22,11 @@ type Instant = InstanceType<ReturnType<typeof getTemporal>["Instant"]>;
22
22
  type ExportJobRow = {
23
23
  readonly id: string;
24
24
  readonly status: string;
25
- readonly requested_at: Instant;
26
- readonly completed_at: Instant | null;
27
- readonly expires_at: Instant | null;
28
- readonly error_message: string | null;
29
- readonly bytes_written: number | null;
25
+ readonly requestedAt: Instant;
26
+ readonly completedAt: Instant | null;
27
+ readonly expiresAt: Instant | null;
28
+ readonly errorMessage: string | null;
29
+ readonly bytesWritten: number | null;
30
30
  };
31
31
 
32
32
  export const exportStatusQuery = defineQueryHandler({
@@ -49,13 +49,13 @@ export const exportStatusQuery = defineQueryHandler({
49
49
  return {
50
50
  hasJob: true as const,
51
51
  job: {
52
- id: latest["id"],
53
- status: latest["status"],
54
- requestedAt: latest["requested_at"].toString(),
55
- completedAt: latest["completed_at"]?.toString() ?? null,
56
- expiresAt: latest["expires_at"]?.toString() ?? null,
57
- errorMessage: latest["error_message"],
58
- bytesWritten: latest["bytes_written"],
52
+ id: latest.id,
53
+ status: latest.status,
54
+ requestedAt: latest.requestedAt.toString(),
55
+ completedAt: latest.completedAt?.toString() ?? null,
56
+ expiresAt: latest.expiresAt?.toString() ?? null,
57
+ errorMessage: latest.errorMessage,
58
+ bytesWritten: latest.bytesWritten,
59
59
  },
60
60
  };
61
61
  },
@@ -595,11 +595,8 @@ async function storageCleanupPass(args: {
595
595
  // → Trade-off zugunsten DSGVO entschieden. Wenn ein Operator forensik
596
596
  // braucht, muss er das vor dem Cleanup-Pass capturen (out-of-band).
597
597
  //
598
- // **SQL-Filter:** WHERE-clause auf downloadStorageKey IS NOT NULL filtert
599
- // bereits in der DB statt im Loop. Bei skalierender DB-Historie (10k+
600
- // done-jobs nach 30 Tagen) reduziert das den Worker-Roundtrip drastisch.
601
- //
602
- // or() + isNotNull(): no bun-db helper covers this combination — raw SQL.
598
+ // **SQL-Filter:** status IN (done, failed) + downloadStorageKey IS NOT NULL
599
+ // via selectMany (db/queries/export-jobs.ts).
603
600
  const candidates = await selectExportJobsForStorageCleanup(
604
601
  db,
605
602
  EXPORT_JOB_STATUS.Done,
@@ -112,7 +112,6 @@ export async function runForgetCleanup(
112
112
  const { db, registry, now, sendDeletionExecutedEmail } = args;
113
113
 
114
114
  // Step 1: Find users with expired grace period.
115
- // lte with Instant: no bun-db operator covers this — raw SQL.
116
115
  const dueUsers = await selectUsersDueForForgetCleanup(
117
116
  db,
118
117
  USER_STATUS.DeletionRequested,
@@ -20,6 +20,7 @@ import {
20
20
  import { createComplianceProfilesFeature } from "../../compliance-profiles";
21
21
  import { createDataRetentionFeature } from "../../data-retention";
22
22
  import { createFilesFeature } from "../../files";
23
+ import { createSessionsFeature } from "../../sessions";
23
24
  import {
24
25
  createUserFeature,
25
26
  USER_ANONYMIZED_DISPLAY_NAME,
@@ -39,6 +40,7 @@ const features = [
39
40
  createFilesFeature(),
40
41
  createDataRetentionFeature(),
41
42
  createComplianceProfilesFeature(),
43
+ createSessionsFeature(),
42
44
  createUserDataRightsFeature(),
43
45
  createUserDataRightsDefaultsFeature(),
44
46
  ];