@cosmicdrift/kumiko-bundled-features 0.349.0 → 0.351.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/dist/audit/handlers/list.query.js +1 -1
- package/dist/auth-email-password/email-templates.js +1 -1
- package/dist/auth-email-password/handlers/invite-create.write.js +1 -1
- package/dist/auth-email-password/handlers/signup-request.write.js +1 -1
- package/dist/auth-email-password/handlers/token-request-handler.d.ts +1 -1
- package/dist/auth-email-password/reset-token.d.ts +1 -1
- package/dist/auth-email-password/unlock-token.d.ts +1 -1
- package/dist/auth-email-password/verification-token.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/enable-confirm.write.js +1 -1
- package/dist/auth-mfa/hmac-token-codec.d.ts +1 -1
- package/dist/auth-mfa/hmac-token-codec.js +1 -1
- package/dist/auth-mfa/mfa-challenge-token.d.ts +1 -1
- package/dist/auth-mfa/mfa-challenge-token.js +1 -1
- package/dist/auth-mfa/mfa-preauth-setup-token.d.ts +1 -1
- package/dist/auth-mfa/mfa-preauth-setup-token.js +1 -1
- package/dist/auth-mfa/mfa-setup-token.d.ts +1 -1
- package/dist/auth-mfa/mfa-setup-token.js +1 -1
- package/dist/billing-foundation/constants.d.ts +2 -2
- package/dist/billing-foundation/constants.js +3 -12
- package/dist/billing-foundation/consumer-protection/confirmation-mail.js +1 -1
- package/dist/billing-foundation/consumer-protection/termination-mail.js +1 -1
- package/dist/billing-foundation/feature.js +2 -9
- package/dist/billing-foundation/handlers/sync-subscription.write.js +3 -6
- package/dist/cap-counter/book-cap-usage.js +1 -1
- package/dist/cap-counter/enforce-cap.d.ts +1 -1
- package/dist/cap-counter/enforce-cap.js +1 -8
- package/dist/channel-email/email-channel.js +13 -5
- package/dist/channel-email/pii-guard.js +6 -1
- package/dist/channel-email/smtp-transport.js +1 -0
- package/dist/channel-email/types.d.ts +1 -0
- package/dist/delivery/handlers/log.query.d.ts +1 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/jobs.js +3 -1
- package/dist/delivery/types.d.ts +3 -0
- package/dist/feature-toggles/handlers/set.write.js +1 -1
- package/dist/form-draft/db/queries/cleanup.d.ts +1 -1
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.d.ts +1 -1
- package/dist/form-draft/lookup.d.ts +1 -1
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +1 -1
- package/dist/inbound-mail-foundation/oauth-access-token.d.ts +1 -1
- package/dist/inbound-mail-foundation/oauth-access-token.js +1 -1
- package/dist/inbound-mail-foundation/oauth-state.d.ts +1 -1
- package/dist/inbound-mail-foundation/oauth-state.js +1 -1
- package/dist/inbound-mail-foundation/watch-supervisor.js +1 -1
- package/dist/inbound-provider-imap/feature.js +1 -1
- package/dist/inbound-provider-imap/imap-client.js +1 -1
- package/dist/jobs/job-instant.d.ts +1 -1
- package/dist/jobs/job-instant.js +1 -1
- package/dist/metrics/compute.d.ts +1 -1
- package/dist/metrics/feature.js +1 -1
- package/dist/metrics/types.d.ts +1 -1
- package/dist/metrics/window.d.ts +1 -1
- package/dist/metrics/window.js +1 -1
- package/dist/personal-access-tokens/expiry.js +1 -1
- package/dist/personal-access-tokens/handlers/create.write.js +1 -1
- package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
- package/dist/personal-access-tokens/revoke-for-user.js +1 -1
- package/dist/renderer-simple/simple-renderer.js +49 -13
- package/dist/sessions/handlers/revoke-all-for-user.write.js +1 -1
- package/dist/sessions/handlers/revoke-all-others.write.js +1 -1
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/session-callbacks.js +1 -1
- package/dist/shared/grace-period.d.ts +2 -1
- package/dist/shared/grace-period.js +3 -7
- package/dist/shared/row-bound-grant.d.ts +1 -1
- package/dist/shared/signed-token.d.ts +1 -1
- package/dist/shared/signed-token.js +1 -1
- package/dist/subscription-mollie/verify-webhook.js +1 -1
- package/dist/subscription-stripe/verify-webhook.js +1 -1
- package/dist/template-resolver/api.d.ts +1 -1
- package/dist/template-resolver/handlers/by-slug.query.d.ts +1 -1
- package/dist/template-resolver/handlers/by-tenant.query.d.ts +2 -2
- package/dist/template-resolver/handlers/collection-item.query.d.ts +1 -1
- package/dist/template-resolver/handlers/collection-list.query.d.ts +1 -1
- package/dist/template-resolver/handlers/collection-shared.d.ts +2 -2
- package/dist/template-resolver/handlers/find-by-id.query.d.ts +1 -1
- package/dist/template-resolver/handlers/list.query.d.ts +1 -1
- package/dist/template-resolver/table.d.ts +1 -1
- package/dist/tenant/handlers/team-list.query.d.ts +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/invited-membership.d.ts +1 -1
- package/dist/tenant/invited-membership.js +1 -1
- package/dist/tenant-handover/grant.d.ts +1 -1
- package/dist/user-data-rights/db/queries/export-jobs.d.ts +1 -1
- package/dist/user-data-rights/db/queries/forget-cleanup.d.ts +2 -2
- package/dist/user-data-rights/db/queries/forget-cleanup.js +2 -8
- package/dist/user-data-rights/deletion-token.d.ts +1 -1
- package/dist/user-data-rights/email-templates.d.ts +1 -0
- package/dist/user-data-rights/email-templates.js +27 -5
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +1 -1
- package/dist/user-data-rights/handlers/my-audit-log.query.js +1 -1
- package/dist/user-data-rights/lib/default-mailers.js +8 -8
- package/dist/waitlist/handlers/invite.write.js +1 -1
- package/dist/waitlist/handlers/submit.write.js +1 -1
- package/package.json +9 -9
- package/src/channel-email/changes.json +6 -0
package/dist/metrics/types.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { EntityTableMeta } from "@cosmicdrift/kumiko-framework/db";
|
|
|
2
2
|
import type { HandlerContext } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import type { AggregateMeasure, AggregateTimeBucket } from "@cosmicdrift/kumiko-types/aggregate-types";
|
|
4
4
|
import type { SchemaTable } from "@cosmicdrift/kumiko-types/schema-table-types";
|
|
5
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
5
6
|
import type { WhereObject } from "@cosmicdrift/kumiko-types/where-clause-types";
|
|
6
|
-
import type { Temporal } from "temporal-polyfill";
|
|
7
7
|
import type { MetricRange, MetricScope } from "./constants.js";
|
|
8
8
|
/** Maps a payload value (e.g. a folder id) to the values `column` may have (e.g. the folder and its subfolders' loan ids). Runs with the tenant handler context, so reads stay tenant-scoped; the result only narrows. An empty result yields no rows. */
|
|
9
9
|
export type MetricFilterResolver = {
|
package/dist/metrics/window.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AggregateTimeBucket } from "@cosmicdrift/kumiko-types/aggregate-types";
|
|
2
|
-
import { Temporal } from "temporal
|
|
2
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
3
|
import type { MetricRange } from "./constants.js";
|
|
4
4
|
import type { MetricDefinition } from "./types.js";
|
|
5
5
|
export type MetricWindow = {
|
package/dist/metrics/window.js
CHANGED
|
@@ -2,7 +2,7 @@ import { insertOne } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
|
2
2
|
import { createSystemUser, defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
5
|
-
import { Temporal } from "temporal
|
|
5
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
6
|
import * as z from "zod";
|
|
7
7
|
import { encryptForDirectWrite, verifyPassword } from "../../shared/index.js";
|
|
8
8
|
import { UserQueries } from "../../user/index.js";
|
|
@@ -2,7 +2,7 @@ import { updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
|
2
2
|
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
5
|
-
import { Temporal } from "temporal
|
|
5
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
6
|
import * as z from "zod";
|
|
7
7
|
import { API_TOKEN_ENTITY_NAME, PatErrors } from "../constants.js";
|
|
8
8
|
import { PAT_REVOKED_AGGREGATE_TYPE, PAT_REVOKED_EVENT_QN } from "../pat-revoked-event.js";
|
|
@@ -2,7 +2,7 @@ import { transaction, updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
|
2
2
|
import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { append } from "@cosmicdrift/kumiko-framework/event-store";
|
|
4
4
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
5
|
-
import { Temporal } from "temporal
|
|
5
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
6
|
import { PAT_REVOKED_AGGREGATE_TYPE, PAT_REVOKED_EVENT_QN, patRevokedSchema, } from "./pat-revoked-event.js";
|
|
7
7
|
import { apiTokenTable } from "./schema/api-token.js";
|
|
8
8
|
// A pool has begin(); a tx/savepoint handle does not and is already atomic.
|
|
@@ -73,25 +73,57 @@ function renderBrandingHeader(branding, primaryColor, logoUrl) {
|
|
|
73
73
|
: `<span style="font-size:18px;font-weight:700;color:${escapeHtmlAttr(primaryColor)}">${escapeHtml(branding.productName ?? "")}</span>`;
|
|
74
74
|
return `<div style="margin:0 0 24px;padding:0 0 16px;border-bottom:3px solid ${escapeHtmlAttr(primaryColor)}">${logo}</div>`;
|
|
75
75
|
}
|
|
76
|
-
function
|
|
77
|
-
if (!branding)
|
|
78
|
-
return "";
|
|
76
|
+
function resolveBrandingFooter(branding, locale) {
|
|
79
77
|
const pick = (value) => resolveLocalized(value, locale, branding.defaultLocale);
|
|
80
78
|
const links = (branding.footerLinks ?? []).flatMap((link) => {
|
|
81
79
|
const url = pick(link.url);
|
|
82
80
|
if (url === undefined || !isHttpUrl(url))
|
|
83
81
|
return [];
|
|
84
|
-
return [
|
|
85
|
-
`<a href="${escapeHtmlAttr(url)}" style="color:#999">${escapeHtml(pick(link.label) ?? "")}</a>`,
|
|
86
|
-
];
|
|
82
|
+
return [{ label: pick(link.label) ?? "", url }];
|
|
87
83
|
});
|
|
88
|
-
|
|
84
|
+
return { footerText: pick(branding.footerText), links };
|
|
85
|
+
}
|
|
86
|
+
function renderBrandingFooter(branding, locale) {
|
|
87
|
+
if (!branding)
|
|
88
|
+
return "";
|
|
89
|
+
const { footerText, links: resolvedLinks } = resolveBrandingFooter(branding, locale);
|
|
90
|
+
const links = resolvedLinks.map((link) => `<a href="${escapeHtmlAttr(link.url)}" style="color:#999">${escapeHtml(link.label)}</a>`);
|
|
89
91
|
const footerPartsHtml = [footerText ? escapeHtml(footerText) : "", links.join(" · ")].filter((part) => part !== "");
|
|
90
92
|
if (footerPartsHtml.length === 0)
|
|
91
93
|
return "";
|
|
92
94
|
const footerHtml = footerPartsHtml.join("<br />");
|
|
93
95
|
return `<p style="margin:16px 0 0;color:#999;font-size:12px">${footerHtml}</p>`;
|
|
94
96
|
}
|
|
97
|
+
function brandingFooterLines(branding, locale) {
|
|
98
|
+
if (!branding)
|
|
99
|
+
return [];
|
|
100
|
+
const { footerText, links } = resolveBrandingFooter(branding, locale);
|
|
101
|
+
return [
|
|
102
|
+
...(footerText ? [footerText] : []),
|
|
103
|
+
...links.map((link) => (link.label ? `${link.label}: ${link.url}` : link.url)),
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
function templateContent(variables) {
|
|
107
|
+
const data = variables; // @cast-boundary render-helper
|
|
108
|
+
// Without structured fields, title + body become the header and a single text section.
|
|
109
|
+
return {
|
|
110
|
+
header: data.header ?? data.title,
|
|
111
|
+
sections: data.sections ?? (data.body ? [{ text: data.body }] : undefined),
|
|
112
|
+
footer: data.footer,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Markdown stays as written: its source is already readable plain text.
|
|
116
|
+
function sectionText(section) {
|
|
117
|
+
if ("text" in section)
|
|
118
|
+
return section.text;
|
|
119
|
+
if ("heading" in section)
|
|
120
|
+
return section.heading;
|
|
121
|
+
if ("markdown" in section)
|
|
122
|
+
return section.markdown;
|
|
123
|
+
if ("button" in section)
|
|
124
|
+
return `${section.button.label}: ${section.button.url}`;
|
|
125
|
+
return "";
|
|
126
|
+
}
|
|
95
127
|
function renderSection(section, primaryColor) {
|
|
96
128
|
if ("text" in section) {
|
|
97
129
|
return `<p style="margin:0 0 16px;color:#333;font-size:14px;line-height:1.5">${escapeHtml(section.text)}</p>`;
|
|
@@ -118,10 +150,7 @@ export function createSimpleRenderer(branding) {
|
|
|
118
150
|
return {
|
|
119
151
|
name: "simple",
|
|
120
152
|
async render(input) {
|
|
121
|
-
const
|
|
122
|
-
// Fallback: if no structured fields, use title + body as header + single text section
|
|
123
|
-
const header = data.header ?? data.title;
|
|
124
|
-
const sections = data.sections ?? (data.body ? [{ text: data.body }] : undefined);
|
|
153
|
+
const { header, sections, footer } = templateContent(input.variables);
|
|
125
154
|
const parts = [];
|
|
126
155
|
parts.push('<!DOCTYPE html><html><body style="margin:0;padding:0;font-family:sans-serif">');
|
|
127
156
|
parts.push('<div style="max-width:600px;margin:0 auto;padding:24px">');
|
|
@@ -134,13 +163,20 @@ export function createSimpleRenderer(branding) {
|
|
|
134
163
|
parts.push(renderSection(section, primaryColor));
|
|
135
164
|
}
|
|
136
165
|
}
|
|
137
|
-
if (
|
|
138
|
-
parts.push(`<p style="margin:24px 0 0;color:#999;font-size:12px;border-top:1px solid #eee;padding-top:16px">${escapeHtml(
|
|
166
|
+
if (footer) {
|
|
167
|
+
parts.push(`<p style="margin:24px 0 0;color:#999;font-size:12px;border-top:1px solid #eee;padding-top:16px">${escapeHtml(footer)}</p>`);
|
|
139
168
|
}
|
|
140
169
|
parts.push(renderBrandingFooter(branding, input.locale));
|
|
141
170
|
parts.push("</div></body></html>");
|
|
142
171
|
return parts.join("");
|
|
143
172
|
},
|
|
173
|
+
async renderText(input) {
|
|
174
|
+
const { header, sections, footer } = templateContent(input.variables);
|
|
175
|
+
const brandingFooter = brandingFooterLines(branding, input.locale).join("\n");
|
|
176
|
+
return [header, ...(sections ?? []).map(sectionText), footer, brandingFooter]
|
|
177
|
+
.filter((block) => block !== undefined && block !== "")
|
|
178
|
+
.join("\n\n");
|
|
179
|
+
},
|
|
144
180
|
};
|
|
145
181
|
}
|
|
146
182
|
export const simpleRenderer = createSimpleRenderer();
|
|
@@ -4,7 +4,7 @@ import { access, defineWriteHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumik
|
|
|
4
4
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
5
|
import { append } from "@cosmicdrift/kumiko-framework/event-store";
|
|
6
6
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
7
|
-
import { Temporal } from "temporal
|
|
7
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
8
8
|
import * as z from "zod";
|
|
9
9
|
import { userSessionTable } from "../schema/user-session.js";
|
|
10
10
|
import { SESSION_REVOKED_AGGREGATE_TYPE, SESSION_REVOKED_EVENT_QN, sessionRevokedSchema, } from "../session-revoked-event.js";
|
|
@@ -2,7 +2,7 @@ import { updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
|
2
2
|
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
5
|
-
import { Temporal } from "temporal
|
|
5
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
6
|
import * as z from "zod";
|
|
7
7
|
import { SessionErrors } from "../constants.js";
|
|
8
8
|
import { userSessionTable } from "../schema/user-session.js";
|
|
@@ -2,7 +2,7 @@ import { fetchOne, updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
|
2
2
|
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
5
|
-
import { Temporal } from "temporal
|
|
5
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
6
|
import * as z from "zod";
|
|
7
7
|
import { SessionErrors, USER_SESSION_ENTITY_NAME } from "../constants.js";
|
|
8
8
|
import { userSessionTable } from "../schema/user-session.js";
|
|
@@ -2,7 +2,7 @@ import { fetchOne, insertOne, transaction, updateMany } from "@cosmicdrift/kumik
|
|
|
2
2
|
import { buildSessionRoles, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { append } from "@cosmicdrift/kumiko-framework/event-store";
|
|
4
4
|
import { generateId, parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
5
|
-
import { Temporal } from "temporal
|
|
5
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
6
|
import { encryptForDirectWrite } from "../shared/index.js";
|
|
7
7
|
import { tenantMembershipsTable } from "../tenant/index.js";
|
|
8
8
|
import { isPrincipalBlocked, userTable } from "../user/index.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/** Shared grace-period check for user-data-rights + tenant-lifecycle cancel flows. */
|
|
2
2
|
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
3
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
4
|
/**
|
|
4
5
|
* True when `gracePeriodEnd` is still in the future.
|
|
5
|
-
* Uses the
|
|
6
|
+
* Uses the module's Temporal so callers don't depend on `globalThis.Temporal`.
|
|
6
7
|
*/
|
|
7
8
|
export declare function isWithinGracePeriod(gracePeriodEnd: Temporal.Instant | null): boolean;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
2
|
/** Shared grace-period check for user-data-rights + tenant-lifecycle cancel flows. */
|
|
3
|
-
import { Temporal
|
|
3
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
4
|
/**
|
|
5
5
|
* True when `gracePeriodEnd` is still in the future.
|
|
6
|
-
* Uses the
|
|
6
|
+
* Uses the module's Temporal so callers don't depend on `globalThis.Temporal`.
|
|
7
7
|
*/
|
|
8
8
|
export function isWithinGracePeriod(gracePeriodEnd) {
|
|
9
|
-
|
|
10
|
-
// at runtime — row types resolve against ambient Temporal; polyfill Instant
|
|
11
|
-
// is a separate nominal type across the two .d.ts sources.
|
|
12
|
-
return (gracePeriodEnd != null &&
|
|
13
|
-
TemporalPolyfill.Instant.compare(gracePeriodEnd, TemporalPolyfill.Now.instant()) > 0);
|
|
9
|
+
return (gracePeriodEnd != null && Temporal.Instant.compare(gracePeriodEnd, Temporal.Now.instant()) > 0);
|
|
14
10
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// Timing-safe comparison on verify so a valid-length forgery can't leak
|
|
13
13
|
// signal through a short-circuit.
|
|
14
14
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
15
|
-
import { Temporal } from "temporal
|
|
15
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
16
16
|
function sign(input, secret) {
|
|
17
17
|
return createHmac("sha256", secret).update(input).digest("base64url");
|
|
18
18
|
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// Created-Event mit subscription-id bekommt.
|
|
16
16
|
import { parseProviderConsentId, SubscriptionEventTypes, SubscriptionStatuses, } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
|
|
17
17
|
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
18
|
-
import { Temporal } from "temporal
|
|
18
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
19
19
|
import { MOLLIE_PROVIDER_NAME } from "./constants.js";
|
|
20
20
|
const log = createFallbackLogger("subscription-mollie");
|
|
21
21
|
export function verifyAndParseMollieWebhook(client, options) {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
import { BillingEventKinds, parseProviderConsentId, SubscriptionEventTypes, SubscriptionStatuses, } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
|
|
35
35
|
import { ExtraRouteRejection } from "@cosmicdrift/kumiko-framework/api";
|
|
36
36
|
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
37
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
37
38
|
import Stripe from "stripe";
|
|
38
|
-
import { Temporal } from "temporal-polyfill";
|
|
39
39
|
import { STRIPE_PROVIDER_NAME, StripeEventTypes } from "./constants.js";
|
|
40
40
|
const log = createFallbackLogger("subscription-stripe");
|
|
41
41
|
export function isResourceMissingStripeError(error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import type { Temporal } from "temporal
|
|
3
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
4
|
import type { ContentFormat, TemplateKind } from "./constants.js";
|
|
5
5
|
export type TemplateResource = {
|
|
6
6
|
readonly id: string;
|
|
@@ -10,5 +10,5 @@ export declare const bySlugQuery: import("@cosmicdrift/kumiko-types/define-handl
|
|
|
10
10
|
content: string | null;
|
|
11
11
|
contentFormat: string;
|
|
12
12
|
folder: string | null;
|
|
13
|
-
modifiedAt:
|
|
13
|
+
modifiedAt: Temporal.Instant | null;
|
|
14
14
|
} | null, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Temporal } from "temporal
|
|
1
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
export type TextBlockSummary = {
|
|
4
4
|
readonly slug: string;
|
|
@@ -17,6 +17,6 @@ export declare const byTenantQuery: import("@cosmicdrift/kumiko-types/define-han
|
|
|
17
17
|
title: string | null;
|
|
18
18
|
content: string | null;
|
|
19
19
|
folder: string | null;
|
|
20
|
-
modifiedAt: Temporal.Instant | null;
|
|
20
|
+
modifiedAt: globalThis.Temporal.Instant | null;
|
|
21
21
|
}[];
|
|
22
22
|
}, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
@@ -11,5 +11,5 @@ export declare function makeCollectionItemQuery(collection: ContentCollectionDef
|
|
|
11
11
|
content: string | null;
|
|
12
12
|
contentFormat: string;
|
|
13
13
|
folder: string | null;
|
|
14
|
-
modifiedAt:
|
|
14
|
+
modifiedAt: Temporal.Instant | null;
|
|
15
15
|
} | null, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
@@ -10,6 +10,6 @@ export declare function makeCollectionListQuery(collection: ContentCollectionDef
|
|
|
10
10
|
content: string | null;
|
|
11
11
|
contentFormat: string;
|
|
12
12
|
folder: string | null;
|
|
13
|
-
modifiedAt:
|
|
13
|
+
modifiedAt: Temporal.Instant | null;
|
|
14
14
|
}[];
|
|
15
15
|
}, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import type { AccessRule, ContentCollectionDefinition, SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import type { Temporal } from "temporal
|
|
3
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
4
|
import { templateResourcesTable } from "../table.js";
|
|
5
5
|
import { userContentEntriesTable } from "../user-content-table.js";
|
|
6
6
|
export declare const DEFAULT_COLLECTION_ACCESS: AccessRule;
|
|
@@ -31,5 +31,5 @@ export declare function toCollectionEntry(row: CollectionEntryRow): {
|
|
|
31
31
|
content: string | null;
|
|
32
32
|
contentFormat: string;
|
|
33
33
|
folder: string | null;
|
|
34
|
-
modifiedAt: Temporal.Instant | null;
|
|
34
|
+
modifiedAt: globalThis.Temporal.Instant | null;
|
|
35
35
|
};
|
|
@@ -15,5 +15,5 @@ export declare const findByIdQuery: import("@cosmicdrift/kumiko-types/define-han
|
|
|
15
15
|
scope: string;
|
|
16
16
|
parentTemplateId: string | null;
|
|
17
17
|
status: string;
|
|
18
|
-
modifiedAt:
|
|
18
|
+
modifiedAt: Temporal.Instant | null;
|
|
19
19
|
} | null, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
@@ -22,5 +22,5 @@ export declare const listQuery: import("@cosmicdrift/kumiko-types/define-handler
|
|
|
22
22
|
scope: string;
|
|
23
23
|
status: string;
|
|
24
24
|
contentFormat: string;
|
|
25
|
-
modifiedAt:
|
|
25
|
+
modifiedAt: Temporal.Instant | null;
|
|
26
26
|
}[], import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
@@ -2,7 +2,7 @@ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
|
2
2
|
import { access, definePagedQueryHandler, MAX_LIST_LIMIT, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
5
|
-
import { Temporal } from "temporal
|
|
5
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
6
|
import * as z from "zod";
|
|
7
7
|
import { userSessionTable } from "../../sessions/index.js";
|
|
8
8
|
import { decryptStoredPii, mapWithConcurrency } from "../../shared/index.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DbRunner } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { type TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import { Temporal } from "temporal
|
|
3
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
4
|
export type InvitedMembershipOptions = {
|
|
5
5
|
readonly userId: string;
|
|
6
6
|
readonly tenantId: TenantId;
|
|
@@ -3,7 +3,7 @@ import { createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-f
|
|
|
3
3
|
import { createSystemUser } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import { ConflictError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
5
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
6
|
-
import { Temporal } from "temporal
|
|
6
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
7
7
|
import { TenantErrors } from "./constants.js";
|
|
8
8
|
import { findForbiddenMembershipRole, reservedMembershipRoleError } from "./membership-roles.js";
|
|
9
9
|
import { tenantMembershipEntity, tenantMembershipsTable } from "./membership-table.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Temporal } from "temporal
|
|
1
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
2
|
export declare function tenantHandoverPurpose(entityType: string): string;
|
|
3
3
|
export declare function signTenantHandoverGrant(args: {
|
|
4
4
|
readonly entityType: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import type { Temporal } from "temporal
|
|
3
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
4
|
export type ExportJobCleanupCandidate = {
|
|
5
5
|
readonly id: string;
|
|
6
6
|
readonly version: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
-
import { Temporal
|
|
3
|
-
export declare function selectUsersDueForForgetCleanup(db: DbConnection, status: string, gracePeriodEndCutoff:
|
|
2
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
|
+
export declare function selectUsersDueForForgetCleanup(db: DbConnection, status: string, gracePeriodEndCutoff: Temporal.Instant | string): Promise<readonly {
|
|
4
4
|
id: string;
|
|
5
5
|
}[]>;
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
|
-
|
|
3
|
-
// `Temporal` TYPE that gracePeriodEndCutoff's parameter type resolves
|
|
4
|
-
// against (same #1438 dual-package-hazard pattern as event-store.ts).
|
|
5
|
-
import { Temporal as TemporalPolyfill } from "temporal-polyfill";
|
|
2
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
6
3
|
import { userTable } from "../../../user/index.js";
|
|
7
4
|
export async function selectUsersDueForForgetCleanup(db, status, gracePeriodEndCutoff) {
|
|
8
|
-
// @cast-boundary temporal-polyfill-vs-ambient: same TC39 Temporal.Instant
|
|
9
|
-
// at runtime, distinct nominal types across the two .d.ts sources (see
|
|
10
|
-
// event-store.ts). Only ever consumed via the `lte` comparison below.
|
|
11
5
|
const cutoff = typeof gracePeriodEndCutoff === "string"
|
|
12
|
-
?
|
|
6
|
+
? Temporal.Instant.from(gracePeriodEndCutoff)
|
|
13
7
|
: gracePeriodEndCutoff;
|
|
14
8
|
return selectMany(db, userTable, {
|
|
15
9
|
status,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Temporal } from "temporal
|
|
1
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
2
|
import { type RowBoundGrantResult } from "../shared/index.js";
|
|
3
3
|
export declare function signDeletionToken(userId: string, requestId: string, ttlMinutes: number, secret: string, now?: Temporal.Instant): {
|
|
4
4
|
readonly token: string;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// branding pass send*Email callbacks and these defaults do not run.
|
|
5
5
|
import { mailT, registerMailTranslations } from "@cosmicdrift/kumiko-framework/i18n";
|
|
6
6
|
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-headless";
|
|
7
|
-
import { Temporal } from "temporal
|
|
7
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
8
8
|
export function normalizeGdprMailLocale(raw) {
|
|
9
9
|
if (!raw)
|
|
10
10
|
return undefined;
|
|
@@ -45,7 +45,13 @@ export function renderExportReadyEmail(args) {
|
|
|
45
45
|
<p style="margin: 0 0 24px;">${renderButton({ url: args.downloadUrl, label: t(locale, "gdpr.mail.exportReady.button") })}</p>
|
|
46
46
|
<p style="margin: 0 0 8px; font-size: 13px; color: #555;">${escapeHtml(t(locale, "gdpr.mail.exportReady.expiry", { when: formatTimestamp(args.expiresAt) }))}</p>
|
|
47
47
|
${renderFallbackUrl({ url: args.downloadUrl, label: t(locale, "gdpr.mail.fallbackUrl") })}`;
|
|
48
|
-
|
|
48
|
+
const text = plainTextBody([
|
|
49
|
+
t(locale, "gdpr.mail.greeting"),
|
|
50
|
+
t(locale, "gdpr.mail.exportReady.intro", { app }),
|
|
51
|
+
`${t(locale, "gdpr.mail.exportReady.button")}: ${args.downloadUrl}`,
|
|
52
|
+
t(locale, "gdpr.mail.exportReady.expiry", { when: formatTimestamp(args.expiresAt) }),
|
|
53
|
+
]);
|
|
54
|
+
return { subject, html: renderShell({ title: subject, bodyHtml: wrapCell(body), locale }), text };
|
|
49
55
|
}
|
|
50
56
|
export function renderExportFailedEmail(args) {
|
|
51
57
|
const locale = args.locale ?? "en";
|
|
@@ -54,7 +60,11 @@ export function renderExportFailedEmail(args) {
|
|
|
54
60
|
const body = `
|
|
55
61
|
<p style="margin: 0 0 16px; font-size: 16px;">${escapeHtml(t(locale, "gdpr.mail.greeting"))}</p>
|
|
56
62
|
<p style="margin: 0; font-size: 14px; line-height: 1.5;">${escapeHtml(t(locale, "gdpr.mail.exportFailed.intro", { app }))}</p>`;
|
|
57
|
-
|
|
63
|
+
const text = plainTextBody([
|
|
64
|
+
t(locale, "gdpr.mail.greeting"),
|
|
65
|
+
t(locale, "gdpr.mail.exportFailed.intro", { app }),
|
|
66
|
+
]);
|
|
67
|
+
return { subject, html: renderShell({ title: subject, bodyHtml: wrapCell(body), locale }), text };
|
|
58
68
|
}
|
|
59
69
|
export function renderDeletionRequestedEmail(args) {
|
|
60
70
|
const locale = args.locale ?? "en";
|
|
@@ -65,7 +75,12 @@ export function renderDeletionRequestedEmail(args) {
|
|
|
65
75
|
<p style="margin: 0 0 16px; font-size: 16px;">${escapeHtml(t(locale, "gdpr.mail.greeting"))}</p>
|
|
66
76
|
<p style="margin: 0 0 16px; font-size: 14px; line-height: 1.5;">${escapeHtml(t(locale, "gdpr.mail.deletionRequested.intro", { app, when }))}</p>
|
|
67
77
|
<p style="margin: 0; font-size: 13px; color: #555;">${escapeHtml(t(locale, "gdpr.mail.deletionRequested.cancel"))}</p>`;
|
|
68
|
-
|
|
78
|
+
const text = plainTextBody([
|
|
79
|
+
t(locale, "gdpr.mail.greeting"),
|
|
80
|
+
t(locale, "gdpr.mail.deletionRequested.intro", { app, when }),
|
|
81
|
+
t(locale, "gdpr.mail.deletionRequested.cancel"),
|
|
82
|
+
]);
|
|
83
|
+
return { subject, html: renderShell({ title: subject, bodyHtml: wrapCell(body), locale }), text };
|
|
69
84
|
}
|
|
70
85
|
export function renderDeletionExecutedEmail(args) {
|
|
71
86
|
const locale = args.locale ?? "en";
|
|
@@ -75,7 +90,14 @@ export function renderDeletionExecutedEmail(args) {
|
|
|
75
90
|
const body = `
|
|
76
91
|
<p style="margin: 0 0 16px; font-size: 16px;">${escapeHtml(t(locale, "gdpr.mail.greeting"))}</p>
|
|
77
92
|
<p style="margin: 0; font-size: 14px; line-height: 1.5;">${escapeHtml(t(locale, "gdpr.mail.deletionExecuted.intro", { app, when }))}</p>`;
|
|
78
|
-
|
|
93
|
+
const text = plainTextBody([
|
|
94
|
+
t(locale, "gdpr.mail.greeting"),
|
|
95
|
+
t(locale, "gdpr.mail.deletionExecuted.intro", { app, when }),
|
|
96
|
+
]);
|
|
97
|
+
return { subject, html: renderShell({ title: subject, bodyHtml: wrapCell(body), locale }), text };
|
|
98
|
+
}
|
|
99
|
+
function plainTextBody(paragraphs) {
|
|
100
|
+
return paragraphs.join("\n\n");
|
|
79
101
|
}
|
|
80
102
|
function wrapCell(bodyHtml) {
|
|
81
103
|
return `<tr><td>${bodyHtml}</td></tr>`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import { Temporal } from "temporal
|
|
3
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
4
|
import * as z from "zod";
|
|
5
5
|
import { downloadAttemptsTable } from "../schema/download-attempt.js";
|
|
6
6
|
// Operator-Query: invalid Download-Attempts (S2.U7).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
4
|
-
import { Temporal } from "temporal
|
|
4
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
5
5
|
import * as z from "zod";
|
|
6
6
|
// DSGVO Art. 15 Selbstauskunft — User reads HIS OWN audit-log.
|
|
7
7
|
// WHERE createdBy = ctx.user.id ist hard-coded (kein userId-Param,
|
|
@@ -29,34 +29,34 @@ function localeFor(userLocale, defaults) {
|
|
|
29
29
|
export function makeDefaultExportReadyEmail(resolveTransport, defaults = {}) {
|
|
30
30
|
return async (args) => {
|
|
31
31
|
const transport = await resolveTransport(args.tenantId);
|
|
32
|
-
const { subject, html } = renderExportReadyEmail({
|
|
32
|
+
const { subject, html, text } = renderExportReadyEmail({
|
|
33
33
|
downloadUrl: args.downloadUrl,
|
|
34
34
|
expiresAt: args.expiresAt,
|
|
35
35
|
locale: localeFor(args.userLocale, defaults),
|
|
36
36
|
appName: defaults.appName,
|
|
37
37
|
});
|
|
38
|
-
await transport.send({ to: args.userEmail, subject, html });
|
|
38
|
+
await transport.send({ to: args.userEmail, subject, html, text });
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
export function makeDefaultExportFailedEmail(resolveTransport, defaults = {}) {
|
|
42
42
|
return async (args) => {
|
|
43
43
|
const transport = await resolveTransport(args.tenantId);
|
|
44
|
-
const { subject, html } = renderExportFailedEmail({
|
|
44
|
+
const { subject, html, text } = renderExportFailedEmail({
|
|
45
45
|
locale: localeFor(args.userLocale, defaults),
|
|
46
46
|
appName: defaults.appName,
|
|
47
47
|
});
|
|
48
|
-
await transport.send({ to: args.userEmail, subject, html });
|
|
48
|
+
await transport.send({ to: args.userEmail, subject, html, text });
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
export function makeDefaultDeletionRequestedEmail(resolveTransport, defaults = {}) {
|
|
52
52
|
return async (args) => {
|
|
53
53
|
const transport = await resolveTransport(args.tenantId);
|
|
54
|
-
const { subject, html } = renderDeletionRequestedEmail({
|
|
54
|
+
const { subject, html, text } = renderDeletionRequestedEmail({
|
|
55
55
|
gracePeriodEnd: args.gracePeriodEnd,
|
|
56
56
|
locale: localeFor(args.userLocale, defaults),
|
|
57
57
|
appName: defaults.appName,
|
|
58
58
|
});
|
|
59
|
-
await transport.send({ to: args.userEmail, subject, html });
|
|
59
|
+
await transport.send({ to: args.userEmail, subject, html, text });
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
export function makeDefaultDeletionExecutedEmail(resolveTransport, defaults = {}) {
|
|
@@ -70,11 +70,11 @@ export function makeDefaultDeletionExecutedEmail(resolveTransport, defaults = {}
|
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
const transport = await resolveTransport(tenantId);
|
|
73
|
-
const { subject, html } = renderDeletionExecutedEmail({
|
|
73
|
+
const { subject, html, text } = renderDeletionExecutedEmail({
|
|
74
74
|
executedAt: args.executedAt,
|
|
75
75
|
locale: localeFor(args.userLocale, defaults),
|
|
76
76
|
appName: defaults.appName,
|
|
77
77
|
});
|
|
78
|
-
await transport.send({ to: args.userEmail, subject, html });
|
|
78
|
+
await transport.send({ to: args.userEmail, subject, html, text });
|
|
79
79
|
};
|
|
80
80
|
}
|