@cosmicdrift/kumiko-types 0.327.0 → 0.328.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/action-icon.d.ts +3 -0
  2. package/dist/action-icon.js +51 -0
  3. package/{src/agent-exposure.ts → dist/agent-exposure.d.ts} +8 -15
  4. package/dist/agent-exposure.js +16 -0
  5. package/dist/concurrency-mode.d.ts +1 -0
  6. package/dist/config-scope.d.ts +1 -0
  7. package/dist/config-scope.js +1 -0
  8. package/dist/config.d.ts +234 -0
  9. package/dist/config.js +1 -0
  10. package/dist/cursor-types.d.ts +16 -0
  11. package/dist/cursor-types.js +1 -0
  12. package/dist/db-connection.d.ts +14 -0
  13. package/dist/db-connection.js +1 -0
  14. package/dist/define-handler.d.ts +58 -0
  15. package/dist/define-handler.js +1 -0
  16. package/dist/derivatives-types.d.ts +53 -0
  17. package/dist/derivatives-types.js +3 -0
  18. package/dist/entity-cache.d.ts +16 -0
  19. package/dist/entity-cache.js +1 -0
  20. package/dist/entity-handlers.d.ts +54 -0
  21. package/dist/entity-handlers.js +1 -0
  22. package/dist/entity-table-meta-types.d.ts +44 -0
  23. package/dist/entity-table-meta-types.js +6 -0
  24. package/dist/envelope-cipher-types.d.ts +5 -0
  25. package/dist/envelope-cipher-types.js +1 -0
  26. package/dist/event-store-executor-types.d.ts +86 -0
  27. package/dist/event-store-executor-types.js +1 -0
  28. package/dist/event-store-types.d.ts +37 -0
  29. package/dist/event-store-types.js +7 -0
  30. package/dist/event-type-map.d.ts +8 -0
  31. package/{src/event-type-map.ts → dist/event-type-map.js} +1 -16
  32. package/dist/executor-brand.d.ts +8 -0
  33. package/dist/executor-brand.js +1 -0
  34. package/dist/extension-options-map.d.ts +9 -0
  35. package/dist/extension-options-map.js +4 -0
  36. package/dist/feature.d.ts +518 -0
  37. package/dist/feature.js +1 -0
  38. package/dist/field-icon.d.ts +1 -0
  39. package/dist/field-icon.js +1 -0
  40. package/dist/fields.d.ts +729 -0
  41. package/dist/fields.js +50 -0
  42. package/dist/file-handle-types.d.ts +12 -0
  43. package/dist/file-handle-types.js +1 -0
  44. package/dist/file-provider-resolver-types.d.ts +3 -0
  45. package/dist/file-provider-resolver-types.js +1 -0
  46. package/dist/file-storage-provider-types.d.ts +17 -0
  47. package/dist/file-storage-provider-types.js +1 -0
  48. package/dist/geo-tz.d.ts +17 -0
  49. package/{src/geo-tz.ts → dist/geo-tz.js} +1 -20
  50. package/dist/handlers.d.ts +493 -0
  51. package/dist/handlers.js +49 -0
  52. package/dist/hook-phase.d.ts +1 -0
  53. package/dist/hook-phase.js +1 -0
  54. package/dist/hooks.d.ts +75 -0
  55. package/dist/hooks.js +1 -0
  56. package/dist/http-route.d.ts +52 -0
  57. package/dist/http-route.js +13 -0
  58. package/dist/identifiers.d.ts +8 -0
  59. package/{src/identifiers.ts → dist/identifiers.js} +7 -24
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.js +1 -0
  62. package/dist/kms-adapter-types.d.ts +68 -0
  63. package/dist/kms-adapter-types.js +49 -0
  64. package/dist/logger.d.ts +7 -0
  65. package/dist/logger.js +1 -0
  66. package/dist/multi-stream-apply-context-types.d.ts +18 -0
  67. package/dist/multi-stream-apply-context-types.js +1 -0
  68. package/dist/nav-icon.d.ts +3 -0
  69. package/dist/nav-icon.js +100 -0
  70. package/dist/nav.d.ts +39 -0
  71. package/dist/nav.js +1 -0
  72. package/dist/observability/index.d.ts +3 -0
  73. package/dist/observability/index.js +2 -0
  74. package/dist/observability/metric.d.ts +34 -0
  75. package/dist/observability/metric.js +3 -0
  76. package/dist/observability/provider.d.ts +24 -0
  77. package/dist/observability/provider.js +4 -0
  78. package/dist/observability/span.d.ts +32 -0
  79. package/dist/observability/span.js +4 -0
  80. package/dist/ownership.d.ts +33 -0
  81. package/dist/ownership.js +5 -0
  82. package/dist/projection.d.ts +38 -0
  83. package/dist/projection.js +1 -0
  84. package/dist/rate-limit-types.d.ts +19 -0
  85. package/dist/rate-limit-types.js +1 -0
  86. package/dist/relations.d.ts +25 -0
  87. package/dist/relations.js +1 -0
  88. package/dist/schema-table-types.d.ts +15 -0
  89. package/{src/schema-table-types.ts → dist/schema-table-types.js} +0 -20
  90. package/dist/screen.d.ts +1265 -0
  91. package/dist/screen.js +3 -0
  92. package/dist/search-adapter.d.ts +32 -0
  93. package/dist/search-adapter.js +1 -0
  94. package/dist/secrets-types.d.ts +52 -0
  95. package/dist/secrets-types.js +30 -0
  96. package/dist/snapshot-types.d.ts +13 -0
  97. package/dist/snapshot-types.js +1 -0
  98. package/dist/step.d.ts +304 -0
  99. package/dist/step.js +11 -0
  100. package/dist/target-ref.d.ts +5 -0
  101. package/{src/target-ref.ts → dist/target-ref.js} +1 -6
  102. package/dist/tenancy-brand.d.ts +6 -0
  103. package/dist/tenancy-brand.js +1 -0
  104. package/dist/tenant-db-types.d.ts +67 -0
  105. package/dist/tenant-db-types.js +5 -0
  106. package/dist/tree-node.d.ts +26 -0
  107. package/dist/tree-node.js +22 -0
  108. package/dist/tz-context.d.ts +48 -0
  109. package/dist/tz-context.js +6 -0
  110. package/dist/websocket-route.d.ts +46 -0
  111. package/dist/websocket-route.js +10 -0
  112. package/dist/where-clause-types.d.ts +20 -0
  113. package/dist/where-clause-types.js +1 -0
  114. package/dist/workspace.d.ts +10 -0
  115. package/dist/workspace.js +1 -0
  116. package/dist/write-error-info-types.d.ts +12 -0
  117. package/dist/write-error-info-types.js +1 -0
  118. package/package.json +372 -124
  119. package/src/changes.json +18 -0
  120. package/src/__tests__/handlers.test.ts +0 -40
  121. package/src/__tests__/plural-forms.test.ts +0 -18
  122. package/src/action-icon.ts +0 -57
  123. package/src/concurrency-mode.ts +0 -5
  124. package/src/config-scope.ts +0 -5
  125. package/src/config.ts +0 -563
  126. package/src/cursor-types.ts +0 -18
  127. package/src/db-connection.ts +0 -25
  128. package/src/define-handler.ts +0 -138
  129. package/src/derivatives-types.ts +0 -106
  130. package/src/entity-cache.ts +0 -35
  131. package/src/entity-handlers.ts +0 -68
  132. package/src/entity-table-meta-types.ts +0 -101
  133. package/src/envelope-cipher-types.ts +0 -6
  134. package/src/event-store-executor-types.ts +0 -163
  135. package/src/event-store-types.ts +0 -85
  136. package/src/executor-brand.ts +0 -19
  137. package/src/extension-options-map.ts +0 -21
  138. package/src/feature.ts +0 -1141
  139. package/src/field-icon.ts +0 -23
  140. package/src/fields.ts +0 -1114
  141. package/src/file-handle-types.ts +0 -20
  142. package/src/file-provider-resolver-types.ts +0 -7
  143. package/src/file-storage-provider-types.ts +0 -54
  144. package/src/handlers.ts +0 -1246
  145. package/src/hook-phase.ts +0 -2
  146. package/src/hooks.ts +0 -170
  147. package/src/http-route.ts +0 -78
  148. package/src/kms-adapter-types.ts +0 -128
  149. package/src/logger.ts +0 -7
  150. package/src/multi-stream-apply-context-types.ts +0 -52
  151. package/src/nav-icon.ts +0 -105
  152. package/src/nav.ts +0 -139
  153. package/src/observability/index.ts +0 -28
  154. package/src/observability/metric.ts +0 -56
  155. package/src/observability/provider.ts +0 -32
  156. package/src/observability/span.ts +0 -58
  157. package/src/ownership.ts +0 -83
  158. package/src/projection.ts +0 -170
  159. package/src/rate-limit-types.ts +0 -32
  160. package/src/relations.ts +0 -52
  161. package/src/screen.ts +0 -1593
  162. package/src/search-adapter.ts +0 -45
  163. package/src/secrets-types.ts +0 -182
  164. package/src/snapshot-types.ts +0 -36
  165. package/src/step.ts +0 -390
  166. package/src/tenancy-brand.ts +0 -9
  167. package/src/tenant-db-types.ts +0 -116
  168. package/src/tree-node.ts +0 -134
  169. package/src/tz-context.ts +0 -63
  170. package/src/websocket-route.ts +0 -68
  171. package/src/where-clause-types.ts +0 -31
  172. package/src/workspace.ts +0 -42
  173. package/src/write-error-info-types.ts +0 -20
  174. /package/{src/index.ts → dist/concurrency-mode.js} +0 -0
package/dist/fields.js ADDED
@@ -0,0 +1,50 @@
1
+ // --- Field Types ---
2
+ /** Qualified config key a `{ kind: "tenant" }` MoneyCurrencySource resolves
3
+ * against — the tenant-settings bundle's per-tenant currency. Lives here
4
+ * (client-safe) rather than framework/engine so renderer code can read it
5
+ * without a runtime-only import (kumiko-framework#2937). */
6
+ export const TENANT_CURRENCY_CONFIG_KEY = "tenant-settings:config:currency";
7
+ // Exhaustive catalogue of `FieldDefinition["type"]` values, derived from a
8
+ // `Record` so an added/removed union member fails to compile here instead of
9
+ // silently drifting out of sync with the runtime validator that consults
10
+ // this list (feature-ast's pattern-change-schema). Plain array, not a Set —
11
+ // same rationale as NO_WIDGET_FIELD_TYPES (guard-types-class-free.test.ts).
12
+ const FIELD_TYPE_NAME_FLAGS = {
13
+ text: true,
14
+ longText: true,
15
+ boolean: true,
16
+ select: true,
17
+ multiSelect: true,
18
+ number: true,
19
+ bigInt: true,
20
+ decimal: true,
21
+ money: true,
22
+ reference: true,
23
+ embedded: true,
24
+ jsonb: true,
25
+ date: true,
26
+ timestamp: true,
27
+ tz: true,
28
+ locatedTimestamp: true,
29
+ file: true,
30
+ image: true,
31
+ files: true,
32
+ images: true,
33
+ };
34
+ export const FIELD_TYPE_NAMES = Object.keys(FIELD_TYPE_NAME_FLAGS);
35
+ // Field types with no bound, editable widget on the auto-wired entityEdit
36
+ // path (render-field.tsx renders a read-only banner instead) — shared by
37
+ // the boot validator (packages/framework/src/engine/boot-validator/screens.ts)
38
+ // and the client-side required-field check (packages/renderer/src/app/form-schema.ts).
39
+ // Embedded LIST fields (`multiple: true`) are the one exception — they get
40
+ // their own EmbeddedListField grid widget (#1838) — callers must check that
41
+ // separately, this array alone doesn't distinguish plain embedded from embedded lists.
42
+ // A plain array, not a Set: kumiko-types stays free of module-scope runtime
43
+ // identity (guard-types-class-free.test.ts) since a consumer may resolve two
44
+ // copies of this package.
45
+ export const NO_WIDGET_FIELD_TYPES = [
46
+ "jsonb",
47
+ "embedded",
48
+ "files",
49
+ "images",
50
+ ];
@@ -0,0 +1,12 @@
1
+ export type FileHandle = {
2
+ readonly key: string;
3
+ read(): Promise<Uint8Array>;
4
+ write(data: Uint8Array, mimeType?: string): Promise<void>;
5
+ delete(): Promise<void>;
6
+ exists(): Promise<boolean>;
7
+ derive(suffix: string): FileHandle;
8
+ };
9
+ export type FileContext = {
10
+ ref(key: string): FileHandle;
11
+ list(prefix: string): Promise<readonly string[]>;
12
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { FileStorageProvider } from "./file-storage-provider-types.js";
2
+ import type { TenantId } from "./identifiers.js";
3
+ export type FileProviderResolver = (tenantId: TenantId) => Promise<FileStorageProvider>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ export type SignedUrlOptions = {
2
+ readonly contentDisposition?: string;
3
+ };
4
+ export type WriteStreamOptions = {
5
+ readonly mimeType?: string;
6
+ readonly contentLength?: number;
7
+ };
8
+ export type FileStorageProvider = {
9
+ write(key: string, data: Uint8Array, mimeType?: string): Promise<void>;
10
+ writeStream(key: string, source: AsyncIterable<Uint8Array>, options?: WriteStreamOptions): Promise<void>;
11
+ read(key: string): Promise<Uint8Array>;
12
+ readStream(key: string): AsyncIterable<Uint8Array>;
13
+ delete(key: string): Promise<void>;
14
+ exists(key: string): Promise<boolean>;
15
+ list(prefix: string): Promise<readonly string[]>;
16
+ getSignedUrl?(key: string, expiresInSeconds: number, options?: SignedUrlOptions): Promise<string>;
17
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ export type GeoCoordinates = {
2
+ readonly latitude: number;
3
+ readonly longitude: number;
4
+ };
5
+ export type GeoAddress = {
6
+ readonly street?: string;
7
+ readonly city?: string;
8
+ readonly region?: string;
9
+ readonly postalCode?: string;
10
+ readonly country?: string;
11
+ };
12
+ export type GeoTzProvider = {
13
+ /** Geo-coordinates → IANA zone (offline lat/lng → tz). */
14
+ readonly fromCoordinates: (coords: GeoCoordinates) => string | Promise<string>;
15
+ /** Optional: postal address → IANA zone (geocoding API provider). */
16
+ readonly fromAddress?: (address: GeoAddress) => string | Promise<string>;
17
+ };
@@ -10,23 +10,4 @@
10
10
  // zone, online). This split keeps the interface compatible with both
11
11
  // provider classes instead of forcing an address shape the offline case
12
12
  // can't serve at all.
13
-
14
- export type GeoCoordinates = {
15
- readonly latitude: number;
16
- readonly longitude: number;
17
- };
18
-
19
- export type GeoAddress = {
20
- readonly street?: string;
21
- readonly city?: string;
22
- readonly region?: string;
23
- readonly postalCode?: string;
24
- readonly country?: string;
25
- };
26
-
27
- export type GeoTzProvider = {
28
- /** Geo-coordinates → IANA zone (offline lat/lng → tz). */
29
- readonly fromCoordinates: (coords: GeoCoordinates) => string | Promise<string>;
30
- /** Optional: postal address → IANA zone (geocoding API provider). */
31
- readonly fromAddress?: (address: GeoAddress) => string | Promise<string>;
32
- };
13
+ export {};
@@ -0,0 +1,493 @@
1
+ import type { Redis } from "ioredis";
2
+ import type { ZodType } from "zod";
3
+ import type { ConfigAccessor, ConfigAccessorFactory, ConfigResolver } from "./config.js";
4
+ import type { DbConnection } from "./db-connection.js";
5
+ import type { DerivativesContext } from "./derivatives-types.js";
6
+ import type { EntityCache } from "./entity-cache.js";
7
+ import type { EventMetadata, WriteOrigin } from "./event-store-types.js";
8
+ import type { KumikoEventTypeMap } from "./event-type-map.js";
9
+ import type { FileContext } from "./file-handle-types.js";
10
+ import type { FileProviderResolver } from "./file-provider-resolver-types.js";
11
+ import type { GeoTzProvider } from "./geo-tz.js";
12
+ import type { Logger } from "./logger.js";
13
+ import type { Meter, MetricsHandle, Tracer } from "./observability/index.js";
14
+ import type { SearchAdapter } from "./search-adapter.js";
15
+ import type { TenantDb } from "./tenant-db-types.js";
16
+ import type { TzContext } from "./tz-context.js";
17
+ export type OpenToAllPersonalData = "tenant-members";
18
+ export type OpenToAllDeclaration = {
19
+ readonly reason: string;
20
+ readonly personalData?: OpenToAllPersonalData;
21
+ };
22
+ export type OpenToAllAccessRule = {
23
+ readonly openToAll: OpenToAllDeclaration;
24
+ };
25
+ export type RoleAccessPersonalData = "public-intake";
26
+ export type RoleAccessRule = {
27
+ readonly roles: readonly string[];
28
+ readonly personalData?: RoleAccessPersonalData;
29
+ };
30
+ export type AccessRule = RoleAccessRule | OpenToAllAccessRule;
31
+ export type EscapeHatchDeclaration = {
32
+ readonly reason: string;
33
+ };
34
+ export declare function isOpenToAllGranted(rule: AccessRule): boolean;
35
+ export declare function isUiAccessGranted(access: AccessRule | undefined, userRoles: readonly string[] | undefined): boolean;
36
+ export type SessionUserOrigin = "member-resolution";
37
+ export type SessionUser = {
38
+ readonly id: string;
39
+ readonly tenantId: TenantId;
40
+ readonly roles: readonly string[];
41
+ readonly timezone?: string;
42
+ readonly locale?: string;
43
+ readonly claims?: Readonly<Record<string, unknown>>;
44
+ readonly sid?: string;
45
+ readonly pat?: {
46
+ readonly tokenId: string;
47
+ readonly scopes: readonly string[];
48
+ readonly allowedQns: readonly string[];
49
+ };
50
+ readonly origin?: SessionUserOrigin;
51
+ };
52
+ export type ClaimKeyType = "string" | "number" | "boolean" | "string[]" | "object";
53
+ export type ClaimKeyJsType<T extends ClaimKeyType> = T extends "string" ? string : T extends "number" ? number : T extends "boolean" ? boolean : T extends "string[]" ? readonly string[] : T extends "object" ? Readonly<Record<string, unknown>> : never;
54
+ export type ClaimKeyDefinition = {
55
+ readonly shortName: string;
56
+ readonly qualifiedName: string;
57
+ readonly type: ClaimKeyType;
58
+ };
59
+ export type ClaimKeyHandle<T extends ClaimKeyType = ClaimKeyType> = {
60
+ readonly name: string;
61
+ readonly type: T;
62
+ };
63
+ export type AuthClaimsContext = {
64
+ readonly db: import("./tenant-db-types.js").TenantDb;
65
+ readonly queryAs: (user: SessionUser, qn: string, payload: unknown) => Promise<unknown>;
66
+ readonly config?: ConfigAccessor;
67
+ };
68
+ export type AuthClaimsFn = (user: SessionUser, ctx: AuthClaimsContext) => Promise<Record<string, unknown>>;
69
+ export type AuthClaimsHookDef = {
70
+ readonly featureName: string;
71
+ readonly fn: AuthClaimsFn;
72
+ readonly declaredKeys?: ReadonlySet<string>;
73
+ };
74
+ export type ActiveMembershipRejection = "not_a_member" | "principal_blocked" | "tenant_teardown";
75
+ export type ActiveMembership = {
76
+ readonly tenantId: TenantId;
77
+ readonly roles: readonly string[];
78
+ readonly tenantName?: string;
79
+ readonly tenantKey?: string;
80
+ };
81
+ export type ActiveMembershipResult = {
82
+ readonly kind: "active";
83
+ readonly membership: ActiveMembership;
84
+ } | {
85
+ readonly kind: "rejected";
86
+ readonly reason: ActiveMembershipRejection;
87
+ };
88
+ export type WriteEvent<TPayload = unknown> = {
89
+ readonly type: string;
90
+ readonly payload: TPayload;
91
+ readonly user: SessionUser;
92
+ };
93
+ export type QueryEvent<TPayload = unknown> = {
94
+ readonly type: string;
95
+ readonly payload: TPayload;
96
+ readonly user: SessionUser;
97
+ };
98
+ import type { WriteFailure } from "./write-error-info-types.js";
99
+ export type WriteResult<TData = unknown> = {
100
+ readonly isSuccess: true;
101
+ readonly data: TData;
102
+ } | WriteFailure;
103
+ import type { Registry } from "./feature.js";
104
+ import type { TenantId } from "./identifiers.js";
105
+ import type { UncheckedSystemDb } from "./tenant-db-types.js";
106
+ export type MemberReader = (userId: string, qn: string, payload: unknown) => Promise<unknown>;
107
+ export type JobTriggerEvent = {
108
+ readonly id: string;
109
+ readonly headers: NonNullable<EventMetadata["headers"]>;
110
+ };
111
+ export type JobRunnerRef = {
112
+ handleEvent(eventName: string, payload: Record<string, unknown>, user?: SessionUser, triggerEvent?: JobTriggerEvent): Promise<void>;
113
+ };
114
+ export type DispatchWriteRef = {
115
+ readonly write: (user: SessionUser, qn: string, payload: unknown, inheritedOrigin?: WriteOrigin) => Promise<WriteResult>;
116
+ readonly queryAs: (user: SessionUser, qn: string, payload: unknown, inheritedOrigin?: WriteOrigin) => Promise<unknown>;
117
+ readonly createMemberReader: (tenantId: TenantId) => MemberReader;
118
+ };
119
+ export type NotifyPriority = "critical" | "normal" | "low";
120
+ export type NotifyOptions = {
121
+ readonly to?: string | readonly string[] | {
122
+ readonly tenant: TenantId;
123
+ };
124
+ readonly route?: Readonly<Record<string, string>>;
125
+ readonly data?: Readonly<Record<string, unknown>>;
126
+ readonly priority?: NotifyPriority;
127
+ readonly idempotencyKey?: string;
128
+ readonly recipientId?: string;
129
+ };
130
+ export type NotifyFn = (notificationType: string, options: NotifyOptions) => Promise<void>;
131
+ export type NotifyFactory = (user: SessionUser, tenantId: TenantId) => NotifyFn;
132
+ export type EscapeHatchKind = "unsafe-raw" | "acknowledge-cross-tenant" | "global-write" | "identity-switch" | "unsafe-all-tenants";
133
+ export type EscapeHatchTarget = {
134
+ readonly id: string;
135
+ readonly tenantId: TenantId;
136
+ };
137
+ export type EscapeHatchUseEvent = {
138
+ readonly handler: string;
139
+ readonly kind: EscapeHatchKind;
140
+ readonly reason: string;
141
+ readonly tenantId: TenantId;
142
+ readonly actor: string;
143
+ readonly target?: EscapeHatchTarget;
144
+ };
145
+ export type EscapeHatchAuditSink = (event: EscapeHatchUseEvent) => Promise<void>;
146
+ export type EscapeHatchReporter = (kind: EscapeHatchKind, reason: string, target?: EscapeHatchTarget) => void;
147
+ type SharedContextFields = {
148
+ readonly redis?: Redis;
149
+ readonly jobRunner?: JobRunnerRef;
150
+ readonly configResolver?: ConfigResolver;
151
+ readonly config?: ConfigAccessor;
152
+ readonly _configAccessorFactory?: ConfigAccessorFactory;
153
+ readonly configEncryption?: import("./envelope-cipher-types.js").EnvelopeCipher;
154
+ readonly rateLimit?: import("./rate-limit-types.js").RateLimitResolver;
155
+ readonly searchAdapter?: SearchAdapter;
156
+ readonly files?: FileContext;
157
+ readonly derivatives?: DerivativesContext;
158
+ readonly _fileProviderResolver?: FileProviderResolver;
159
+ readonly entityCache?: EntityCache;
160
+ readonly notify?: NotifyFn;
161
+ readonly _notifyFactory?: NotifyFactory;
162
+ readonly _escapeHatchAuditSink?: EscapeHatchAuditSink;
163
+ readonly secrets?: import("./secrets-types.js").SecretsContext;
164
+ readonly masterKeyProvider?: import("./secrets-types.js").MasterKeyProvider;
165
+ readonly kms?: import("./kms-adapter-types.js").KmsAdapter;
166
+ readonly tracer?: Tracer;
167
+ readonly meter?: Meter;
168
+ readonly signal?: AbortSignal;
169
+ readonly effectiveFeatures?: (tenantId: TenantId) => ReadonlySet<string>;
170
+ readonly scheduleAfterCommit?: (hook: () => Promise<void>) => void;
171
+ readonly queryAsMember?: MemberReader;
172
+ };
173
+ export type AppContext = SharedContextFields & {
174
+ readonly db?: DbConnection | TenantDb;
175
+ readonly systemDb?: UncheckedSystemDb;
176
+ readonly registry?: Registry;
177
+ readonly systemUser?: SessionUser;
178
+ readonly log?: Logger;
179
+ readonly triggeredBy?: {
180
+ readonly id: string;
181
+ readonly tenantId: TenantId;
182
+ } | null;
183
+ /** Bei Job-Handler-Aufrufen die aus einem Event-Trigger heraus laufen
184
+ * (r.job mit `trigger: { on: ... }`): der Name des Handlers der das
185
+ * Event ausgelöst hat. Bei Multi-Trigger-Jobs (`on: [...]`) ist das
186
+ * die einzige Möglichkeit für den Handler zu wissen WELCHER Trigger
187
+ * gefeuert hat. Cron- und manual-Jobs lassen das Feld undefined. */
188
+ readonly triggerName?: string;
189
+ readonly _userId?: string | undefined;
190
+ readonly _handlerType?: string | undefined;
191
+ /** Optionaler Geo→Zone-Adapter. Wenn gesetzt (via buildServer-context oder
192
+ * runProdApp/runDevApp extraContext), reicht der Dispatcher ihn an
193
+ * ctx.tz.fromCoordinates / fromAddress weiter. Ohne Provider werfen diese. */
194
+ readonly geoTzProvider?: GeoTzProvider;
195
+ /** Tenant des aktuellen Pipeline-Calls. Wird vom Dispatcher beim Bauen
196
+ * des HandlerContext aus `user.tenantId` gespiegelt, damit lifecycle-
197
+ * pipeline + system-hooks den Wert ohne Zugriff auf user-Object haben.
198
+ * Sprint-8a Tier-Composition: `effectiveFeatures(ctx._tenantId)`-call
199
+ * in den hook-filter-Stellen. */
200
+ readonly _tenantId?: TenantId;
201
+ /** Boot-configured default locale (BCP-47). Last fallback in ctx.locale's
202
+ * Request-Locale → Boot-Default chain (dispatch-shared.ts) — used when
203
+ * the request carries no X-Locale header and no usable Accept-Language.
204
+ * Absent falls back to "en". */
205
+ readonly defaultLocale?: string;
206
+ };
207
+ export type HandlerContext<TMap extends object = KumikoEventTypeMap> = SharedContextFields & {
208
+ readonly db: TenantDb;
209
+ readonly dbOutsideTransaction: TenantDb | undefined;
210
+ readonly systemDb?: UncheckedSystemDb;
211
+ readonly registry: Registry;
212
+ /** Aktiver SessionUser des Handler-Aufrufs — Convenience-Alias zu
213
+ * `event.user`. Existiert weil Handler intuitiv `ctx.user.tenantId`
214
+ * schreiben (Context = "kennt seinen User") und der Pfad sonst nur
215
+ * über `event.user` läuft, was typo-anfällig ist und stillschweigend
216
+ * zu `internal_error` führt wenn der falsche Pfad gewählt wird.
217
+ * Identisch zum event.user-Wert; Identity-Switches nutzen
218
+ * weiterhin queryAs/writeAs. */
219
+ readonly user: SessionUser;
220
+ readonly systemUser?: SessionUser;
221
+ readonly log?: Logger;
222
+ readonly triggeredBy?: {
223
+ readonly id: string;
224
+ readonly tenantId: TenantId;
225
+ } | null;
226
+ readonly _userId?: string | undefined;
227
+ readonly _handlerType?: string | undefined;
228
+ readonly includeDeleted?: boolean;
229
+ readonly runPreSave?: (handlerName: string, changes: Record<string, unknown>, previous: Readonly<Record<string, unknown>>, isNew: boolean) => Promise<Record<string, unknown>>;
230
+ readonly query: (qn: string, payload: unknown) => Promise<unknown>;
231
+ readonly queryAs: (user: SessionUser, qn: string, payload: unknown) => Promise<unknown>;
232
+ readonly write: (qn: string, payload: unknown) => Promise<WriteResult>;
233
+ readonly writeAs: (user: SessionUser, qn: string, payload: unknown) => Promise<WriteResult>;
234
+ readonly hasFeature: (featureName: string) => Promise<boolean>;
235
+ readonly appendEvent: AppendEventFn<TMap>;
236
+ readonly unsafeAppendEvent: UnsafeAppendEventFn;
237
+ readonly tryAppendEvent: TryAppendEventFn;
238
+ readonly fetchForWriting: (args: FetchForWritingArgs) => Promise<AggregateStreamHandle>;
239
+ readonly loadAggregate: (aggregateId: string, options?: {
240
+ readonly asOf?: Temporal.Instant;
241
+ }) => Promise<readonly import("./event-store-types.js").StoredEvent[]>;
242
+ readonly archiveStream: (aggregateId: string, args: {
243
+ readonly aggregateType: string;
244
+ readonly reason?: string;
245
+ }) => Promise<void>;
246
+ readonly restoreStream: (aggregateId: string) => Promise<void>;
247
+ readonly isStreamArchived: (aggregateId: string) => Promise<boolean>;
248
+ readonly snapshotAggregate: (args: {
249
+ readonly aggregateId: string;
250
+ readonly aggregateType: string;
251
+ readonly version: number;
252
+ readonly state: Record<string, unknown>;
253
+ readonly snapshotVersion?: number;
254
+ }) => Promise<void>;
255
+ readonly loadAggregateWithSnapshot: <TState extends Record<string, unknown>>(aggregateId: string, reducer: import("./snapshot-types.js").SnapshotReducer<TState>, initial: TState, options?: Omit<import("./snapshot-types.js").LoadAggregateWithSnapshotOptions, "upcastEvent">) => Promise<import("./snapshot-types.js").LoadAggregateWithSnapshotResult<TState>>;
256
+ readonly queryProjection: <T = Record<string, unknown>>(qualifiedName: string, options?: {
257
+ readonly unsafeAllTenants?: boolean;
258
+ }) => Promise<readonly T[]>;
259
+ readonly metrics: MetricsHandle;
260
+ readonly metricsFor: (featureName: string) => MetricsHandle;
261
+ readonly tracer: Tracer;
262
+ readonly tz: TzContext;
263
+ readonly locale: string;
264
+ readonly resolveAuthClaims: (user: SessionUser) => Promise<Record<string, unknown>>;
265
+ readonly resolveActiveMembership: (userId: string, tenantId: TenantId) => Promise<ActiveMembershipResult>;
266
+ readonly queryAsMember: MemberReader;
267
+ };
268
+ export type JobContext = SharedContextFields & {
269
+ readonly db: TenantDb;
270
+ readonly registry: Registry;
271
+ readonly systemUser: SessionUser;
272
+ readonly log: Logger;
273
+ readonly triggeredBy: {
274
+ readonly id: string;
275
+ readonly tenantId: TenantId;
276
+ } | null;
277
+ readonly attempt: number;
278
+ readonly finalAttempt: boolean;
279
+ readonly systemDb?: UncheckedSystemDb;
280
+ readonly write: (qn: string, payload: unknown) => Promise<WriteResult>;
281
+ readonly writeAs: (user: SessionUser, qn: string, payload: unknown) => Promise<WriteResult>;
282
+ readonly queryAs: (user: SessionUser, qn: string, payload: unknown) => Promise<unknown>;
283
+ readonly queryAsMember: MemberReader;
284
+ readonly triggerName?: string;
285
+ readonly triggerEvent?: JobTriggerEvent;
286
+ readonly _tenantId?: TenantId;
287
+ readonly _userId?: string | undefined;
288
+ };
289
+ export type WriteHandlerFn<TPayload = unknown, TData = unknown> = (event: WriteEvent<TPayload>, context: HandlerContext) => Promise<WriteResult<TData>>;
290
+ export type QueryHandlerFn<TPayload = unknown, TResult = unknown> = (query: QueryEvent<TPayload>, context: HandlerContext) => Promise<TResult>;
291
+ export type StreamHandlerFn<TPayload = unknown, TChunk = unknown> = (query: QueryEvent<TPayload>, context: HandlerContext) => AsyncGenerator<TChunk>;
292
+ /**
293
+ * Compile-time mirror of `engine/qualified-name.ts:toKebab` for camelCase
294
+ * → kebab-case. Drives the literal-type of `EventDef.name`, so that
295
+ * `r.defineEvent("foo", schema)` inside `defineFeature("driverOrders")`
296
+ * carries `name: "driver-orders:event:foo"` as a literal — strict-mode
297
+ * for `ctx.appendEvent({ type: eventDef.name, ... })` lights up.
298
+ *
299
+ * Algorithm mirrors the runtime regex pipeline:
300
+ * 1. `.` → `-` (dot acts as word-boundary)
301
+ * 2. Insert `-` between `[A-Z]+` and `[A-Z][a-z]` (so `SSEFoo` →
302
+ * `SSE-Foo`, splitting an uppercase run before a camel-hump)
303
+ * 3. Insert `-` between `[a-z0-9]` and `[A-Z]` (camelCase boundary,
304
+ * so `ticketAssigned` → `ticket-Assigned`)
305
+ * 4. lowercase everything
306
+ *
307
+ * Implemented as a state machine with one-char lookahead. State:
308
+ * - "start" — at start of string, or right after a dot-boundary
309
+ * - "upper" — last emitted char came from an uppercase letter
310
+ * - "post-letter" — last emitted char was a lowercase letter or digit
311
+ *
312
+ * Sync vs runtime is verified by `engine/__tests__/camel-to-kebab.test-d.ts`
313
+ * — the type-tests cross-check identical inputs against `toKebab()`.
314
+ */
315
+ export type CamelToKebab<S extends string> = CamelToKebabImpl<S, "start", "">;
316
+ type CamelToKebabImpl<S extends string, Prev extends "start" | "upper" | "post-letter", Acc extends string> = S extends `${infer C}${infer Rest}` ? CharKind<C> extends "upper" ? Prev extends "start" ? CamelToKebabImpl<Rest, "upper", `${Acc}${Lowercase<C>}`> : Prev extends "post-letter" ? CamelToKebabImpl<Rest, "upper", `${Acc}-${Lowercase<C>}`> : Rest extends `${infer Next}${string}` ? CharKind<Next> extends "lower" ? CamelToKebabImpl<Rest, "upper", `${Acc}-${Lowercase<C>}`> : CamelToKebabImpl<Rest, "upper", `${Acc}${Lowercase<C>}`> : `${Acc}${Lowercase<C>}` : CharKind<C> extends "lower" ? CamelToKebabImpl<Rest, "post-letter", `${Acc}${C}`> : C extends "." ? CamelToKebabImpl<Rest, "start", `${Acc}-`> : CamelToKebabImpl<Rest, "post-letter", `${Acc}${C}`> : Acc;
317
+ /**
318
+ * Three-way classification used by `CamelToKebab`:
319
+ * - "lower" — a lowercase letter (a-z and Unicode lowercase)
320
+ * - "upper" — an uppercase letter (A-Z and Unicode uppercase)
321
+ * - "non-letter" — digit, dot, dash, etc. (Lowercase==Uppercase for them)
322
+ */
323
+ type CharKind<C extends string> = C extends Lowercase<C> ? (C extends Uppercase<C> ? "non-letter" : "lower") : "upper";
324
+ /**
325
+ * Builds the qualified event-name from feature + inner-name in the same
326
+ * shape the runtime emits via `qn(toKebab(feature), "event", toKebab(inner))`.
327
+ */
328
+ export type QualifiedEventName<TFeature extends string, TInner extends string> = `${CamelToKebab<TFeature>}:event:${CamelToKebab<TInner>}`;
329
+ export type EventPiiAbsentSubject = "plaintext" | "tenant";
330
+ export type EventPiiSubject = {
331
+ readonly personal: {
332
+ readonly of: string;
333
+ readonly whenAbsent?: EventPiiAbsentSubject;
334
+ };
335
+ } | {
336
+ readonly personal: "tenant";
337
+ } | {
338
+ readonly personal: "self";
339
+ } | {
340
+ /** @deprecated use `{ personal: { of: "<ownerField>" } }` instead. */
341
+ readonly subjectField: string;
342
+ };
343
+ export type EventPiiFields = Readonly<Record<string, EventPiiSubject>>;
344
+ export type NormalizedEventPiiSubject = {
345
+ readonly kind: "user";
346
+ readonly ownerField: string;
347
+ readonly whenAbsent: EventPiiAbsentSubject | undefined;
348
+ } | {
349
+ readonly kind: "tenant";
350
+ } | {
351
+ readonly kind: "self";
352
+ };
353
+ export declare function normalizeEventPiiSubject(spec: EventPiiSubject): NormalizedEventPiiSubject;
354
+ export type EventPiiStance = EventPiiFields | "none";
355
+ export type EventDef<TPayload = unknown, TName extends string = string> = {
356
+ readonly name: TName;
357
+ readonly schema: ZodType<TPayload>;
358
+ readonly version: number;
359
+ readonly piiFields?: EventPiiStance;
360
+ };
361
+ export type AppendEventArgs = {
362
+ readonly aggregateId: string;
363
+ readonly aggregateType: string;
364
+ readonly type: string;
365
+ readonly payload: unknown;
366
+ readonly headers?: Readonly<Record<string, string | number | boolean>>;
367
+ };
368
+ export type TypedAppendEventArgs<TMap extends object, K extends keyof TMap> = {
369
+ readonly aggregateId: string;
370
+ readonly aggregateType: string;
371
+ readonly type: K;
372
+ readonly payload: TMap[K];
373
+ readonly headers?: Readonly<Record<string, string | number | boolean>>;
374
+ };
375
+ export type AppendEventFn<TMap extends object = KumikoEventTypeMap> = <K extends keyof TMap>(args: TypedAppendEventArgs<TMap, K>) => Promise<void>;
376
+ export type UnsafeAppendEventFn = (args: AppendEventArgs) => Promise<void>;
377
+ export type TryAppendEventResult = {
378
+ readonly ok: true;
379
+ readonly event: import("./event-store-types.js").StoredEvent;
380
+ } | {
381
+ readonly ok: false;
382
+ readonly conflict: import("./event-store-types.js").VersionConflict;
383
+ };
384
+ export type TryAppendEventFn = (args: AppendEventArgs) => Promise<TryAppendEventResult>;
385
+ export type FetchForWritingArgs = {
386
+ readonly aggregateId: string;
387
+ readonly aggregateType: string;
388
+ readonly expectedVersion?: number;
389
+ };
390
+ export type AggregateStreamHandle = {
391
+ readonly events: readonly import("./event-store-types.js").StoredEvent[];
392
+ readonly version: number;
393
+ readonly appendOne: (args: {
394
+ readonly type: string;
395
+ readonly payload: unknown;
396
+ }) => Promise<void>;
397
+ readonly hasEvent: (type: string) => boolean;
398
+ };
399
+ export type EventUpcastCtx = {
400
+ readonly db: import("./db-connection.js").DbRunner;
401
+ readonly tenantId: import("./identifiers.js").TenantId;
402
+ };
403
+ export type EventUpcastFn = (payload: unknown, ctx: EventUpcastCtx) => unknown | Promise<unknown>;
404
+ export type DeclarativeEventMigration = {
405
+ readonly rename?: Readonly<Record<string, string>>;
406
+ readonly default?: Readonly<Record<string, unknown>>;
407
+ readonly map?: Readonly<Record<string, (value: unknown) => unknown>>;
408
+ };
409
+ export type EventMigrationDef = {
410
+ readonly eventName: string;
411
+ readonly fromVersion: number;
412
+ readonly toVersion: number;
413
+ readonly transform: EventUpcastFn;
414
+ };
415
+ export type NameOrRef = string | {
416
+ readonly name: string;
417
+ };
418
+ export type EntityRef = {
419
+ readonly name: string;
420
+ readonly table: string;
421
+ };
422
+ export type HandlerRef = {
423
+ readonly name: string;
424
+ };
425
+ export type RateLimitPer = "user" | "tenant" | "ip" | "user+handler" | "tenant+handler" | "ip+handler";
426
+ export type RateLimitOption = {
427
+ readonly per: RateLimitPer;
428
+ readonly limit: number;
429
+ readonly windowSeconds: number;
430
+ readonly cost?: number;
431
+ };
432
+ export type RateLimitDisabled = {
433
+ readonly disabled: true;
434
+ readonly reason: string;
435
+ };
436
+ export type RateLimitDeclaration = RateLimitOption | RateLimitDisabled;
437
+ export declare function isRateLimitDisabled(v: RateLimitDeclaration | undefined): v is RateLimitDisabled;
438
+ export type AgentRisk = "low" | "mid" | "high";
439
+ /** Per-handler hints for the AI-agent manifest. `expose` overrides the
440
+ * default derived from `description`; `risk` overrides the per-kind default. */
441
+ export type AgentHandlerHints = {
442
+ readonly expose?: boolean;
443
+ readonly risk?: AgentRisk;
444
+ };
445
+ export type AgentExposure = {
446
+ readonly expose: boolean;
447
+ readonly risk: AgentRisk;
448
+ };
449
+ export type WriteHandlerDef = {
450
+ readonly name: string;
451
+ readonly schema: ZodType;
452
+ readonly handler: WriteHandlerFn;
453
+ readonly access: AccessRule;
454
+ readonly description?: string;
455
+ readonly agent?: AgentHandlerHints;
456
+ readonly unsafeSkipTransitionGuard?: boolean;
457
+ readonly rateLimit?: RateLimitDeclaration;
458
+ readonly escapeHatch?: EscapeHatchDeclaration;
459
+ readonly perform?: import("./step.js").PipelineDef;
460
+ };
461
+ export declare const ENTITY_CONVENTION_QUERY_BRAND = "__kumikoEntityConventionQuery";
462
+ export type QueryHandlerDef = {
463
+ readonly name: string;
464
+ readonly schema: ZodType;
465
+ readonly handler: QueryHandlerFn;
466
+ /** Set only by defineEntityQueryHandler, which wires the parent-ref
467
+ * read-gate. The boot-validator requires it on a `parentRef` entity's
468
+ * list/detail handler — see boot-validator/parent-ref.ts. */
469
+ readonly [ENTITY_CONVENTION_QUERY_BRAND]?: true;
470
+ readonly access: AccessRule;
471
+ readonly description?: string;
472
+ readonly agent?: AgentHandlerHints;
473
+ readonly rateLimit?: RateLimitDeclaration;
474
+ /** Zod schema of the handler's actual return value — the paged envelope
475
+ * `{ rows, nextCursor, total? }` for a `definePagedQueryHandler`, or the
476
+ * flat record (optionally `.nullable()`) for a plain query handler.
477
+ * Optional and purely additive: absent on every existing handler, and
478
+ * the boot-validator skips any column-reference check that would need
479
+ * it (screens.ts projectionList/relatedList `columns`, projectionDetail
480
+ * `header`/`metrics`, dashboard `valueField`/`subField`/etc.) rather
481
+ * than requiring it retroactively. See fw#2493. */
482
+ readonly outputSchema?: ZodType;
483
+ readonly escapeHatch?: EscapeHatchDeclaration;
484
+ };
485
+ export type StreamHandlerDef = {
486
+ readonly name: string;
487
+ readonly schema: ZodType;
488
+ readonly handler: StreamHandlerFn;
489
+ readonly access: AccessRule;
490
+ readonly rateLimit?: RateLimitDeclaration;
491
+ readonly escapeHatch?: EscapeHatchDeclaration;
492
+ };
493
+ export {};