@cosmicdrift/kumiko-bundled-features 0.352.0 → 0.354.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/agent-tools/agent-doc-lint.d.ts +2 -0
- package/dist/agent-tools/agent-doc-lint.js +61 -1
- package/dist/agent-tools/agent-manifest.d.ts +1 -0
- package/dist/agent-tools/agent-manifest.js +17 -5
- package/dist/agent-tools/feature.js +7 -2
- package/dist/agent-tools/index.d.ts +1 -1
- package/dist/agent-tools/index.js +1 -1
- package/dist/agent-tools/manifest-deny-qns.d.ts +3 -0
- package/dist/agent-tools/manifest-deny-qns.js +17 -0
- package/dist/agent-tools/tool-catalog.d.ts +2 -1
- package/dist/agent-tools/tool-catalog.js +4 -1
- package/dist/agent-tools/tool-dispatch.js +1 -1
- package/dist/audit/handlers/list.query.js +13 -8
- package/dist/auth-email-password/handlers/change-password.write.js +1 -0
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +2 -2
- package/dist/auth-email-password/handlers/invite-accept.write.js +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +17 -0
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +4 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -0
- package/dist/auth-email-password/handlers/reset-password.write.js +1 -0
- package/dist/auth-email-password/handlers/signup-confirm.write.js +6 -4
- package/dist/auth-email-password/handlers/signup-request.write.js +51 -77
- package/dist/auth-email-password/handlers/token-request-handler.js +1 -0
- package/dist/auth-email-password/handlers/verify-email.write.js +1 -0
- package/dist/auth-email-password/index.d.ts +2 -0
- package/dist/auth-email-password/index.js +2 -0
- package/dist/auth-email-password/seeding.d.ts +2 -0
- package/dist/auth-email-password/seeding.js +30 -8
- package/dist/auth-email-password/signup-activation.d.ts +24 -0
- package/dist/auth-email-password/signup-activation.js +41 -0
- package/dist/auth-email-password/signup-token-store.d.ts +5 -0
- package/dist/auth-email-password/signup-token-store.js +8 -3
- package/dist/auth-email-password/web/auth-gate.d.ts +2 -2
- package/dist/auth-email-password/web/auth-gate.js +5 -5
- package/dist/auth-email-password/web/auth-redirect.d.ts +1 -0
- package/dist/auth-email-password/web/auth-redirect.js +14 -0
- package/dist/auth-email-password/web/login-screen.js +2 -2
- package/dist/auth-email-password/web/user-menu.js +1 -1
- package/dist/auth-mfa/feature.js +5 -0
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -0
- package/dist/auth-mfa/handlers/verify.write.js +1 -0
- package/dist/auth-mfa/schema/user-mfa.d.ts +6 -0
- package/dist/auth-mfa/screens.js +2 -2
- package/dist/auth-mfa/web/mfa-recovery-codes-reveal.js +1 -1
- package/dist/auth-mfa/web/mfa-setup-preauth-screen.d.ts +1 -1
- package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +3 -3
- package/dist/auth-mfa/web/mfa-verify-screen.d.ts +1 -1
- package/dist/auth-mfa/web/mfa-verify-screen.js +1 -1
- package/dist/billing-foundation/billing-info-query.d.ts +5 -2
- package/dist/billing-foundation/checkout-core.d.ts +7 -0
- package/dist/billing-foundation/checkout-core.js +7 -2
- package/dist/billing-foundation/entities.d.ts +8 -0
- package/dist/billing-foundation/handlers/start-plan-checkout.write.js +7 -1
- package/dist/billing-foundation/projection.d.ts +8 -0
- package/dist/cap-counter/entity.d.ts +1 -0
- package/dist/cap-overview/access.js +2 -9
- package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -2
- package/dist/cap-overview/handlers/tenant-options.query.js +4 -5
- package/dist/channel-in-app/in-app-channel.js +1 -1
- package/dist/channel-in-app/tables.js +4 -2
- package/dist/compliance-profiles/schema/profile-selection.d.ts +10 -8
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +2 -4
- package/dist/config/handlers/values.query.d.ts +3 -1
- package/dist/config/handlers/values.query.js +7 -2
- package/dist/config/table.d.ts +6 -0
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -0
- package/dist/crypto-shredding/handlers/forget-subject.write.js +110 -61
- package/dist/custom-fields/entity.d.ts +4 -0
- package/dist/data-retention/schema/tenant-retention-override.d.ts +4 -0
- package/dist/delivery/db/queries/address-opt-outs.d.ts +3 -1
- package/dist/delivery/db/queries/address-opt-outs.js +12 -7
- package/dist/delivery/delivery-service.js +60 -12
- package/dist/delivery/public-names.js +1 -1
- package/dist/delivery/tables.d.ts +6 -0
- package/dist/delivery/unsubscribe.js +66 -14
- package/dist/document-ingest-foundation/entity.d.ts +4 -0
- package/dist/feature-toggles/feature.js +2 -3
- package/dist/feature-toggles/toggle-runtime.d.ts +5 -1
- package/dist/feature-toggles/toggle-runtime.js +30 -6
- package/dist/feature-toggles/toggle-sync-signal.d.ts +3 -2
- package/dist/feature-toggles/toggle-sync-signal.js +29 -10
- package/dist/file-derivatives/handlers/public-variant.query.d.ts +1 -0
- package/dist/file-derivatives/handlers/public-variant.query.js +7 -1
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +5 -0
- package/dist/files-tenant-data/hooks.js +61 -24
- package/dist/folders/entity.d.ts +8 -0
- package/dist/folders/feature.js +2 -10
- package/dist/folders/handlers/delete-folder.write.js +31 -4
- package/dist/form-draft/db/queries/cleanup.d.ts +1 -1
- package/dist/form-draft/db/queries/cleanup.js +4 -3
- package/dist/form-draft/entity.d.ts +2 -0
- package/dist/form-draft/handlers/cleanup.job.d.ts +5 -1
- package/dist/form-draft/handlers/cleanup.job.js +11 -5
- package/dist/foundation-shared/index.d.ts +1 -1
- package/dist/foundation-shared/index.js +1 -1
- package/dist/foundation-shared/mail-host-policy.d.ts +4 -0
- package/dist/foundation-shared/mail-host-policy.js +13 -4
- package/dist/inbound-mail-foundation/entities.d.ts +25 -0
- package/dist/inbound-mail-foundation/projection.d.ts +20 -0
- package/dist/inbound-provider-imap/feature.js +2 -0
- package/dist/inbound-provider-imap/imap-client.js +3 -4
- package/dist/jobs/constants.d.ts +1 -0
- package/dist/jobs/constants.js +1 -0
- package/dist/jobs/db/queries/retention.d.ts +1 -0
- package/dist/jobs/db/queries/retention.js +5 -0
- package/dist/jobs/db/queries/stale-run-sweep.d.ts +2 -0
- package/dist/jobs/db/queries/stale-run-sweep.js +13 -2
- package/dist/jobs/feature.js +7 -1
- package/dist/jobs/handlers/list.query.d.ts +2 -1
- package/dist/jobs/handlers/list.query.js +40 -15
- package/dist/jobs/handlers/tenant-failures.query.js +1 -1
- package/dist/jobs/handlers/tenant-runs.query.d.ts +17 -0
- package/dist/jobs/handlers/tenant-runs.query.js +72 -0
- package/dist/jobs/i18n.js +1 -0
- package/dist/jobs/index.d.ts +2 -0
- package/dist/jobs/index.js +1 -0
- package/dist/jobs/job-run-logger.d.ts +2 -2
- package/dist/jobs/job-run-logger.js +98 -9
- package/dist/jobs/job-run-table.d.ts +6 -0
- package/dist/jobs/tenant-job-failure-table.js +15 -2
- package/dist/jobs/tenant-job-run-table.d.ts +4 -0
- package/dist/jobs/tenant-job-run-table.js +34 -0
- package/dist/ledger/entity.d.ts +24 -8
- package/dist/ledger/entity.js +17 -5
- package/dist/ledger/feature.js +3 -0
- package/dist/ledger/handlers/confirm-schedule-period.write.js +9 -3
- package/dist/ledger/handlers/create-transaction.write.js +1 -0
- package/dist/ledger/handlers/reverse-transaction.write.js +1 -0
- package/dist/ledger/schedule-subject-pair.d.ts +2 -0
- package/dist/ledger/schedule-subject-pair.js +24 -0
- package/dist/ledger/schemas.js +8 -2
- package/dist/mail-transport-smtp/feature.d.ts +3 -4
- package/dist/mail-transport-smtp/feature.js +4 -13
- package/dist/managed-pages/feature.js +28 -10
- package/dist/managed-pages/table.d.ts +12 -0
- package/dist/notes-history/entity.d.ts +12 -0
- package/dist/notes-history/entity.js +4 -0
- package/dist/notes-history/feature.js +2 -10
- package/dist/personal-access-tokens/handlers/create.write.js +1 -0
- package/dist/personal-access-tokens/schema/api-token.d.ts +6 -0
- package/dist/personal-access-tokens/screens.js +14 -3
- package/dist/secrets/table.d.ts +1 -0
- package/dist/seo/feature.js +28 -6
- package/dist/sessions/feature.d.ts +1 -0
- package/dist/sessions/feature.js +9 -8
- package/dist/sessions/handlers/detail.query.d.ts +1 -1
- package/dist/sessions/handlers/detail.query.js +2 -2
- package/dist/sessions/handlers/list.query.d.ts +1 -1
- package/dist/sessions/handlers/list.query.js +5 -3
- package/dist/sessions/schema/user-session.d.ts +4 -0
- package/dist/sessions/screens.d.ts +2 -2
- package/dist/sessions/screens.js +6 -7
- package/dist/shared/assert-no-where-rule-in-ownership-write.d.ts +2 -0
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +18 -0
- package/dist/shared/encrypt-for-direct-write.js +10 -2
- package/dist/shared/index.d.ts +4 -3
- package/dist/shared/index.js +4 -3
- package/dist/shared/parent-visibility.d.ts +2 -1
- package/dist/shared/parent-visibility.js +21 -0
- package/dist/shared/rate-limited-text-response.d.ts +2 -0
- package/dist/shared/rate-limited-text-response.js +9 -0
- package/dist/shared/row-bound-grant.js +16 -2
- package/dist/shared/session-locale-field.d.ts +1 -0
- package/dist/shared/session-locale-field.js +6 -0
- package/dist/tags/entity.d.ts +9 -0
- package/dist/tags/feature.js +2 -10
- package/dist/template-resolver/api.d.ts +2 -2
- package/dist/template-resolver/handlers/list.query.d.ts +2 -0
- package/dist/template-resolver/handlers/list.query.js +2 -2
- package/dist/template-resolver/table.d.ts +48 -30
- package/dist/template-resolver/user-content-table.d.ts +34 -20
- package/dist/tenant/decrypt-tenant-names.d.ts +3 -0
- package/dist/tenant/decrypt-tenant-names.js +10 -0
- package/dist/tenant/feature.js +7 -1
- package/dist/tenant/handlers/me.query.js +5 -1
- package/dist/tenant/handlers/memberships.query.js +3 -2
- package/dist/tenant/handlers/tenant-directory.query.js +9 -3
- package/dist/tenant/handlers/toggle-enabled.write.js +2 -0
- package/dist/tenant/handlers/update-member-roles.write.js +1 -0
- package/dist/tenant/index.d.ts +1 -0
- package/dist/tenant/index.js +1 -0
- package/dist/tenant/invitation-table.d.ts +54 -8
- package/dist/tenant/invitation-table.js +6 -1
- package/dist/tenant/invited-membership.d.ts +8 -6
- package/dist/tenant/invited-membership.js +28 -7
- package/dist/tenant/membership-table.d.ts +4 -0
- package/dist/tenant/schema/tenant.d.ts +18 -10
- package/dist/tenant/schema/tenant.js +4 -6
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +11 -18
- package/dist/tenant-handover/transfer-graph.d.ts +2 -21
- package/dist/tenant-handover/transfer-graph.js +8 -75
- package/dist/tenant-lifecycle/boot-checks.d.ts +1 -0
- package/dist/tenant-lifecycle/boot-checks.js +13 -0
- package/dist/tenant-lifecycle/constants.d.ts +3 -0
- package/dist/tenant-lifecycle/constants.js +5 -0
- package/dist/tenant-lifecycle/events.d.ts +5 -0
- package/dist/tenant-lifecycle/events.js +5 -0
- package/dist/tenant-lifecycle/feature.js +6 -3
- package/dist/tenant-lifecycle/run-tenant-destroy.d.ts +10 -5
- package/dist/tenant-lifecycle/run-tenant-destroy.js +59 -17
- package/dist/tenant-lifecycle/stages.d.ts +8 -1
- package/dist/tenant-lifecycle/stages.js +33 -4
- package/dist/tenant-lifecycle/testing.d.ts +8 -0
- package/dist/tenant-lifecycle/testing.js +42 -0
- package/dist/tier-engine/entity.d.ts +2 -0
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -0
- package/dist/tier-engine/tier-resolver.d.ts +2 -0
- package/dist/user/handlers/detail.query.js +2 -0
- package/dist/user/handlers/list.query.js +6 -2
- package/dist/user/handlers/update.write.js +1 -0
- package/dist/user/schema/user.d.ts +22 -8
- package/dist/user/seeding.d.ts +1 -0
- package/dist/user/seeding.js +20 -0
- package/dist/user-data-rights/boot-checks.js +5 -0
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +1 -0
- package/dist/user-data-rights/index.d.ts +1 -0
- package/dist/user-data-rights/index.js +1 -0
- package/dist/user-data-rights/schema/download-attempt.d.ts +14 -0
- package/dist/user-data-rights/schema/download-attempt.js +17 -9
- package/dist/user-data-rights/schema/download-token.d.ts +8 -0
- package/dist/user-data-rights/schema/export-job.d.ts +16 -8
- package/dist/user-profile/handlers/change-email.write.js +8 -2
- package/dist/waitlist/entity.d.ts +22 -6
- package/dist/workflow-runner/event-trigger.d.ts +1 -0
- package/dist/workflow-runner/event-trigger.js +63 -15
- package/dist/workflow-runner/handlers/resume-run.write.js +8 -2
- package/dist/workflow-runner/runner.d.ts +2 -1
- package/dist/workflow-runner/runner.js +5 -1
- package/package.json +35 -10
- package/src/agent-tools/changes.json +12 -0
- package/src/audit/changes.json +6 -0
- package/src/auth-email-password/changes.json +24 -0
- package/src/auth-mfa/changes.json +7 -0
- package/src/billing-foundation/changes.json +6 -0
- package/src/channel-in-app/changes.json +8 -1
- package/src/crypto-shredding/changes.json +12 -0
- package/src/delivery/changes.json +6 -0
- package/src/files/changes.json +24 -0
- package/src/files-tenant-data/changes.json +5 -0
- package/src/folders/changes.json +6 -0
- package/src/form-draft/changes.json +7 -1
- package/src/inbound-provider-imap/changes.json +6 -0
- package/src/jobs/changes.json +30 -0
- package/src/ledger/changes.json +23 -0
- package/src/managed-pages/changes.json +6 -0
- package/src/notes-history/changes.json +13 -0
- package/src/seo/changes.json +5 -0
- package/src/template-resolver/changes.json +5 -0
- package/src/tenant/changes.json +19 -0
- package/src/tenant-handover/changes.json +12 -0
- package/src/tenant-lifecycle/changes.json +22 -0
- package/src/tier-engine/changes.json +5 -0
- package/src/user/changes.json +15 -0
- package/src/user-data-rights/changes.json +6 -0
- package/src/workflow-runner/changes.json +5 -0
- package/dist/shared/has-where-rule.d.ts +0 -2
- package/dist/shared/has-where-rule.js +0 -10
|
@@ -2,7 +2,7 @@ import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
|
2
2
|
import { access, defineEntityListHandler, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
|
|
4
4
|
// kumiko-lint-ignore cross-feature-import SystemAdmin user-list joins memberships for tenants column
|
|
5
|
-
import { tenantMembershipsTable, tenantTable } from "../../tenant/index.js";
|
|
5
|
+
import { decryptTenantNames, tenantMembershipsTable, tenantTable } from "../../tenant/index.js";
|
|
6
6
|
import { userEntity } from "../schema/user.js";
|
|
7
7
|
const baseList = defineEntityListHandler("user", userEntity, {
|
|
8
8
|
access: { roles: access.systemAdmin },
|
|
@@ -59,7 +59,7 @@ export async function attachTenantLabels(rows, db) {
|
|
|
59
59
|
...new Set(memberships.map((m) => String(m.tenantId ?? "")).filter((id) => id !== "")),
|
|
60
60
|
];
|
|
61
61
|
const tenants = tenantIds.length > 0
|
|
62
|
-
? await selectMany(db, tenantTable, { id: { in: tenantIds } })
|
|
62
|
+
? await decryptTenantNames(await selectMany(db, tenantTable, { id: { in: tenantIds } }), "user:list")
|
|
63
63
|
: [];
|
|
64
64
|
const byUser = labelsByUserId(memberships, tenantLabelById(tenants));
|
|
65
65
|
return rows.map((row) => {
|
|
@@ -90,6 +90,10 @@ export const listQuery = {
|
|
|
90
90
|
return result;
|
|
91
91
|
}
|
|
92
92
|
const envelope = result;
|
|
93
|
+
// Without the tenant feature there are no membership tables to join; with
|
|
94
|
+
// it, a failing lookup must surface instead of rendering a silent empty column.
|
|
95
|
+
if (!ctx.registry.features.has("tenant"))
|
|
96
|
+
return result;
|
|
93
97
|
const rows = await attachTenantLabels(envelope.rows, dbForList(ctx));
|
|
94
98
|
return { ...envelope, rows };
|
|
95
99
|
},
|
|
@@ -49,6 +49,7 @@ export const updateWrite = defineWriteHandler({
|
|
|
49
49
|
},
|
|
50
50
|
},
|
|
51
51
|
description: "Changes a user's display name, locale, timezone, email, verification flag, last active tenant or global roles against the version the caller read; callers may edit themselves, while editing someone else or granting roles needs a privileged actor.",
|
|
52
|
+
agent: { risk: "high" },
|
|
52
53
|
escapeHatch: {
|
|
53
54
|
reason: SYSTEM_ADMIN_DEMOTION_COUNT_REASON,
|
|
54
55
|
},
|
|
@@ -32,6 +32,7 @@ export declare const userEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
32
32
|
readonly type: "text";
|
|
33
33
|
readonly description?: string;
|
|
34
34
|
readonly maxLength?: number;
|
|
35
|
+
readonly minLength?: number;
|
|
35
36
|
readonly required?: boolean;
|
|
36
37
|
readonly searchable?: boolean;
|
|
37
38
|
readonly sortable?: boolean;
|
|
@@ -53,6 +54,7 @@ export declare const userEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
53
54
|
readonly type: "text";
|
|
54
55
|
readonly description?: string;
|
|
55
56
|
readonly maxLength?: number;
|
|
57
|
+
readonly minLength?: number;
|
|
56
58
|
readonly required?: boolean;
|
|
57
59
|
readonly searchable?: boolean;
|
|
58
60
|
readonly sortable?: boolean;
|
|
@@ -74,6 +76,7 @@ export declare const userEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
74
76
|
readonly type: "text";
|
|
75
77
|
readonly description?: string;
|
|
76
78
|
readonly maxLength?: number;
|
|
79
|
+
readonly minLength?: number;
|
|
77
80
|
readonly required?: boolean;
|
|
78
81
|
readonly searchable?: boolean;
|
|
79
82
|
readonly sortable?: boolean;
|
|
@@ -95,6 +98,7 @@ export declare const userEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
95
98
|
readonly type: "text";
|
|
96
99
|
readonly description?: string;
|
|
97
100
|
readonly maxLength?: number;
|
|
101
|
+
readonly minLength?: number;
|
|
98
102
|
readonly required?: boolean;
|
|
99
103
|
readonly searchable?: boolean;
|
|
100
104
|
readonly sortable?: boolean;
|
|
@@ -125,6 +129,7 @@ export declare const userEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
125
129
|
readonly type: "text";
|
|
126
130
|
readonly description?: string;
|
|
127
131
|
readonly maxLength?: number;
|
|
132
|
+
readonly minLength?: number;
|
|
128
133
|
readonly required?: boolean;
|
|
129
134
|
readonly searchable?: boolean;
|
|
130
135
|
readonly sortable?: boolean;
|
|
@@ -158,14 +163,15 @@ export declare const userEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
158
163
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
159
164
|
readonly display?: "radio" | "dropdown";
|
|
160
165
|
readonly optionTones?: {
|
|
161
|
-
readonly active?:
|
|
162
|
-
readonly deleted?:
|
|
163
|
-
readonly deletionRequested?:
|
|
164
|
-
readonly restricted?:
|
|
166
|
+
readonly active?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
167
|
+
readonly deleted?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
168
|
+
readonly deletionRequested?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
169
|
+
readonly restricted?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
165
170
|
} | undefined;
|
|
166
171
|
readonly optionsQuery?: string;
|
|
167
172
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
168
173
|
readonly optionsAvailabilityQuery?: string;
|
|
174
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"active" | "deleted" | "deletionRequested" | "restricted">[] | undefined;
|
|
169
175
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
170
176
|
required: true;
|
|
171
177
|
};
|
|
@@ -188,6 +194,7 @@ export declare const userEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
188
194
|
readonly type: "text";
|
|
189
195
|
readonly description?: string;
|
|
190
196
|
readonly maxLength?: number;
|
|
197
|
+
readonly minLength?: number;
|
|
191
198
|
readonly required?: boolean;
|
|
192
199
|
readonly searchable?: boolean;
|
|
193
200
|
readonly sortable?: boolean;
|
|
@@ -211,6 +218,7 @@ export declare const userTable: import("@cosmicdrift/kumiko-framework/db").Entit
|
|
|
211
218
|
readonly type: "text";
|
|
212
219
|
readonly description?: string;
|
|
213
220
|
readonly maxLength?: number;
|
|
221
|
+
readonly minLength?: number;
|
|
214
222
|
readonly required?: boolean;
|
|
215
223
|
readonly searchable?: boolean;
|
|
216
224
|
readonly sortable?: boolean;
|
|
@@ -232,6 +240,7 @@ export declare const userTable: import("@cosmicdrift/kumiko-framework/db").Entit
|
|
|
232
240
|
readonly type: "text";
|
|
233
241
|
readonly description?: string;
|
|
234
242
|
readonly maxLength?: number;
|
|
243
|
+
readonly minLength?: number;
|
|
235
244
|
readonly required?: boolean;
|
|
236
245
|
readonly searchable?: boolean;
|
|
237
246
|
readonly sortable?: boolean;
|
|
@@ -253,6 +262,7 @@ export declare const userTable: import("@cosmicdrift/kumiko-framework/db").Entit
|
|
|
253
262
|
readonly type: "text";
|
|
254
263
|
readonly description?: string;
|
|
255
264
|
readonly maxLength?: number;
|
|
265
|
+
readonly minLength?: number;
|
|
256
266
|
readonly required?: boolean;
|
|
257
267
|
readonly searchable?: boolean;
|
|
258
268
|
readonly sortable?: boolean;
|
|
@@ -274,6 +284,7 @@ export declare const userTable: import("@cosmicdrift/kumiko-framework/db").Entit
|
|
|
274
284
|
readonly type: "text";
|
|
275
285
|
readonly description?: string;
|
|
276
286
|
readonly maxLength?: number;
|
|
287
|
+
readonly minLength?: number;
|
|
277
288
|
readonly required?: boolean;
|
|
278
289
|
readonly searchable?: boolean;
|
|
279
290
|
readonly sortable?: boolean;
|
|
@@ -304,6 +315,7 @@ export declare const userTable: import("@cosmicdrift/kumiko-framework/db").Entit
|
|
|
304
315
|
readonly type: "text";
|
|
305
316
|
readonly description?: string;
|
|
306
317
|
readonly maxLength?: number;
|
|
318
|
+
readonly minLength?: number;
|
|
307
319
|
readonly required?: boolean;
|
|
308
320
|
readonly searchable?: boolean;
|
|
309
321
|
readonly sortable?: boolean;
|
|
@@ -337,14 +349,15 @@ export declare const userTable: import("@cosmicdrift/kumiko-framework/db").Entit
|
|
|
337
349
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
338
350
|
readonly display?: "radio" | "dropdown";
|
|
339
351
|
readonly optionTones?: {
|
|
340
|
-
readonly active?:
|
|
341
|
-
readonly deleted?:
|
|
342
|
-
readonly deletionRequested?:
|
|
343
|
-
readonly restricted?:
|
|
352
|
+
readonly active?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
353
|
+
readonly deleted?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
354
|
+
readonly deletionRequested?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
355
|
+
readonly restricted?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
344
356
|
} | undefined;
|
|
345
357
|
readonly optionsQuery?: string;
|
|
346
358
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
347
359
|
readonly optionsAvailabilityQuery?: string;
|
|
360
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"active" | "deleted" | "deletionRequested" | "restricted">[] | undefined;
|
|
348
361
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
349
362
|
required: true;
|
|
350
363
|
};
|
|
@@ -367,6 +380,7 @@ export declare const userTable: import("@cosmicdrift/kumiko-framework/db").Entit
|
|
|
367
380
|
readonly type: "text";
|
|
368
381
|
readonly description?: string;
|
|
369
382
|
readonly maxLength?: number;
|
|
383
|
+
readonly minLength?: number;
|
|
370
384
|
readonly required?: boolean;
|
|
371
385
|
readonly searchable?: boolean;
|
|
372
386
|
readonly sortable?: boolean;
|
package/dist/user/seeding.d.ts
CHANGED
|
@@ -31,3 +31,4 @@ export declare function seedUser(db: DbConnection, options: SeedUserOptions, hoo
|
|
|
31
31
|
id: string;
|
|
32
32
|
}>;
|
|
33
33
|
export declare function reconcileSeededUserEmailVerified(db: DbConnection, existingRow: Record<string, unknown>, by: SessionUser): Promise<void>;
|
|
34
|
+
export declare function rewriteSeededUserEmail(db: DbConnection, existingRow: Record<string, unknown>, email: string, by: SessionUser): Promise<void>;
|
package/dist/user/seeding.js
CHANGED
|
@@ -73,6 +73,26 @@ export async function reconcileSeededUserEmailVerified(db, existingRow, by) {
|
|
|
73
73
|
throw new Error(`reconcileSeededUserEmailVerified failed: ${result.error.code} — ${JSON.stringify(result.error.details ?? {})}`);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
// Re-writes `email` through the executor so the PII write pipeline recomputes
|
|
77
|
+
// `email_bidx`. Repairs rows whose blind index is NULL or stale (written before
|
|
78
|
+
// the key existed, key rotated, subject-key erased), which would otherwise stay
|
|
79
|
+
// invisible to every `fetchOne(userTable, { email })` lookup.
|
|
80
|
+
export async function rewriteSeededUserEmail(db, existingRow, email, by) {
|
|
81
|
+
const id = existingRow["id"];
|
|
82
|
+
if (typeof id !== "string") {
|
|
83
|
+
throw new Error("rewriteSeededUserEmail: existing user row has no string id");
|
|
84
|
+
}
|
|
85
|
+
const tdb = createTenantDb(db, by.tenantId, "system");
|
|
86
|
+
const result = await userExecutor.update({ id, version: existingRow["version"], changes: { email } }, by, tdb);
|
|
87
|
+
// version_conflict: a concurrent write already changed the row — fine for a seed helper.
|
|
88
|
+
// unique_violation: a duplicate row already holds the blind index; the repair
|
|
89
|
+
// has to wait for a manual duplicate cleanup.
|
|
90
|
+
if (!result.isSuccess &&
|
|
91
|
+
result.error.code !== "version_conflict" &&
|
|
92
|
+
result.error.code !== "unique_violation") {
|
|
93
|
+
throw new Error(`rewriteSeededUserEmail failed: ${result.error.code} — ${JSON.stringify(result.error.details ?? {})}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
76
96
|
// Extrahiert die `id`-Spalte aus dem executor.create-Result. Der
|
|
77
97
|
// Executor liefert ein Record<string, unknown> (die Projection-Row), in
|
|
78
98
|
// das die DB die Aggregat-id reinschreibt — wir prüfen runtime statt
|
|
@@ -20,6 +20,11 @@ export function validateGdprHookCompleteness(features) {
|
|
|
20
20
|
continue;
|
|
21
21
|
const hasExport = typeof usage.options?.["export"] === "function";
|
|
22
22
|
const hasDelete = typeof usage.options?.["delete"] === "function";
|
|
23
|
+
// The compile-time "at least one hook" type is bypassed by string-typed
|
|
24
|
+
// extension names and casts; without this an empty bag registers nothing.
|
|
25
|
+
if (!hasExport && !hasDelete) {
|
|
26
|
+
throw new Error(`[kumiko:boot] Feature "${feature.name}" registers EXT_USER_DATA for entity "${usage.entityName}" with neither an export nor a delete hook — the entity silently stays out of the Art.15/17/20 pipeline. Register at least one hook.`);
|
|
27
|
+
}
|
|
23
28
|
if (hasExport && !hasDelete) {
|
|
24
29
|
throw new Error(`[kumiko:boot] Feature "${feature.name}" exports entity "${usage.entityName}" via EXT_USER_DATA but registers no delete hook — data is included in Art.20 exports but never erased on forget (Art.17 violation). Add a delete hook. If erasure is intentionally handled elsewhere (e.g. crypto-shredding key-erase, parent cascade), register a no-op delete: async () => {} with a comment explaining why.`);
|
|
25
30
|
}
|
|
@@ -28,7 +28,7 @@ async function readPendingDeletionRequestId(ctx, userId) {
|
|
|
28
28
|
}
|
|
29
29
|
// Anonymous apex flow step 2: verify-link target. Verifies the HMAC token,
|
|
30
30
|
// extracts the userId, and flips the grace period through the shared logic —
|
|
31
|
-
// in ONE atomic step with the anchor spend
|
|
31
|
+
// in ONE atomic step with the anchor spend: commitDeletion carries
|
|
32
32
|
// the actual grace-period transition, so a crash after the spend can no
|
|
33
33
|
// longer lose the write step.
|
|
34
34
|
//
|
|
@@ -38,7 +38,7 @@ async function readPendingDeletionRequestId(ctx, userId) {
|
|
|
38
38
|
// a cancel-deletion (status → Active, pendingDeletionRequestId → null), a
|
|
39
39
|
// replayed token fails against the nulled/renewed requestId — no re-arm.
|
|
40
40
|
//
|
|
41
|
-
// Concurrency
|
|
41
|
+
// Concurrency: two simultaneous confirms of the same token both read
|
|
42
42
|
// the same requestId and both verify the HMAC — commitDeletion spends the
|
|
43
43
|
// anchor AND writes the transition atomically (expect: status===Active &&
|
|
44
44
|
// pendingDeletionRequestId===requestId), so exactly one wins. The loser gets
|
|
@@ -21,6 +21,7 @@ export function createRequestDeletionHandler(opts = {}) {
|
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
escapeHatch: {
|
|
24
|
+
grants: ["systemIdentity", "unsafeRaw"],
|
|
24
25
|
reason: "resolveGracePeriod reads the tenant compliance profile via ctx.queryAs(SYSTEM, " +
|
|
25
26
|
"...) to compute the grace period end — the calling user's own identity has no read " +
|
|
26
27
|
"access to that tenant-config projection. startDeletionGracePeriod also appends the " +
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { TENANT_MODEL_CONFIG_KEY } from "./constants.js";
|
|
1
2
|
export { createUserDataRightsFeature, type UserDataRightsOptions } from "./feature.js";
|
|
2
3
|
export type { SendDeletionVerificationEmailFn } from "./handlers/request-deletion-by-email.write.js";
|
|
3
4
|
export { denyIfTargetOutsideAdminTenant, TARGET_USER_NOT_IN_ADMIN_TENANT, } from "./lib/deny-if-target-outside-admin-tenant.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { TENANT_MODEL_CONFIG_KEY } from "./constants.js";
|
|
1
2
|
export { createUserDataRightsFeature } from "./feature.js";
|
|
2
3
|
export { denyIfTargetOutsideAdminTenant, TARGET_USER_NOT_IN_ADMIN_TENANT, } from "./lib/deny-if-target-outside-admin-tenant.js";
|
|
3
4
|
export { isSystemAdminActor } from "./lib/is-admin-actor.js";
|
|
@@ -3,6 +3,7 @@ export declare const downloadAttemptEntity: import("@cosmicdrift/kumiko-types/fi
|
|
|
3
3
|
readonly type: "text";
|
|
4
4
|
readonly description?: string;
|
|
5
5
|
readonly maxLength?: number;
|
|
6
|
+
readonly minLength?: number;
|
|
6
7
|
readonly required?: boolean;
|
|
7
8
|
readonly searchable?: boolean;
|
|
8
9
|
readonly sortable?: boolean;
|
|
@@ -24,6 +25,7 @@ export declare const downloadAttemptEntity: import("@cosmicdrift/kumiko-types/fi
|
|
|
24
25
|
readonly type: "text";
|
|
25
26
|
readonly description?: string;
|
|
26
27
|
readonly maxLength?: number;
|
|
28
|
+
readonly minLength?: number;
|
|
27
29
|
readonly required?: boolean;
|
|
28
30
|
readonly searchable?: boolean;
|
|
29
31
|
readonly sortable?: boolean;
|
|
@@ -45,6 +47,7 @@ export declare const downloadAttemptEntity: import("@cosmicdrift/kumiko-types/fi
|
|
|
45
47
|
readonly type: "text";
|
|
46
48
|
readonly description?: string;
|
|
47
49
|
readonly maxLength?: number;
|
|
50
|
+
readonly minLength?: number;
|
|
48
51
|
readonly required?: boolean;
|
|
49
52
|
readonly searchable?: boolean;
|
|
50
53
|
readonly sortable?: boolean;
|
|
@@ -66,6 +69,7 @@ export declare const downloadAttemptEntity: import("@cosmicdrift/kumiko-types/fi
|
|
|
66
69
|
readonly type: "text";
|
|
67
70
|
readonly description?: string;
|
|
68
71
|
readonly maxLength?: number;
|
|
72
|
+
readonly minLength?: number;
|
|
69
73
|
readonly required?: boolean;
|
|
70
74
|
readonly searchable?: boolean;
|
|
71
75
|
readonly sortable?: boolean;
|
|
@@ -87,6 +91,7 @@ export declare const downloadAttemptEntity: import("@cosmicdrift/kumiko-types/fi
|
|
|
87
91
|
readonly type: "text";
|
|
88
92
|
readonly description?: string;
|
|
89
93
|
readonly maxLength?: number;
|
|
94
|
+
readonly minLength?: number;
|
|
90
95
|
readonly required?: boolean;
|
|
91
96
|
readonly searchable?: boolean;
|
|
92
97
|
readonly sortable?: boolean;
|
|
@@ -108,6 +113,7 @@ export declare const downloadAttemptEntity: import("@cosmicdrift/kumiko-types/fi
|
|
|
108
113
|
readonly type: "text";
|
|
109
114
|
readonly description?: string;
|
|
110
115
|
readonly maxLength?: number;
|
|
116
|
+
readonly minLength?: number;
|
|
111
117
|
readonly required?: boolean;
|
|
112
118
|
readonly searchable?: boolean;
|
|
113
119
|
readonly sortable?: boolean;
|
|
@@ -129,6 +135,7 @@ export declare const downloadAttemptEntity: import("@cosmicdrift/kumiko-types/fi
|
|
|
129
135
|
readonly type: "text";
|
|
130
136
|
readonly description?: string;
|
|
131
137
|
readonly maxLength?: number;
|
|
138
|
+
readonly minLength?: number;
|
|
132
139
|
readonly required?: boolean;
|
|
133
140
|
readonly searchable?: boolean;
|
|
134
141
|
readonly sortable?: boolean;
|
|
@@ -167,6 +174,7 @@ export declare const downloadAttemptsTable: import("@cosmicdrift/kumiko-framewor
|
|
|
167
174
|
readonly type: "text";
|
|
168
175
|
readonly description?: string;
|
|
169
176
|
readonly maxLength?: number;
|
|
177
|
+
readonly minLength?: number;
|
|
170
178
|
readonly required?: boolean;
|
|
171
179
|
readonly searchable?: boolean;
|
|
172
180
|
readonly sortable?: boolean;
|
|
@@ -188,6 +196,7 @@ export declare const downloadAttemptsTable: import("@cosmicdrift/kumiko-framewor
|
|
|
188
196
|
readonly type: "text";
|
|
189
197
|
readonly description?: string;
|
|
190
198
|
readonly maxLength?: number;
|
|
199
|
+
readonly minLength?: number;
|
|
191
200
|
readonly required?: boolean;
|
|
192
201
|
readonly searchable?: boolean;
|
|
193
202
|
readonly sortable?: boolean;
|
|
@@ -209,6 +218,7 @@ export declare const downloadAttemptsTable: import("@cosmicdrift/kumiko-framewor
|
|
|
209
218
|
readonly type: "text";
|
|
210
219
|
readonly description?: string;
|
|
211
220
|
readonly maxLength?: number;
|
|
221
|
+
readonly minLength?: number;
|
|
212
222
|
readonly required?: boolean;
|
|
213
223
|
readonly searchable?: boolean;
|
|
214
224
|
readonly sortable?: boolean;
|
|
@@ -230,6 +240,7 @@ export declare const downloadAttemptsTable: import("@cosmicdrift/kumiko-framewor
|
|
|
230
240
|
readonly type: "text";
|
|
231
241
|
readonly description?: string;
|
|
232
242
|
readonly maxLength?: number;
|
|
243
|
+
readonly minLength?: number;
|
|
233
244
|
readonly required?: boolean;
|
|
234
245
|
readonly searchable?: boolean;
|
|
235
246
|
readonly sortable?: boolean;
|
|
@@ -251,6 +262,7 @@ export declare const downloadAttemptsTable: import("@cosmicdrift/kumiko-framewor
|
|
|
251
262
|
readonly type: "text";
|
|
252
263
|
readonly description?: string;
|
|
253
264
|
readonly maxLength?: number;
|
|
265
|
+
readonly minLength?: number;
|
|
254
266
|
readonly required?: boolean;
|
|
255
267
|
readonly searchable?: boolean;
|
|
256
268
|
readonly sortable?: boolean;
|
|
@@ -272,6 +284,7 @@ export declare const downloadAttemptsTable: import("@cosmicdrift/kumiko-framewor
|
|
|
272
284
|
readonly type: "text";
|
|
273
285
|
readonly description?: string;
|
|
274
286
|
readonly maxLength?: number;
|
|
287
|
+
readonly minLength?: number;
|
|
275
288
|
readonly required?: boolean;
|
|
276
289
|
readonly searchable?: boolean;
|
|
277
290
|
readonly sortable?: boolean;
|
|
@@ -293,6 +306,7 @@ export declare const downloadAttemptsTable: import("@cosmicdrift/kumiko-framewor
|
|
|
293
306
|
readonly type: "text";
|
|
294
307
|
readonly description?: string;
|
|
295
308
|
readonly maxLength?: number;
|
|
309
|
+
readonly minLength?: number;
|
|
296
310
|
readonly required?: boolean;
|
|
297
311
|
readonly searchable?: boolean;
|
|
298
312
|
readonly sortable?: boolean;
|
|
@@ -29,16 +29,24 @@ export const downloadAttemptEntity = createEntity({
|
|
|
29
29
|
jobId: createTextField({ personal: false, reason: "technical_reference" }),
|
|
30
30
|
// User-ID wenn auth-Pfad (job). NULL bei anonymous (token-Pfad).
|
|
31
31
|
attemptedByUserId: createTextField({ personal: false, reason: "pseudonymous_fk" }),
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
// is null-by-design for the anonymous token path, so a subject annotation
|
|
37
|
-
// (`personal: { of: "attemptedByUserId" }`) would throw
|
|
38
|
-
// SubjectResolutionError on every such row once a KMS is configured
|
|
32
|
+
// No subject annotation on this buildEntityTable-managed entity:
|
|
33
|
+
// attemptedByUserId is null-by-design for the anonymous token path, so
|
|
34
|
+
// `personal: { of: "attemptedByUserId" }` would throw SubjectResolutionError
|
|
35
|
+
// on every such row once a KMS is configured
|
|
39
36
|
// (crypto/subject-resolver.ts resolveUserOwnedSubject).
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
// The job path knows the requester and an IP is personal data, so this is a
|
|
38
|
+
// deliberate waiver, not business data: a user forget does not shred these
|
|
39
|
+
// values, the 90d hardDelete below is what removes them.
|
|
40
|
+
ip: createTextField({
|
|
41
|
+
maxLength: 64,
|
|
42
|
+
personal: false,
|
|
43
|
+
reason: "security_audit_retention_bounded",
|
|
44
|
+
}),
|
|
45
|
+
userAgent: createTextField({
|
|
46
|
+
maxLength: 256,
|
|
47
|
+
personal: false,
|
|
48
|
+
reason: "security_audit_retention_bounded",
|
|
49
|
+
}),
|
|
42
50
|
attemptedAt: createTimestampField({ required: true }),
|
|
43
51
|
},
|
|
44
52
|
// 90d hardDelete: unbounded growth = disk-bomb genau gegen das System
|
|
@@ -3,6 +3,7 @@ export declare const exportDownloadTokenEntity: import("@cosmicdrift/kumiko-type
|
|
|
3
3
|
readonly type: "text";
|
|
4
4
|
readonly description?: string;
|
|
5
5
|
readonly maxLength?: number;
|
|
6
|
+
readonly minLength?: number;
|
|
6
7
|
readonly required?: boolean;
|
|
7
8
|
readonly searchable?: boolean;
|
|
8
9
|
readonly sortable?: boolean;
|
|
@@ -24,6 +25,7 @@ export declare const exportDownloadTokenEntity: import("@cosmicdrift/kumiko-type
|
|
|
24
25
|
readonly type: "text";
|
|
25
26
|
readonly description?: string;
|
|
26
27
|
readonly maxLength?: number;
|
|
28
|
+
readonly minLength?: number;
|
|
27
29
|
readonly required?: boolean;
|
|
28
30
|
readonly searchable?: boolean;
|
|
29
31
|
readonly sortable?: boolean;
|
|
@@ -102,6 +104,7 @@ export declare const exportDownloadTokenEntity: import("@cosmicdrift/kumiko-type
|
|
|
102
104
|
readonly type: "text";
|
|
103
105
|
readonly description?: string;
|
|
104
106
|
readonly maxLength?: number;
|
|
107
|
+
readonly minLength?: number;
|
|
105
108
|
readonly required?: boolean;
|
|
106
109
|
readonly searchable?: boolean;
|
|
107
110
|
readonly sortable?: boolean;
|
|
@@ -123,6 +126,7 @@ export declare const exportDownloadTokenEntity: import("@cosmicdrift/kumiko-type
|
|
|
123
126
|
readonly type: "text";
|
|
124
127
|
readonly description?: string;
|
|
125
128
|
readonly maxLength?: number;
|
|
129
|
+
readonly minLength?: number;
|
|
126
130
|
readonly required?: boolean;
|
|
127
131
|
readonly searchable?: boolean;
|
|
128
132
|
readonly sortable?: boolean;
|
|
@@ -146,6 +150,7 @@ export declare const exportDownloadTokensTable: import("@cosmicdrift/kumiko-fram
|
|
|
146
150
|
readonly type: "text";
|
|
147
151
|
readonly description?: string;
|
|
148
152
|
readonly maxLength?: number;
|
|
153
|
+
readonly minLength?: number;
|
|
149
154
|
readonly required?: boolean;
|
|
150
155
|
readonly searchable?: boolean;
|
|
151
156
|
readonly sortable?: boolean;
|
|
@@ -167,6 +172,7 @@ export declare const exportDownloadTokensTable: import("@cosmicdrift/kumiko-fram
|
|
|
167
172
|
readonly type: "text";
|
|
168
173
|
readonly description?: string;
|
|
169
174
|
readonly maxLength?: number;
|
|
175
|
+
readonly minLength?: number;
|
|
170
176
|
readonly required?: boolean;
|
|
171
177
|
readonly searchable?: boolean;
|
|
172
178
|
readonly sortable?: boolean;
|
|
@@ -245,6 +251,7 @@ export declare const exportDownloadTokensTable: import("@cosmicdrift/kumiko-fram
|
|
|
245
251
|
readonly type: "text";
|
|
246
252
|
readonly description?: string;
|
|
247
253
|
readonly maxLength?: number;
|
|
254
|
+
readonly minLength?: number;
|
|
248
255
|
readonly required?: boolean;
|
|
249
256
|
readonly searchable?: boolean;
|
|
250
257
|
readonly sortable?: boolean;
|
|
@@ -266,6 +273,7 @@ export declare const exportDownloadTokensTable: import("@cosmicdrift/kumiko-fram
|
|
|
266
273
|
readonly type: "text";
|
|
267
274
|
readonly description?: string;
|
|
268
275
|
readonly maxLength?: number;
|
|
276
|
+
readonly minLength?: number;
|
|
269
277
|
readonly required?: boolean;
|
|
270
278
|
readonly searchable?: boolean;
|
|
271
279
|
readonly sortable?: boolean;
|
|
@@ -17,6 +17,7 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
|
|
|
17
17
|
readonly type: "text";
|
|
18
18
|
readonly description?: string;
|
|
19
19
|
readonly maxLength?: number;
|
|
20
|
+
readonly minLength?: number;
|
|
20
21
|
readonly required?: boolean;
|
|
21
22
|
readonly searchable?: boolean;
|
|
22
23
|
readonly sortable?: boolean;
|
|
@@ -38,6 +39,7 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
|
|
|
38
39
|
readonly type: "text";
|
|
39
40
|
readonly description?: string;
|
|
40
41
|
readonly maxLength?: number;
|
|
42
|
+
readonly minLength?: number;
|
|
41
43
|
readonly required?: boolean;
|
|
42
44
|
readonly searchable?: boolean;
|
|
43
45
|
readonly sortable?: boolean;
|
|
@@ -67,14 +69,15 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
|
|
|
67
69
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
68
70
|
readonly display?: "radio" | "dropdown";
|
|
69
71
|
readonly optionTones?: {
|
|
70
|
-
readonly done?:
|
|
71
|
-
readonly failed?:
|
|
72
|
-
readonly pending?:
|
|
73
|
-
readonly running?:
|
|
72
|
+
readonly done?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
73
|
+
readonly failed?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
74
|
+
readonly pending?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
75
|
+
readonly running?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
74
76
|
} | undefined;
|
|
75
77
|
readonly optionsQuery?: string;
|
|
76
78
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
77
79
|
readonly optionsAvailabilityQuery?: string;
|
|
80
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"done" | "failed" | "pending" | "running">[] | undefined;
|
|
78
81
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
79
82
|
required: true;
|
|
80
83
|
};
|
|
@@ -127,6 +130,7 @@ export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields")
|
|
|
127
130
|
readonly type: "text";
|
|
128
131
|
readonly description?: string;
|
|
129
132
|
readonly maxLength?: number;
|
|
133
|
+
readonly minLength?: number;
|
|
130
134
|
readonly required?: boolean;
|
|
131
135
|
readonly searchable?: boolean;
|
|
132
136
|
readonly sortable?: boolean;
|
|
@@ -193,6 +197,7 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
|
|
|
193
197
|
readonly type: "text";
|
|
194
198
|
readonly description?: string;
|
|
195
199
|
readonly maxLength?: number;
|
|
200
|
+
readonly minLength?: number;
|
|
196
201
|
readonly required?: boolean;
|
|
197
202
|
readonly searchable?: boolean;
|
|
198
203
|
readonly sortable?: boolean;
|
|
@@ -214,6 +219,7 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
|
|
|
214
219
|
readonly type: "text";
|
|
215
220
|
readonly description?: string;
|
|
216
221
|
readonly maxLength?: number;
|
|
222
|
+
readonly minLength?: number;
|
|
217
223
|
readonly required?: boolean;
|
|
218
224
|
readonly searchable?: boolean;
|
|
219
225
|
readonly sortable?: boolean;
|
|
@@ -243,14 +249,15 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
|
|
|
243
249
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
244
250
|
readonly display?: "radio" | "dropdown";
|
|
245
251
|
readonly optionTones?: {
|
|
246
|
-
readonly done?:
|
|
247
|
-
readonly failed?:
|
|
248
|
-
readonly pending?:
|
|
249
|
-
readonly running?:
|
|
252
|
+
readonly done?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
253
|
+
readonly failed?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
254
|
+
readonly pending?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
255
|
+
readonly running?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
250
256
|
} | undefined;
|
|
251
257
|
readonly optionsQuery?: string;
|
|
252
258
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
253
259
|
readonly optionsAvailabilityQuery?: string;
|
|
260
|
+
readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"done" | "failed" | "pending" | "running">[] | undefined;
|
|
254
261
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
255
262
|
required: true;
|
|
256
263
|
};
|
|
@@ -303,6 +310,7 @@ export declare const exportJobsTable: import("@cosmicdrift/kumiko-framework/db")
|
|
|
303
310
|
readonly type: "text";
|
|
304
311
|
readonly description?: string;
|
|
305
312
|
readonly maxLength?: number;
|
|
313
|
+
readonly minLength?: number;
|
|
306
314
|
readonly required?: boolean;
|
|
307
315
|
readonly searchable?: boolean;
|
|
308
316
|
readonly sortable?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSystemUser, defineWriteHandler, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { AuthErrors } from "../../auth-email-password/index.js";
|
|
@@ -27,8 +27,14 @@ export const changeEmailWrite = defineWriteHandler({
|
|
|
27
27
|
currentPassword: z.string().min(1),
|
|
28
28
|
newEmail: z.email(),
|
|
29
29
|
}),
|
|
30
|
-
access: {
|
|
30
|
+
access: {
|
|
31
|
+
openToAll: {
|
|
32
|
+
reason: "self-service for any signed-in user, including tenant members whose only role is " +
|
|
33
|
+
"TenantAdmin; the handler only touches event.user.id and re-checks the caller's password",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
31
36
|
escapeHatch: {
|
|
37
|
+
grants: ["systemIdentity"],
|
|
32
38
|
reason: "Reads the caller's own passwordHash via ctx.queryAs(SYSTEM, user:findForAuth), checks " +
|
|
33
39
|
"email uniqueness the same way, and writes the new email via ctx.writeAs(SYSTEM, " +
|
|
34
40
|
"user:update) — field-access on passwordHash/email is privileged-only.",
|