@cosmicdrift/kumiko-bundled-features 0.351.0 → 0.353.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-manifest.js +8 -2
- 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/audit/handlers/list.query.js +13 -8
- package/dist/auth-email-password/handlers/signup-confirm.write.js +2 -3
- package/dist/auth-mfa/schema/user-mfa.d.ts +6 -0
- package/dist/auth-mfa/screens.js +2 -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/book-cap-usage.d.ts +5 -1
- package/dist/cap-counter/book-cap-usage.js +65 -44
- package/dist/cap-counter/cap-reservation.d.ts +12 -0
- package/dist/cap-counter/cap-reservation.js +135 -0
- package/dist/cap-counter/constants.d.ts +3 -0
- package/dist/cap-counter/constants.js +6 -0
- package/dist/cap-counter/entity.d.ts +1 -0
- package/dist/cap-counter/feature.js +7 -2
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +5 -0
- package/dist/cap-counter/handlers/increment-rolling.write.js +4 -0
- package/dist/cap-counter/index.d.ts +4 -2
- package/dist/cap-counter/index.js +3 -1
- package/dist/cap-counter/payload-field.d.ts +1 -0
- package/dist/cap-counter/payload-field.js +11 -0
- package/dist/cap-counter/reservation-chain.d.ts +2 -0
- package/dist/cap-counter/reservation-chain.js +44 -0
- package/dist/cap-counter/stock-cap-guard.d.ts +3 -0
- package/dist/cap-counter/tables.d.ts +3 -0
- package/dist/cap-counter/tables.js +36 -0
- package/dist/cap-counter/value-cap-guard.d.ts +18 -0
- package/dist/cap-counter/value-cap-guard.js +33 -0
- package/dist/cap-counter/with-cap-enforcement.d.ts +5 -7
- package/dist/cap-counter/with-cap-enforcement.js +35 -51
- 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-discord/feature.js +1 -0
- package/dist/channel-slack/feature.js +1 -0
- package/dist/channel-teams/feature.js +1 -0
- 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/custom-fields/entity.d.ts +4 -0
- package/dist/data-retention/schema/tenant-retention-override.d.ts +4 -0
- package/dist/delivery/attempt-log-retention.d.ts +9 -0
- package/dist/delivery/attempt-log-retention.js +23 -0
- package/dist/delivery/attempt-log.d.ts +1 -1
- package/dist/delivery/attempt-log.js +21 -2
- package/dist/delivery/constants.d.ts +1 -1
- package/dist/delivery/constants.js +1 -1
- package/dist/delivery/events.d.ts +1 -0
- package/dist/delivery/events.js +2 -0
- package/dist/delivery/feature.d.ts +1 -0
- package/dist/delivery/feature.js +39 -3
- package/dist/delivery/index.d.ts +2 -1
- package/dist/delivery/index.js +2 -1
- package/dist/delivery/mask-recipient-address.d.ts +1 -0
- package/dist/delivery/mask-recipient-address.js +41 -0
- package/dist/delivery/public-names.d.ts +2 -0
- package/dist/delivery/public-names.js +4 -1
- package/dist/delivery/tables.d.ts +6 -0
- package/dist/delivery/types.d.ts +1 -0
- package/dist/delivery/types.js +6 -2
- package/dist/document-ingest-foundation/entity.d.ts +4 -0
- package/dist/files-tenant-data/hooks.js +3 -2
- package/dist/folders/entity.d.ts +8 -0
- package/dist/folders/feature.js +2 -10
- 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/inbound-mail-foundation/entities.d.ts +25 -0
- package/dist/inbound-mail-foundation/projection.d.ts +20 -0
- package/dist/jobs/handlers/list.query.d.ts +2 -1
- package/dist/jobs/handlers/list.query.js +39 -14
- package/dist/jobs/i18n.js +1 -0
- package/dist/jobs/job-run-table.d.ts +6 -0
- package/dist/ledger/entity.d.ts +24 -8
- package/dist/ledger/entity.js +4 -0
- package/dist/ledger/schemas.js +8 -2
- 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/feature.js +2 -10
- package/dist/personal-access-tokens/schema/api-token.d.ts +6 -0
- package/dist/personal-access-tokens/screens.js +14 -3
- package/dist/renderer-foundation/types.d.ts +1 -0
- package/dist/renderer-simple/feature.js +4 -6
- package/dist/renderer-simple/index.d.ts +1 -0
- package/dist/renderer-simple/mail-blocks.d.ts +21 -0
- package/dist/renderer-simple/mail-blocks.js +107 -0
- package/dist/renderer-simple/simple-renderer.js +21 -3
- package/dist/secrets/table.d.ts +1 -0
- package/dist/seo/feature.js +28 -6
- package/dist/sessions/schema/user-session.d.ts +4 -0
- 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/index.d.ts +2 -1
- package/dist/shared/index.js +2 -1
- package/dist/shared/rate-limited-text-response.d.ts +2 -0
- package/dist/shared/rate-limited-text-response.js +9 -0
- package/dist/tags/entity.d.ts +9 -0
- package/dist/tags/feature.js +2 -10
- 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/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/index.d.ts +1 -0
- package/dist/tenant/index.js +1 -0
- package/dist/tenant/invitation-table.d.ts +16 -8
- 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-lifecycle/feature.js +1 -0
- package/dist/tenant-lifecycle/run-tenant-destroy.d.ts +3 -0
- package/dist/tenant-lifecycle/run-tenant-destroy.js +2 -0
- package/dist/tenant-lifecycle/stages.d.ts +2 -0
- package/dist/tenant-lifecycle/stages.js +7 -1
- package/dist/tier-engine/entity.d.ts +2 -0
- package/dist/tier-engine/index.d.ts +1 -0
- package/dist/tier-engine/index.js +1 -0
- package/dist/tier-engine/tier-option-gate.d.ts +32 -0
- package/dist/tier-engine/tier-option-gate.js +62 -0
- package/dist/tier-engine/tier-resolver.d.ts +2 -0
- package/dist/user/handlers/list.query.js +2 -2
- package/dist/user/schema/user.d.ts +22 -8
- 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/schema/download-attempt.d.ts +14 -0
- 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-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +25 -6
- package/dist/waitlist/entity.d.ts +22 -6
- package/dist/workflow-runner/event-trigger.js +6 -3
- package/dist/workflow-runner/handlers/resume-run.write.js +3 -0
- package/package.json +10 -10
- package/src/agent-tools/changes.json +12 -0
- package/src/audit/changes.json +6 -0
- package/src/cap-counter/changes.json +28 -0
- package/src/delivery/changes.json +12 -0
- package/src/derivatives-sharp/changes.json +6 -0
- package/src/form-draft/changes.json +7 -1
- package/src/legal-pages/changes.json +6 -0
- package/src/managed-pages/changes.json +6 -0
- package/src/renderer-simple/changes.json +6 -0
- package/src/seo/changes.json +5 -0
- package/src/tenant/changes.json +7 -0
- package/src/tenant-handover/changes.json +6 -0
- package/src/tier-engine/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
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { countWhere, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
2
|
+
import { decodeCursor, encodeCursor } from "@cosmicdrift/kumiko-framework/db";
|
|
2
3
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
|
+
import { InternalError, ValidationError } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
5
|
import * as z from "zod";
|
|
5
6
|
import { decryptStoredPii, mapWithConcurrency } from "../../shared/index.js";
|
|
6
7
|
import { jobRunsTable } from "../job-run-table.js";
|
|
7
8
|
const KMS_POOL_CONCURRENCY = 4;
|
|
9
|
+
const DEFAULT_PAGE_SIZE = 50;
|
|
8
10
|
const jobRunStatusSchema = z.enum(["queued", "running", "completed", "failed"]);
|
|
9
11
|
async function decryptRunRow(row) {
|
|
10
12
|
let result = row;
|
|
@@ -19,6 +21,26 @@ async function decryptRunRow(row) {
|
|
|
19
21
|
}
|
|
20
22
|
return result;
|
|
21
23
|
}
|
|
24
|
+
function buildListWhere(payload) {
|
|
25
|
+
const where = {};
|
|
26
|
+
if (payload.jobName)
|
|
27
|
+
where["jobName"] = payload.jobName;
|
|
28
|
+
const statuses = payload.filters?.[0]?.value ?? (payload.status ? [payload.status] : []);
|
|
29
|
+
if (statuses.length === 1)
|
|
30
|
+
where["status"] = statuses[0];
|
|
31
|
+
else if (statuses.length > 1)
|
|
32
|
+
where["status"] = { in: statuses };
|
|
33
|
+
return where;
|
|
34
|
+
}
|
|
35
|
+
function parseOffsetCursor(cursor) {
|
|
36
|
+
const offset = cursor ? Number(decodeCursor(cursor)) : 0;
|
|
37
|
+
if (!Number.isInteger(offset) || offset < 0) {
|
|
38
|
+
throw new ValidationError({
|
|
39
|
+
fields: [{ path: "cursor", code: "invalid_cursor", i18nKey: "jobs.errors.invalidCursor" }],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return offset;
|
|
43
|
+
}
|
|
22
44
|
export const listQuery = defineQueryHandler({
|
|
23
45
|
name: "list",
|
|
24
46
|
description: "Lists job runs across all tenants newest-first, optionally filtered by job name and status; use it to check whether a job ran and whether it succeeded.",
|
|
@@ -35,6 +57,7 @@ export const listQuery = defineQueryHandler({
|
|
|
35
57
|
sort: z.enum(["jobName", "status", "startedAt", "duration"]).optional(),
|
|
36
58
|
sortDirection: z.enum(["asc", "desc"]).optional(),
|
|
37
59
|
limit: z.number().optional(),
|
|
60
|
+
cursor: z.string().optional(),
|
|
38
61
|
totalCount: z.boolean().optional(),
|
|
39
62
|
}),
|
|
40
63
|
access: { roles: ["SystemAdmin"] },
|
|
@@ -45,27 +68,29 @@ export const listQuery = defineQueryHandler({
|
|
|
45
68
|
});
|
|
46
69
|
}
|
|
47
70
|
const db = ctx.systemDb.unsafeRaw("cross-tenant job monitoring: SystemAdmin lists job runs of every tenant");
|
|
48
|
-
const where =
|
|
49
|
-
if (query.payload.jobName)
|
|
50
|
-
where["jobName"] = query.payload.jobName;
|
|
51
|
-
const statusFilter = query.payload.filters?.find((filter) => filter.field === "status");
|
|
52
|
-
const statuses = statusFilter?.value ?? (query.payload.status ? [query.payload.status] : []);
|
|
53
|
-
if (statuses.length === 1)
|
|
54
|
-
where["status"] = statuses[0];
|
|
55
|
-
else if (statuses.length > 1)
|
|
56
|
-
where["status"] = { in: statuses };
|
|
71
|
+
const where = buildListWhere(query.payload);
|
|
57
72
|
const sortColumn = query.payload.sort ?? "startedAt";
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
const limit = query.payload.limit ?? DEFAULT_PAGE_SIZE;
|
|
74
|
+
const offset = parseOffsetCursor(query.payload.cursor);
|
|
75
|
+
const direction = query.payload.sortDirection ?? "desc";
|
|
76
|
+
// selectMany has no OFFSET: read through the end of the page plus one probe
|
|
77
|
+
// row, then slice. `id` as tiebreaker keeps pages stable for non-unique sorts.
|
|
78
|
+
const fetched = await selectMany(db, jobRunsTable, where, {
|
|
79
|
+
orderBy: [
|
|
80
|
+
{ col: sortColumn, direction },
|
|
81
|
+
{ col: "id", direction },
|
|
82
|
+
],
|
|
83
|
+
limit: offset + limit + 1,
|
|
61
84
|
});
|
|
85
|
+
const hasMore = fetched.length > offset + limit;
|
|
86
|
+
const rows = fetched.slice(offset, offset + limit);
|
|
62
87
|
// countWhere reruns the SAME `where` without the limit — `rows.length` is
|
|
63
88
|
// capped at the page size and would silently undercount the total.
|
|
64
89
|
const total = query.payload.totalCount === true ? await countWhere(db, jobRunsTable, where) : undefined;
|
|
65
90
|
// payload/error are stored encrypted under the triggering user's DEK (#799, #2307).
|
|
66
91
|
return {
|
|
67
92
|
rows: await mapWithConcurrency(rows, KMS_POOL_CONCURRENCY, decryptRunRow),
|
|
68
|
-
nextCursor: null,
|
|
93
|
+
nextCursor: hasMore ? encodeCursor(String(offset + limit)) : null,
|
|
69
94
|
...(total !== undefined && { total }),
|
|
70
95
|
};
|
|
71
96
|
},
|
package/dist/jobs/i18n.js
CHANGED
|
@@ -33,6 +33,7 @@ export const JOBS_I18N = {
|
|
|
33
33
|
"jobs.detail.logs": { en: "Logs" },
|
|
34
34
|
"jobs.detail.retry": { en: "Retry" },
|
|
35
35
|
"jobs.trigger.title": { en: "Run a job" },
|
|
36
|
+
"jobs.errors.invalidCursor": { en: "The pagination cursor is invalid." },
|
|
36
37
|
"jobs.trigger.submit": { en: "Run" },
|
|
37
38
|
"jobs.errors.unknownJob": { en: "Unknown job." },
|
|
38
39
|
"jobs.errors.notManual": {
|
|
@@ -6,6 +6,7 @@ export declare const jobRunEntity: import("@cosmicdrift/kumiko-types/fields").En
|
|
|
6
6
|
readonly type: "text";
|
|
7
7
|
readonly description?: string;
|
|
8
8
|
readonly maxLength?: number;
|
|
9
|
+
readonly minLength?: number;
|
|
9
10
|
readonly required?: boolean;
|
|
10
11
|
readonly searchable?: boolean;
|
|
11
12
|
readonly sortable?: boolean;
|
|
@@ -27,6 +28,7 @@ export declare const jobRunEntity: import("@cosmicdrift/kumiko-types/fields").En
|
|
|
27
28
|
readonly type: "text";
|
|
28
29
|
readonly description?: string;
|
|
29
30
|
readonly maxLength?: number;
|
|
31
|
+
readonly minLength?: number;
|
|
30
32
|
readonly required?: boolean;
|
|
31
33
|
readonly searchable?: boolean;
|
|
32
34
|
readonly sortable?: boolean;
|
|
@@ -48,6 +50,7 @@ export declare const jobRunEntity: import("@cosmicdrift/kumiko-types/fields").En
|
|
|
48
50
|
readonly type: "text";
|
|
49
51
|
readonly description?: string;
|
|
50
52
|
readonly maxLength?: number;
|
|
53
|
+
readonly minLength?: number;
|
|
51
54
|
readonly required?: boolean;
|
|
52
55
|
readonly searchable?: boolean;
|
|
53
56
|
readonly sortable?: boolean;
|
|
@@ -69,6 +72,7 @@ export declare const jobRunEntity: import("@cosmicdrift/kumiko-types/fields").En
|
|
|
69
72
|
readonly type: "text";
|
|
70
73
|
readonly description?: string;
|
|
71
74
|
readonly maxLength?: number;
|
|
75
|
+
readonly minLength?: number;
|
|
72
76
|
readonly required?: boolean;
|
|
73
77
|
readonly searchable?: boolean;
|
|
74
78
|
readonly sortable?: boolean;
|
|
@@ -90,6 +94,7 @@ export declare const jobRunEntity: import("@cosmicdrift/kumiko-types/fields").En
|
|
|
90
94
|
readonly type: "text";
|
|
91
95
|
readonly description?: string;
|
|
92
96
|
readonly maxLength?: number;
|
|
97
|
+
readonly minLength?: number;
|
|
93
98
|
readonly required?: boolean;
|
|
94
99
|
readonly searchable?: boolean;
|
|
95
100
|
readonly sortable?: boolean;
|
|
@@ -179,6 +184,7 @@ export declare const jobRunEntity: import("@cosmicdrift/kumiko-types/fields").En
|
|
|
179
184
|
readonly type: "text";
|
|
180
185
|
readonly description?: string;
|
|
181
186
|
readonly maxLength?: number;
|
|
187
|
+
readonly minLength?: number;
|
|
182
188
|
readonly required?: boolean;
|
|
183
189
|
readonly searchable?: boolean;
|
|
184
190
|
readonly sortable?: boolean;
|
package/dist/ledger/entity.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
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;
|
|
@@ -32,14 +33,15 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
32
33
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
33
34
|
readonly display?: "radio" | "dropdown";
|
|
34
35
|
readonly optionTones?: {
|
|
35
|
-
readonly asset?:
|
|
36
|
-
readonly equity?:
|
|
37
|
-
readonly expense?:
|
|
38
|
-
readonly income?:
|
|
39
|
-
readonly liability?:
|
|
36
|
+
readonly asset?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
37
|
+
readonly equity?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
38
|
+
readonly expense?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
39
|
+
readonly income?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
40
|
+
readonly liability?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
40
41
|
} | undefined;
|
|
41
42
|
readonly optionsQuery?: string;
|
|
42
43
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
44
|
+
readonly optionsAvailabilityQuery?: string;
|
|
43
45
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
44
46
|
required: true;
|
|
45
47
|
};
|
|
@@ -47,6 +49,7 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
47
49
|
readonly type: "text";
|
|
48
50
|
readonly description?: string;
|
|
49
51
|
readonly maxLength?: number;
|
|
52
|
+
readonly minLength?: number;
|
|
50
53
|
readonly required?: boolean;
|
|
51
54
|
readonly searchable?: boolean;
|
|
52
55
|
readonly sortable?: boolean;
|
|
@@ -68,6 +71,7 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
68
71
|
readonly type: "text";
|
|
69
72
|
readonly description?: string;
|
|
70
73
|
readonly maxLength?: number;
|
|
74
|
+
readonly minLength?: number;
|
|
71
75
|
readonly required?: boolean;
|
|
72
76
|
readonly searchable?: boolean;
|
|
73
77
|
readonly sortable?: boolean;
|
|
@@ -105,6 +109,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
|
|
|
105
109
|
readonly type: "text";
|
|
106
110
|
readonly description?: string;
|
|
107
111
|
readonly maxLength?: number;
|
|
112
|
+
readonly minLength?: number;
|
|
108
113
|
readonly required?: boolean;
|
|
109
114
|
readonly searchable?: boolean;
|
|
110
115
|
readonly sortable?: boolean;
|
|
@@ -126,6 +131,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
|
|
|
126
131
|
readonly type: "text";
|
|
127
132
|
readonly description?: string;
|
|
128
133
|
readonly maxLength?: number;
|
|
134
|
+
readonly minLength?: number;
|
|
129
135
|
readonly required?: boolean;
|
|
130
136
|
readonly searchable?: boolean;
|
|
131
137
|
readonly sortable?: boolean;
|
|
@@ -155,11 +161,12 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
|
|
|
155
161
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
156
162
|
readonly display?: "radio" | "dropdown";
|
|
157
163
|
readonly optionTones?: {
|
|
158
|
-
readonly draft?:
|
|
159
|
-
readonly posted?:
|
|
164
|
+
readonly draft?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
165
|
+
readonly posted?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
160
166
|
} | undefined;
|
|
161
167
|
readonly optionsQuery?: string;
|
|
162
168
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
169
|
+
readonly optionsAvailabilityQuery?: string;
|
|
163
170
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
164
171
|
required: true;
|
|
165
172
|
};
|
|
@@ -183,6 +190,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
|
|
|
183
190
|
readonly type: "text";
|
|
184
191
|
readonly description?: string;
|
|
185
192
|
readonly maxLength?: number;
|
|
193
|
+
readonly minLength?: number;
|
|
186
194
|
readonly required?: boolean;
|
|
187
195
|
readonly searchable?: boolean;
|
|
188
196
|
readonly sortable?: boolean;
|
|
@@ -204,6 +212,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
|
|
|
204
212
|
readonly type: "text";
|
|
205
213
|
readonly description?: string;
|
|
206
214
|
readonly maxLength?: number;
|
|
215
|
+
readonly minLength?: number;
|
|
207
216
|
readonly required?: boolean;
|
|
208
217
|
readonly searchable?: boolean;
|
|
209
218
|
readonly sortable?: boolean;
|
|
@@ -227,6 +236,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
227
236
|
readonly type: "text";
|
|
228
237
|
readonly description?: string;
|
|
229
238
|
readonly maxLength?: number;
|
|
239
|
+
readonly minLength?: number;
|
|
230
240
|
readonly required?: boolean;
|
|
231
241
|
readonly searchable?: boolean;
|
|
232
242
|
readonly sortable?: boolean;
|
|
@@ -284,10 +294,11 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
284
294
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
285
295
|
readonly display?: "radio" | "dropdown";
|
|
286
296
|
readonly optionTones?: {
|
|
287
|
-
readonly monthly?:
|
|
297
|
+
readonly monthly?: "bad" | "neutral" | "ok" | "warn" | undefined;
|
|
288
298
|
} | undefined;
|
|
289
299
|
readonly optionsQuery?: string;
|
|
290
300
|
readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
|
|
301
|
+
readonly optionsAvailabilityQuery?: string;
|
|
291
302
|
} & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
|
|
292
303
|
required: true;
|
|
293
304
|
};
|
|
@@ -314,6 +325,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
314
325
|
readonly type: "text";
|
|
315
326
|
readonly description?: string;
|
|
316
327
|
readonly maxLength?: number;
|
|
328
|
+
readonly minLength?: number;
|
|
317
329
|
readonly required?: boolean;
|
|
318
330
|
readonly searchable?: boolean;
|
|
319
331
|
readonly sortable?: boolean;
|
|
@@ -335,6 +347,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
335
347
|
readonly type: "text";
|
|
336
348
|
readonly description?: string;
|
|
337
349
|
readonly maxLength?: number;
|
|
350
|
+
readonly minLength?: number;
|
|
338
351
|
readonly required?: boolean;
|
|
339
352
|
readonly searchable?: boolean;
|
|
340
353
|
readonly sortable?: boolean;
|
|
@@ -356,6 +369,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
356
369
|
readonly type: "text";
|
|
357
370
|
readonly description?: string;
|
|
358
371
|
readonly maxLength?: number;
|
|
372
|
+
readonly minLength?: number;
|
|
359
373
|
readonly required?: boolean;
|
|
360
374
|
readonly searchable?: boolean;
|
|
361
375
|
readonly sortable?: boolean;
|
|
@@ -377,6 +391,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
377
391
|
readonly type: "text";
|
|
378
392
|
readonly description?: string;
|
|
379
393
|
readonly maxLength?: number;
|
|
394
|
+
readonly minLength?: number;
|
|
380
395
|
readonly required?: boolean;
|
|
381
396
|
readonly searchable?: boolean;
|
|
382
397
|
readonly sortable?: boolean;
|
|
@@ -398,6 +413,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
398
413
|
readonly type: "text";
|
|
399
414
|
readonly description?: string;
|
|
400
415
|
readonly maxLength?: number;
|
|
416
|
+
readonly minLength?: number;
|
|
401
417
|
readonly required?: boolean;
|
|
402
418
|
readonly searchable?: boolean;
|
|
403
419
|
readonly sortable?: boolean;
|
package/dist/ledger/entity.js
CHANGED
|
@@ -80,12 +80,14 @@ export const transactionEntity = createEntity({
|
|
|
80
80
|
// Optional business-object reference (e.g. a lease contract) so entries can
|
|
81
81
|
// be filtered by what they're about, not just grepped out of `reference`.
|
|
82
82
|
subjectType: createTextField({
|
|
83
|
+
minLength: 1,
|
|
83
84
|
maxLength: 64,
|
|
84
85
|
personal: false,
|
|
85
86
|
reason: "technical_reference",
|
|
86
87
|
filterable: true,
|
|
87
88
|
}),
|
|
88
89
|
subjectId: createTextField({
|
|
90
|
+
minLength: 1,
|
|
89
91
|
maxLength: 128,
|
|
90
92
|
personal: false,
|
|
91
93
|
reason: "technical_reference",
|
|
@@ -131,12 +133,14 @@ export const scheduleEntity = createEntity({
|
|
|
131
133
|
// Confirmed periods inherit this from the schedule (see
|
|
132
134
|
// confirm-schedule-period.write.ts) rather than repeating it per period.
|
|
133
135
|
subjectType: createTextField({
|
|
136
|
+
minLength: 1,
|
|
134
137
|
maxLength: 64,
|
|
135
138
|
personal: false,
|
|
136
139
|
reason: "technical_reference",
|
|
137
140
|
filterable: true,
|
|
138
141
|
}),
|
|
139
142
|
subjectId: createTextField({
|
|
143
|
+
minLength: 1,
|
|
140
144
|
maxLength: 128,
|
|
141
145
|
personal: false,
|
|
142
146
|
reason: "technical_reference",
|
package/dist/ledger/schemas.js
CHANGED
|
@@ -21,8 +21,14 @@ export const createTransactionPayloadSchema = z
|
|
|
21
21
|
status: z.enum(TRANSACTION_STATUS).optional(),
|
|
22
22
|
lines: z.array(postingSchema).min(2),
|
|
23
23
|
// Business-object reference (e.g. a lease contract) this entry is about.
|
|
24
|
-
subjectType: z.string().max(64).optional(),
|
|
25
|
-
subjectId: z.string().max(128).optional(),
|
|
24
|
+
subjectType: z.string().min(1).max(64).optional(),
|
|
25
|
+
subjectId: z.string().min(1).max(128).optional(),
|
|
26
|
+
})
|
|
27
|
+
// Ids are only unique within their type, so a lone subjectId would match
|
|
28
|
+
// bookings of a different object type.
|
|
29
|
+
.refine((p) => (p.subjectType === undefined) === (p.subjectId === undefined), {
|
|
30
|
+
message: "subjectType and subjectId must be set together",
|
|
31
|
+
path: ["subjectId"],
|
|
26
32
|
})
|
|
27
33
|
.refine((p) => sumIsZero(p.lines), {
|
|
28
34
|
message: "Transaction must balance: Σ of posting amounts must equal 0",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { computeRevisionEtag, etagMatches } from "@cosmicdrift/kumiko-framework/api";
|
|
2
2
|
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
+
import { RateLimitError } from "@cosmicdrift/kumiko-framework/errors";
|
|
3
4
|
import { cachedSecurePageResponse, EMPTY_BRANDING, renderSafeMarkdown, wrapInLayout, } from "../page-render/index.js";
|
|
5
|
+
import { rateLimitedTextResponse } from "../shared/index.js";
|
|
4
6
|
import { BRANDING_KEYS, BRANDING_QUERY_QN, CUSTOM_CSS_KEY, coerceBranding } from "./branding.js";
|
|
5
7
|
import { createBrandingQuery } from "./handlers/branding.query.js";
|
|
6
8
|
import { bySlugQuery } from "./handlers/by-slug.query.js";
|
|
@@ -28,14 +30,17 @@ function brandingRevisionSeed(branding) {
|
|
|
28
30
|
branding.customCss,
|
|
29
31
|
]);
|
|
30
32
|
}
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
33
|
+
// A query failure or malformed result degrades to the unbranded default
|
|
34
|
+
// (branding is decoration, not a hard dependency of the page render). A rate
|
|
35
|
+
// limit is rethrown so the route answers 429 instead of serving (and caching)
|
|
36
|
+
// an unbranded page.
|
|
34
37
|
async function readBrandingViaSystemQuery(systemQuery, tenantId) {
|
|
35
38
|
try {
|
|
36
39
|
return coerceBranding(await systemQuery(BRANDING_QUERY_QN, {}, tenantId));
|
|
37
40
|
}
|
|
38
|
-
catch {
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof RateLimitError)
|
|
43
|
+
throw error;
|
|
39
44
|
return EMPTY_BRANDING;
|
|
40
45
|
}
|
|
41
46
|
}
|
|
@@ -125,12 +130,25 @@ export function createManagedPagesFeature(opts) {
|
|
|
125
130
|
// von resolverTrust: "authoritative" zurecht abgelehnt; siehe
|
|
126
131
|
// systemQuery's Doc in http-route.ts). Branding ist Deko → ein
|
|
127
132
|
// Fehlschlag degradiert zum unbranded Default, blockt nie die Page.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
let pageSettled;
|
|
134
|
+
let brandingResult;
|
|
135
|
+
try {
|
|
136
|
+
[pageSettled, brandingResult] = await Promise.all([
|
|
137
|
+
systemQuery(BY_SLUG_QN, { slug, lang }, tenantId)
|
|
138
|
+
.then((data) => ({ ok: true, data: data }))
|
|
139
|
+
.catch((error) => {
|
|
140
|
+
if (error instanceof RateLimitError)
|
|
141
|
+
throw error;
|
|
142
|
+
return { ok: false };
|
|
143
|
+
}),
|
|
144
|
+
readBrandingViaSystemQuery(systemQuery, tenantId),
|
|
145
|
+
]);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (error instanceof RateLimitError)
|
|
149
|
+
return rateLimitedTextResponse(error);
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
134
152
|
if (!pageSettled.ok)
|
|
135
153
|
return c.text("page unavailable", 503);
|
|
136
154
|
const data = pageSettled.data;
|
|
@@ -3,6 +3,7 @@ export declare const pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
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 pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
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 pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
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 pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
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 pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
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 pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
|
|
|
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;
|
|
@@ -134,6 +140,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
|
|
|
134
140
|
readonly type: "text";
|
|
135
141
|
readonly description?: string;
|
|
136
142
|
readonly maxLength?: number;
|
|
143
|
+
readonly minLength?: number;
|
|
137
144
|
readonly required?: boolean;
|
|
138
145
|
readonly searchable?: boolean;
|
|
139
146
|
readonly sortable?: boolean;
|
|
@@ -155,6 +162,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
|
|
|
155
162
|
readonly type: "text";
|
|
156
163
|
readonly description?: string;
|
|
157
164
|
readonly maxLength?: number;
|
|
165
|
+
readonly minLength?: number;
|
|
158
166
|
readonly required?: boolean;
|
|
159
167
|
readonly searchable?: boolean;
|
|
160
168
|
readonly sortable?: boolean;
|
|
@@ -176,6 +184,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
|
|
|
176
184
|
readonly type: "text";
|
|
177
185
|
readonly description?: string;
|
|
178
186
|
readonly maxLength?: number;
|
|
187
|
+
readonly minLength?: number;
|
|
179
188
|
readonly required?: boolean;
|
|
180
189
|
readonly searchable?: boolean;
|
|
181
190
|
readonly sortable?: boolean;
|
|
@@ -197,6 +206,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
|
|
|
197
206
|
readonly type: "text";
|
|
198
207
|
readonly description?: string;
|
|
199
208
|
readonly maxLength?: number;
|
|
209
|
+
readonly minLength?: number;
|
|
200
210
|
readonly required?: boolean;
|
|
201
211
|
readonly searchable?: boolean;
|
|
202
212
|
readonly sortable?: boolean;
|
|
@@ -218,6 +228,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
|
|
|
218
228
|
readonly type: "text";
|
|
219
229
|
readonly description?: string;
|
|
220
230
|
readonly maxLength?: number;
|
|
231
|
+
readonly minLength?: number;
|
|
221
232
|
readonly required?: boolean;
|
|
222
233
|
readonly searchable?: boolean;
|
|
223
234
|
readonly sortable?: boolean;
|
|
@@ -239,6 +250,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
|
|
|
239
250
|
readonly type: "text";
|
|
240
251
|
readonly description?: string;
|
|
241
252
|
readonly maxLength?: number;
|
|
253
|
+
readonly minLength?: number;
|
|
242
254
|
readonly required?: boolean;
|
|
243
255
|
readonly searchable?: boolean;
|
|
244
256
|
readonly sortable?: boolean;
|
|
@@ -4,6 +4,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
|
|
|
4
4
|
readonly type: "text";
|
|
5
5
|
readonly description?: string;
|
|
6
6
|
readonly maxLength?: number;
|
|
7
|
+
readonly minLength?: number;
|
|
7
8
|
readonly required?: boolean;
|
|
8
9
|
readonly searchable?: boolean;
|
|
9
10
|
readonly sortable?: boolean;
|
|
@@ -25,6 +26,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
|
|
|
25
26
|
readonly type: "text";
|
|
26
27
|
readonly description?: string;
|
|
27
28
|
readonly maxLength?: number;
|
|
29
|
+
readonly minLength?: number;
|
|
28
30
|
readonly required?: boolean;
|
|
29
31
|
readonly searchable?: boolean;
|
|
30
32
|
readonly sortable?: boolean;
|
|
@@ -46,6 +48,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
|
|
|
46
48
|
readonly type: "text";
|
|
47
49
|
readonly description?: string;
|
|
48
50
|
readonly maxLength?: number;
|
|
51
|
+
readonly minLength?: number;
|
|
49
52
|
readonly required?: boolean;
|
|
50
53
|
readonly searchable?: boolean;
|
|
51
54
|
readonly sortable?: boolean;
|
|
@@ -67,6 +70,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
|
|
|
67
70
|
readonly type: "text";
|
|
68
71
|
readonly description?: string;
|
|
69
72
|
readonly maxLength?: number;
|
|
73
|
+
readonly minLength?: number;
|
|
70
74
|
readonly required?: boolean;
|
|
71
75
|
readonly searchable?: boolean;
|
|
72
76
|
readonly sortable?: boolean;
|
|
@@ -106,6 +110,7 @@ export declare const noteEntryEntity: EntityDefinition<{
|
|
|
106
110
|
readonly type: "text";
|
|
107
111
|
readonly description?: string;
|
|
108
112
|
readonly maxLength?: number;
|
|
113
|
+
readonly minLength?: number;
|
|
109
114
|
readonly required?: boolean;
|
|
110
115
|
readonly searchable?: boolean;
|
|
111
116
|
readonly sortable?: boolean;
|
|
@@ -127,6 +132,7 @@ export declare const noteEntryEntity: EntityDefinition<{
|
|
|
127
132
|
readonly type: "text";
|
|
128
133
|
readonly description?: string;
|
|
129
134
|
readonly maxLength?: number;
|
|
135
|
+
readonly minLength?: number;
|
|
130
136
|
readonly required?: boolean;
|
|
131
137
|
readonly searchable?: boolean;
|
|
132
138
|
readonly sortable?: boolean;
|
|
@@ -148,6 +154,7 @@ export declare const noteEntryEntity: EntityDefinition<{
|
|
|
148
154
|
readonly type: "text";
|
|
149
155
|
readonly description?: string;
|
|
150
156
|
readonly maxLength?: number;
|
|
157
|
+
readonly minLength?: number;
|
|
151
158
|
readonly required?: boolean;
|
|
152
159
|
readonly searchable?: boolean;
|
|
153
160
|
readonly sortable?: boolean;
|
|
@@ -169,6 +176,7 @@ export declare const noteEntryEntity: EntityDefinition<{
|
|
|
169
176
|
readonly type: "text";
|
|
170
177
|
readonly description?: string;
|
|
171
178
|
readonly maxLength?: number;
|
|
179
|
+
readonly minLength?: number;
|
|
172
180
|
readonly required?: boolean;
|
|
173
181
|
readonly searchable?: boolean;
|
|
174
182
|
readonly sortable?: boolean;
|
|
@@ -208,6 +216,7 @@ export declare function createNoteMentionEntity(): EntityDefinition<{
|
|
|
208
216
|
readonly type: "text";
|
|
209
217
|
readonly description?: string;
|
|
210
218
|
readonly maxLength?: number;
|
|
219
|
+
readonly minLength?: number;
|
|
211
220
|
readonly required?: boolean;
|
|
212
221
|
readonly searchable?: boolean;
|
|
213
222
|
readonly sortable?: boolean;
|
|
@@ -229,6 +238,7 @@ export declare function createNoteMentionEntity(): EntityDefinition<{
|
|
|
229
238
|
readonly type: "text";
|
|
230
239
|
readonly description?: string;
|
|
231
240
|
readonly maxLength?: number;
|
|
241
|
+
readonly minLength?: number;
|
|
232
242
|
readonly required?: boolean;
|
|
233
243
|
readonly searchable?: boolean;
|
|
234
244
|
readonly sortable?: boolean;
|
|
@@ -252,6 +262,7 @@ export declare const noteMentionEntity: EntityDefinition<{
|
|
|
252
262
|
readonly type: "text";
|
|
253
263
|
readonly description?: string;
|
|
254
264
|
readonly maxLength?: number;
|
|
265
|
+
readonly minLength?: number;
|
|
255
266
|
readonly required?: boolean;
|
|
256
267
|
readonly searchable?: boolean;
|
|
257
268
|
readonly sortable?: boolean;
|
|
@@ -273,6 +284,7 @@ export declare const noteMentionEntity: EntityDefinition<{
|
|
|
273
284
|
readonly type: "text";
|
|
274
285
|
readonly description?: string;
|
|
275
286
|
readonly maxLength?: number;
|
|
287
|
+
readonly minLength?: number;
|
|
276
288
|
readonly required?: boolean;
|
|
277
289
|
readonly searchable?: boolean;
|
|
278
290
|
readonly sortable?: boolean;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// a new entry, not an edit; see entity.ts for why that still satisfies GDPR
|
|
14
14
|
// erasure without a delete path.
|
|
15
15
|
import { defineEntityListHandler, defineFeature, } from "@cosmicdrift/kumiko-framework/engine";
|
|
16
|
-
import {
|
|
16
|
+
import { assertNoWhereRuleInOwnershipWrite } from "../shared/index.js";
|
|
17
17
|
import { DEFAULT_NOTES_HISTORY_ACCESS, NOTES_HISTORY_FEATURE_NAME } from "./constants.js";
|
|
18
18
|
import { createNoteEntryEntity, noteMentionEntity } from "./entity.js";
|
|
19
19
|
import { createNoteEntryExecutor } from "./executor.js";
|
|
@@ -58,15 +58,7 @@ export function createNotesHistoryFeature(opts = {}) {
|
|
|
58
58
|
opts.parents === undefined) {
|
|
59
59
|
return notesHistoryFeature;
|
|
60
60
|
}
|
|
61
|
-
|
|
62
|
-
throw new Error("createNotesHistoryFeature({ ownership }): ownership.write must not contain a " +
|
|
63
|
-
'`{ kind: "where" }` rule — where-rules are evaluated only at the SQL ' +
|
|
64
|
-
"layer (the read path, via buildOwnershipClause). Write paths that " +
|
|
65
|
-
"consult access.write (userCanCreateFieldRow/userCanWriteFieldRow) can't " +
|
|
66
|
-
"evaluate them, so such a rule can only ever deny — boot validation " +
|
|
67
|
-
"rejects it too (fw#2626). Use a `from()` rule for ownership.write, or " +
|
|
68
|
-
"leave it unset.");
|
|
69
|
-
}
|
|
61
|
+
assertNoWhereRuleInOwnershipWrite("createNotesHistoryFeature", opts.ownership?.write);
|
|
70
62
|
// A mount that accepts no parents at all can never take a note write —
|
|
71
63
|
// that's a config mistake, not a valid allowlist. Omit `parents` instead
|
|
72
64
|
// of passing an empty array.
|
|
@@ -3,6 +3,7 @@ export declare const apiTokenEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
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 apiTokenEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
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 apiTokenEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
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 apiTokenEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
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 apiTokenEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
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 apiTokenEntity: import("@cosmicdrift/kumiko-types/fields").
|
|
|
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;
|