@cosmicdrift/kumiko-bundled-features 0.59.1 → 0.60.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.
Files changed (39) hide show
  1. package/package.json +2 -1
  2. package/src/config/__tests__/app-override-visibility.integration.test.ts +6 -0
  3. package/src/config/__tests__/backing-secrets.integration.test.ts +38 -0
  4. package/src/config/__tests__/inherited-redaction.integration.test.ts +29 -0
  5. package/src/custom-fields/__tests__/feature.test.ts +57 -4
  6. package/src/custom-fields/feature.ts +19 -4
  7. package/src/files-provider-s3/__tests__/s3-provider.test.ts +61 -1
  8. package/src/files-provider-s3/s3-provider.ts +9 -3
  9. package/src/managed-pages/__tests__/managed-pages.integration.test.ts +92 -1
  10. package/src/managed-pages/handlers/set.write.ts +14 -4
  11. package/src/subscription-stripe/__tests__/runtime.test.ts +59 -5
  12. package/src/subscription-stripe/__tests__/stripe-foundation.integration.test.ts +105 -0
  13. package/src/subscription-stripe/feature.ts +2 -1
  14. package/src/tags/__tests__/feature.test.ts +34 -0
  15. package/src/tags/__tests__/tags.integration.test.ts +66 -0
  16. package/src/tags/constants.ts +11 -2
  17. package/src/tags/feature.ts +26 -21
  18. package/src/tags/handlers/assign-tag.write.ts +4 -6
  19. package/src/tags/handlers/create-tag.write.ts +4 -6
  20. package/src/tags/handlers/remove-tag.write.ts +4 -6
  21. package/src/tags/index.ts +1 -0
  22. package/src/tier-engine/__tests__/drift.test.ts +4 -0
  23. package/src/tier-engine/__tests__/resolver.integration.test.ts +30 -0
  24. package/src/tier-engine/__tests__/tier-engine.integration.test.ts +118 -0
  25. package/src/tier-engine/constants.ts +13 -0
  26. package/src/tier-engine/entity.ts +5 -0
  27. package/src/tier-engine/feature.ts +51 -3
  28. package/src/tier-engine/handlers/get-tenant-tier.query.ts +36 -0
  29. package/src/tier-engine/handlers/set-tenant-tier.write.ts +99 -0
  30. package/src/tier-engine/i18n.ts +39 -0
  31. package/src/tier-engine/web/client-plugin.tsx +27 -0
  32. package/src/tier-engine/web/index.ts +8 -0
  33. package/src/tier-engine/web/tier-admin-screen.tsx +161 -0
  34. package/src/user-data-rights/__tests__/anonymous-deletion.integration.test.ts +11 -0
  35. package/src/user-data-rights/deletion-token.ts +9 -3
  36. package/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +22 -3
  37. package/src/user-profile/__tests__/profile-screen.test.tsx +61 -3
  38. package/src/user-profile/i18n.ts +2 -3
  39. package/src/user-profile/web/profile-screen.tsx +29 -5
@@ -37,6 +37,16 @@ function failureKey(error: unknown): string {
37
37
  return typeof key === "string" ? key : "profile.errors.generic";
38
38
  }
39
39
 
40
+ // gracePeriodEnd ist ein roher ISO-Instant ("2026-07-11T00:00:00.000Z"); nur
41
+ // der Datums-Teil ist für den User relevant, die Uhrzeit/Z wäre Rauschen
42
+ // ("…am 2026-07-11T00:00:00.000Z gelöscht"). Reiner String-Slice — kein
43
+ // Date-API (no-date-api-Guard) und universell (RN+Web). Leer/null → "—".
44
+ export function formatDeletionDate(iso: string | null | undefined): string {
45
+ if (!iso) return "—";
46
+ const tIndex = iso.indexOf("T");
47
+ return tIndex > 0 ? iso.slice(0, tIndex) : iso;
48
+ }
49
+
40
50
  function StatusBanner({ status }: { readonly status: SectionStatus }): ReactNode {
41
51
  const t = useTranslation();
42
52
  const { Banner } = usePrimitives();
@@ -160,10 +170,24 @@ function ChangeEmailSection({
160
170
  setStatus({ kind: "error", messageKey: failureKey(res.error) });
161
171
  return;
162
172
  }
163
- // Verification-Mail an die neue Adresse silent-success wie beim
164
- // Login-Resend; ein Fehler hier darf den Email-Wechsel nicht als
165
- // gescheitert anzeigen (der Wechsel ist bereits persistiert).
166
- await requestEmailVerification(newEmail).catch(() => undefined);
173
+ // Verification-Mail an die neue Adresse. Der Wechsel ist bereits
174
+ // persistiert ein Versand-Fehler darf den Erfolg nicht umkehren, wird
175
+ // aber NICHT verschluckt (sonst wartet der User auf eine Mail, die nie
176
+ // kommt). Die Success-Message verspricht entsprechend keinen Versand.
177
+ try {
178
+ const verification = await requestEmailVerification(newEmail);
179
+ if (!verification.ok) {
180
+ // biome-ignore lint/suspicious/noConsole: operator-visibility for verification-send-failure
181
+ console.warn(
182
+ "[user-profile] email changed but the verification email could not be sent to the new address.",
183
+ );
184
+ }
185
+ } catch (err) {
186
+ // biome-ignore lint/suspicious/noConsole: operator-visibility for verification-send-failure
187
+ console.warn(
188
+ `[user-profile] email changed but the verification email send threw: ${err instanceof Error ? err.message : String(err)}`,
189
+ );
190
+ }
167
191
  setNewEmail("");
168
192
  setCurrentPassword("");
169
193
  setStatus({ kind: "success", messageKey: "profile.email.success" });
@@ -260,7 +284,7 @@ function DangerZoneSection({
260
284
  <>
261
285
  <Banner variant="error" testId="profile-danger-requested">
262
286
  {t("profile.danger.requested", {
263
- date: me.gracePeriodEnd ?? "—",
287
+ date: formatDeletionDate(me.gracePeriodEnd),
264
288
  })}
265
289
  </Banner>
266
290
  <StatusBanner status={status} />