@cosmicdrift/kumiko-types 0.327.0 → 0.328.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.
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 +360 -121
  119. package/src/changes.json +12 -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
@@ -1,138 +0,0 @@
1
- import type * as z from "zod";
2
- import type { ZodType } from "zod";
3
- import type { KumikoEventTypeMap } from "./event-type-map";
4
- import type {
5
- AccessRule,
6
- AgentHandlerHints,
7
- EscapeHatchDeclaration,
8
- HandlerContext,
9
- QueryEvent,
10
- RateLimitDeclaration,
11
- WriteEvent,
12
- WriteResult,
13
- } from "./handlers";
14
- import type { PipelineDef } from "./step";
15
-
16
- // --- Write Handler Definition ---
17
- //
18
- // TMap propagates the strict event-type-map through the handler's
19
- // HandlerContext. CRITICAL: TMap is declared as a generic parameter on the
20
- // FUNCTION (defineWriteHandler), not just on the type. Generic-functions
21
- // substitute TMap at the USE-site (the caller's compile context, where
22
- // the augmentation is visible); generic-type-aliases substitute at the
23
- // definition-site (framework's compile, where the augmentation isn't
24
- // visible) and collapse `keyof TMap` to `never`. See the spike-findings
25
- // memory for the empirical proof.
26
- //
27
- // Two authoring forms — `handler` (free-form) or `perform: stepsPipeline(...)`
28
- // (step-pipeline). A `perform` is compiled to a handler-function at
29
- // definition time; the dispatcher only ever sees `handler`.
30
-
31
- export type WriteHandlerDefinition<
32
- TName extends string = string,
33
- TSchema extends ZodType = ZodType,
34
- TData = unknown,
35
- TMap extends object = KumikoEventTypeMap,
36
- > = {
37
- readonly name: TName;
38
- readonly schema: TSchema;
39
- readonly access: AccessRule;
40
- readonly description?: string;
41
- readonly agent?: AgentHandlerHints;
42
- readonly unsafeSkipTransitionGuard?: boolean;
43
- readonly rateLimit?: RateLimitDeclaration;
44
- readonly escapeHatch?: EscapeHatchDeclaration;
45
- readonly handler: (
46
- event: WriteEvent<z.infer<TSchema>>,
47
- context: HandlerContext<TMap>,
48
- ) => Promise<WriteResult<TData>>;
49
- // Preserved when the author wrote a `perform` block — the original
50
- // PipelineDef. Designer/AI/AST tools read this when present; the
51
- // dispatcher ignores it and just calls `handler`. Absent on free-form
52
- // handlers.
53
- readonly perform?: PipelineDef<z.infer<TSchema>, TData>;
54
- };
55
-
56
- // Author-facing input — accepts either the free-form `handler` or the
57
- // pipeline-form `perform`. defineWriteHandler narrows them to the
58
- // canonical WriteHandlerDefinition shape.
59
- export type WriteHandlerInput<
60
- TName extends string = string,
61
- TSchema extends ZodType = ZodType,
62
- TData = unknown,
63
- TMap extends object = KumikoEventTypeMap,
64
- > = {
65
- readonly name: TName;
66
- readonly schema: TSchema;
67
- readonly access: AccessRule;
68
- readonly description?: string;
69
- readonly agent?: AgentHandlerHints;
70
- readonly unsafeSkipTransitionGuard?: boolean;
71
- readonly rateLimit?: RateLimitDeclaration;
72
- readonly escapeHatch?: EscapeHatchDeclaration;
73
- } & (
74
- | {
75
- readonly handler: (
76
- event: WriteEvent<z.infer<TSchema>>,
77
- context: HandlerContext<TMap>,
78
- ) => Promise<WriteResult<TData>>;
79
- readonly perform?: never;
80
- }
81
- | {
82
- readonly perform: PipelineDef<z.infer<TSchema>, TData>;
83
- readonly handler?: never;
84
- }
85
- );
86
-
87
- // --- Query Handler Definition ---
88
-
89
- export type QueryHandlerDefinition<
90
- TName extends string = string,
91
- TSchema extends ZodType = ZodType,
92
- TResult = unknown,
93
- TMap extends object = KumikoEventTypeMap,
94
- > = {
95
- readonly name: TName;
96
- readonly schema: TSchema;
97
- readonly access: AccessRule;
98
- readonly description?: string;
99
- readonly agent?: AgentHandlerHints;
100
- readonly rateLimit?: RateLimitDeclaration;
101
- readonly escapeHatch?: EscapeHatchDeclaration;
102
- readonly handler: (
103
- query: QueryEvent<z.infer<TSchema>>,
104
- context: HandlerContext<TMap>,
105
- ) => Promise<TResult>;
106
- /** Zod schema of `handler`'s actual return value — see QueryHandlerDef's
107
- * doc (handlers.ts) for the boot-validator checks this unlocks. Not
108
- * inferred from `TResult`: TResult is a compile-time-only type param
109
- * (this function never receives a runtime schema for it), so callers
110
- * that want boot-time column checks declare `outputSchema` explicitly,
111
- * same as `schema` for the input side. */
112
- readonly outputSchema?: ZodType;
113
- };
114
-
115
- // --- Stream Handler Definition ---
116
- //
117
- // Scaffolding only (#1376) — access/rateLimit read by the boot-validator
118
- // (#1377), dispatch-time consumption (async-generator, SSE) lands in #1378.
119
-
120
- export type StreamHandlerDefinition<
121
- TName extends string = string,
122
- TSchema extends ZodType = ZodType,
123
- TChunk = unknown,
124
- TMap extends object = KumikoEventTypeMap,
125
- > = {
126
- readonly name: TName;
127
- readonly schema: TSchema;
128
- readonly access: AccessRule;
129
- readonly rateLimit?: RateLimitDeclaration;
130
- // Stream handlers can't reach db.global() (that gate is write-only), but
131
- // they can still switch identity to SYSTEM via ctx.queryAs — this opts
132
- // in, same contract as WriteHandlerDefinition.escapeHatch.
133
- readonly escapeHatch?: EscapeHatchDeclaration;
134
- readonly handler: (
135
- query: QueryEvent<z.infer<TSchema>>,
136
- context: HandlerContext<TMap>,
137
- ) => AsyncGenerator<TChunk>;
138
- };
@@ -1,106 +0,0 @@
1
- // Derived-file-variants (thumbnails, resized/reformatted images, …) — pure
2
- // types, no runtime logic. Client-visible package: no `node:*` imports.
3
-
4
- export type VariantFit = "cover" | "inside" | "contain";
5
- export type VariantFormat = "webp" | "avif" | "jpeg";
6
-
7
- // Rectangle in relative coordinates (0…1 of width/height) so it survives a
8
- // resize. Burning blur into plates/faces needs coordinates that only exist at
9
- // runtime (detection + user correction), so they ride in the spec instead of a
10
- // field declaration — the spec hash keys the cache, so corrected regions
11
- // automatically yield a fresh URL.
12
- export type BlurRegion = {
13
- readonly x: number;
14
- readonly y: number;
15
- readonly width: number;
16
- readonly height: number;
17
- };
18
-
19
- export type OverlayGravity = "north-west" | "north-east" | "south-west" | "south-east" | "center";
20
-
21
- // Placement is relative to the OUTPUT box (after resize), so one declaration
22
- // covers every aspect ratio the same source is rendered into.
23
- type OverlayPlacement = {
24
- // Layer width as a fraction (0…1) of the output width; height follows the
25
- // layer's own aspect ratio.
26
- readonly widthPct: number;
27
- readonly gravity: OverlayGravity;
28
- // Inset from the edges, fraction of output width. Ignored for "center".
29
- readonly marginPct?: number;
30
- };
31
-
32
- export type OverlayLayer =
33
- // `dataToken` is NOT the QR payload — it names a value an
34
- // EXT_DERIVATIVE_OVERLAY_RESOLVER registration resolves per FileRef. A
35
- // literal payload is deliberately not expressible: the public variant route
36
- // is anonymous, so a caller-supplied target would make it an open image
37
- // generator for arbitrary URLs.
38
- | ({ readonly kind: "qr"; readonly dataToken: string } & OverlayPlacement)
39
- // Caller-supplied raster (watermark/badge), base64 in the declaration.
40
- // Swapping the image changes the spec hash and invalidates every derivative
41
- // that used it — no extra bookkeeping.
42
- | ({ readonly kind: "image"; readonly imageBase64: string } & OverlayPlacement);
43
-
44
- // Renderer-facing counterpart of OverlayLayer once derivatives-context has
45
- // resolved every `dataToken` — a `qr` layer carries the actual value to
46
- // encode instead of a name a resolver still has to look up. Keeping this a
47
- // distinct type (not a value-replacement on OverlayLayer itself) means a
48
- // renderer's input type structurally cannot hold an unresolved token.
49
- export type ResolvedOverlayLayer =
50
- | ({ readonly kind: "qr"; readonly data: string } & OverlayPlacement)
51
- | Extract<OverlayLayer, { kind: "image" }>;
52
-
53
- export type VariantSpec = {
54
- // Default "inside" when omitted (renderer-side default, Schnitt 2).
55
- readonly fit?: VariantFit;
56
- readonly size?: { readonly width: number; readonly height: number };
57
- // Alternative to `size` — longest edge in pixels, aspect preserved.
58
- readonly maxEdge?: number;
59
- readonly format?: VariantFormat;
60
- readonly quality?: number;
61
- // Whole-image blur radius.
62
- readonly blur?: number;
63
- readonly blurRegions?: readonly BlurRegion[];
64
- // Composited AFTER resize, in array order (last layer on top).
65
- readonly overlays?: readonly OverlayLayer[];
66
- // Framework-internal: derivatives-context.ts fills this in from `overlays`
67
- // once every dataToken is resolved. A renderer reads only this field, so a
68
- // token can never reach it, even by accident.
69
- readonly resolvedOverlays?: readonly ResolvedOverlayLayer[];
70
- };
71
-
72
- // A renderer turns the original bytes + a spec into the derived bytes for one
73
- // variant. Registered per MIME-type (exact or `<type>/*` wildcard) via the
74
- // `derivativeRenderer` extension point — see EXT_DERIVATIVE_RENDERER.
75
- //
76
- // The renderer must produce `spec.format` when set, and the source's own
77
- // format otherwise. It never reports back what it produced: the caller
78
- // derives the output mimeType from the spec plus the source FileRef's
79
- // mimeType (see outputMimeType in derivatives-context.ts), because a cache
80
- // hit has no renderer run to read a mimeType off. When `spec.format` is
81
- // unset, the source mimeType is client-controlled, so outputMimeType
82
- // allowlists it against known-safe raster types instead of passing it
83
- // through verbatim (#2021).
84
- export type DerivativeRendererPlugin = {
85
- readonly render: (
86
- input: Uint8Array,
87
- spec: VariantSpec,
88
- sourceMimeType: string,
89
- ) => Promise<Uint8Array>;
90
- };
91
-
92
- export type VariantResult = {
93
- readonly storageKey: string;
94
- readonly mimeType: string;
95
- // true = rendered during this call, false = an existing derivative was
96
- // found and returned unchanged.
97
- readonly rendered: boolean;
98
- };
99
-
100
- // The `ctx.derivatives` service — derive-on-first-use variants of a tracked
101
- // FileRef. `name` feeds only the readable key-prefix; `spec` determines the
102
- // content hash, so a spec change always produces a fresh URL instead of
103
- // silently overwriting what's cached under the old pixels.
104
- export type DerivativesContext = {
105
- readonly variant: (fileRefId: string, spec: VariantSpec, name: string) => Promise<VariantResult>;
106
- };
@@ -1,35 +0,0 @@
1
- import type { EntityId, TenantId } from "./identifiers";
2
-
3
- export type EntityCache = {
4
- /** Get a single cached entity. Returns null on miss. */
5
- get(
6
- tenantId: TenantId,
7
- entityName: string,
8
- id: EntityId,
9
- ): Promise<Record<string, unknown> | null>;
10
-
11
- /** Get multiple cached entities. Returns a Map of id → data (misses are absent). */
12
- mget(
13
- tenantId: TenantId,
14
- entityName: string,
15
- ids: readonly EntityId[],
16
- ): Promise<Map<EntityId, Record<string, unknown>>>;
17
-
18
- /** Cache a single entity. */
19
- set(
20
- tenantId: TenantId,
21
- entityName: string,
22
- id: EntityId,
23
- data: Record<string, unknown>,
24
- ): Promise<void>;
25
-
26
- /** Cache multiple entities at once. */
27
- mset(
28
- tenantId: TenantId,
29
- entityName: string,
30
- entries: ReadonlyArray<{ id: EntityId; data: Record<string, unknown> }>,
31
- ): Promise<void>;
32
-
33
- /** Invalidate a single cached entity. */
34
- del(tenantId: TenantId, entityName: string, id: EntityId): Promise<void>;
35
- };
@@ -1,68 +0,0 @@
1
- import type { EntityDefinition } from "./fields";
2
- import type {
3
- AccessRule,
4
- AgentHandlerHints,
5
- EscapeHatchDeclaration,
6
- QueryHandlerDef,
7
- WriteHandlerDef,
8
- } from "./handlers";
9
-
10
- export type EntityHandlerOptions = {
11
- readonly access: AccessRule;
12
- readonly description?: string;
13
- readonly agent?: AgentHandlerHints;
14
- /** Lifts row filtering for this ONE handler across every tenant instead of
15
- * the caller's own — for a SystemAdmin-only operator handler over an
16
- * otherwise tenant-scoped entity. Every use reports an
17
- * `acknowledge-cross-tenant` escape-hatch audit event. On write handlers
18
- * update/delete/restore address the target row's own tenant stream.
19
- * `access` stays the only caller gate. Unlike `escapeHatch` on a
20
- * hand-written handler this does NOT grant `ctx.db.unsafeRaw`,
21
- * `db.global()` writes or identity switches. */
22
- readonly escapeHatch?: EscapeHatchDeclaration;
23
- /** @deprecated Use `escapeHatch: { reason }` — removed in a future release;
24
- * run `scripts/codemod/migrate-cross-tenant.ts`. */
25
- readonly crossTenant?: boolean;
26
- };
27
-
28
- /** Options for the generic create/update handlers. */
29
- export type EntityWriteHandlerOptions = EntityHandlerOptions & {
30
- /** Fields this handler never writes. They leave the payload schema as
31
- * "must be absent": a payload that still carries one fails validation
32
- * instead of being stripped silently. create rejects a required field
33
- * without default here, since the row could never be created. */
34
- readonly excludeFields?: readonly string[];
35
- };
36
-
37
- export type EntityQueryHandlerOptions = EntityHandlerOptions;
38
-
39
- export type EntityCrudVerb = "create" | "update" | "delete" | "restore" | "list" | "detail";
40
-
41
- // `access` stays optional here — registerEntityCrud resolves it per-verb from `verbAccess`, falling back to this default.
42
- export type EntityCrudHandlerDefaults = Omit<EntityHandlerOptions, "access"> & {
43
- readonly access?: AccessRule;
44
- };
45
-
46
- export type RegisterEntityCrudOptions = {
47
- readonly write?: EntityCrudHandlerDefaults;
48
- readonly read?: EntityCrudHandlerDefaults;
49
- readonly verbs?: Partial<Record<EntityCrudVerb, boolean>>;
50
- /** Per-verb access override — falls back to `write.access`/`read.access` when unset for a verb. */
51
- readonly verbAccess?: Partial<Record<EntityCrudVerb, AccessRule>>;
52
- /** Per-verb `description` — the author writes one sentence per verb; the AI-agent
53
- * manifest exposes only the verbs described here (fail-closed, same rule as
54
- * hand-written handlers). Falls back to `write.description`/`read.description`. */
55
- readonly descriptions?: Partial<Record<EntityCrudVerb, string>>;
56
- /** Per-verb `excludeFields` for the generic create/update handlers — see
57
- * EntityWriteHandlerOptions. */
58
- readonly excludeFields?: Partial<Record<"create" | "update", readonly string[]>>;
59
- /** Default true. Set false when the entity was already registered (e.g. before r.relation). */
60
- readonly registerEntity?: boolean;
61
- };
62
-
63
- /** Minimal registrar surface — keeps entity-handlers free of define-feature imports. */
64
- export type EntityCrudRegistrar = {
65
- entity(name: string, definition: EntityDefinition): unknown;
66
- writeHandler(def: WriteHandlerDef): unknown;
67
- queryHandler(def: QueryHandlerDef): unknown;
68
- };
@@ -1,101 +0,0 @@
1
- // Plain-data types for EntityTableMeta — split from the runtime
2
- // (deriveEntityTableMeta, resolveTableName, defineUnmanagedTable) in
3
- // entity-table-meta.ts. Prep step for the types-only package extraction
4
- // (#1283) — this file must have ONLY `import type`, no value imports
5
- // (crypto/DB deps).
6
-
7
- import type { EntityRelations } from "./relations";
8
- import type { EntityTenancy } from "./tenancy-brand";
9
-
10
- // PG type repertoire the read-model tables need. Deliberately narrow — no
11
- // vendor-specific types (TSVECTOR, HSTORE, etc.). An app-author who needs
12
- // those reaches into the reviewed SQL migration by hand, not the generator.
13
- export type PgType =
14
- | "uuid"
15
- | "text"
16
- | "boolean"
17
- | "integer"
18
- | "double precision"
19
- | "bigint"
20
- | "serial"
21
- | "bigserial"
22
- | "jsonb"
23
- | "timestamptz"
24
- | "timestamptz(3)"
25
- // Calendar day, no time-of-day/timezone component — Temporal.PlainDate.
26
- // Distinct from timestamptz: a `date` field is a pure calendar concept
27
- // (invoice date, lease term) and must never round-trip through an Instant.
28
- | "date"
29
- // Exact decimal — precision/scale are encoded in the type string so the
30
- // DDL renderer and read-coercion need no side-channel metadata.
31
- | `numeric(${number},${number})`;
32
-
33
- export type ColumnMeta = {
34
- readonly name: string; // snake_case PG column name
35
- readonly pgType: PgType;
36
- readonly notNull: boolean;
37
- // Raw SQL-default-expression (e.g. `now()`, `gen_random_uuid()`,
38
- // `'[]'::jsonb`). undefined = no DEFAULT clause.
39
- readonly defaultSql?: string;
40
- readonly primaryKey?: boolean;
41
- readonly identity?: boolean;
42
- // bigint/bigserial only: JS round-trip mode. `number` = createBigIntField /
43
- // drizzle mode:"number" (safe ≤2^53). `bigint` = money cents, raw unmanaged.
44
- readonly bigintJsMode?: "number" | "bigint";
45
- };
46
-
47
- export type IndexMeta = {
48
- readonly name: string;
49
- readonly columns: readonly string[]; // snake_case PG column names
50
- readonly unique?: boolean;
51
- // Raw SQL-where-expression for partial indexes. Caller is responsible
52
- // for safety — emitted verbatim.
53
- readonly whereSql?: string;
54
- // Set when the EntityDefinition has a partial index (def.where as a
55
- // drizzle SQL AST) the generator can't reliably render. The renderer
56
- // emits the statement COMMENTED OUT with a warning hint — the app-author
57
- // has to add the WHERE manually in the generated SQL.
58
- readonly needsManualWhere?: boolean;
59
- };
60
-
61
- export type CompositePrimaryKeyMeta = {
62
- readonly name: string;
63
- readonly columns: readonly string[];
64
- };
65
-
66
- export type EntityTableMeta = {
67
- readonly tableName: string;
68
- readonly columns: readonly ColumnMeta[];
69
- readonly indexes: readonly IndexMeta[];
70
- // For tables with composite PK (no single id column, e.g. snapshots
71
- // keyed by aggregate_id+version). When set, no column should have
72
- // primaryKey:true; the constraint is emitted at table-level.
73
- readonly compositePrimaryKey?: CompositePrimaryKeyMeta;
74
- // Source hint for diagnostics/tests — not used functionally.
75
- // "managed" = from EntityDefinition (with base-columns + audit trail).
76
- // "unmanaged" = via defineUnmanagedTable — no standard audit, the app
77
- // carries the responsibility. Migration-generator + tooling can use the
78
- // discriminator to render warnings ("X tables are unmanaged").
79
- readonly source: "managed" | "unmanaged";
80
- // PII-subject-annotated field names (pii/userOwned/tenantOwned). Set by
81
- // deriveEntityTableMeta so the registry can reject r.storeTable stores
82
- // whose direct writes would skip the executor's encryption (#820).
83
- readonly piiSubjectFields?: readonly string[];
84
- // Only present for "global" tables — absent means "tenant" so existing
85
- // schema snapshots don't drift. See EntityDefinition.tenancy.
86
- readonly tenancy?: "global";
87
- };
88
-
89
- export type BuildEntityTableMetaOptions = {
90
- readonly featureName?: string;
91
- readonly relations?: EntityRelations;
92
- readonly source?: EntityTableMeta["source"];
93
- };
94
-
95
- export type UnmanagedTableInput = {
96
- readonly tableName: string;
97
- readonly columns: readonly ColumnMeta[];
98
- readonly indexes?: readonly IndexMeta[];
99
- readonly compositePrimaryKey?: CompositePrimaryKeyMeta;
100
- readonly tenancy?: EntityTenancy;
101
- };
@@ -1,6 +0,0 @@
1
- import type { KeyScope } from "./secrets-types";
2
-
3
- export type EnvelopeCipher = {
4
- encrypt(plaintext: string, scope?: KeyScope): Promise<string>;
5
- decrypt(stored: string, scope?: KeyScope): Promise<string>;
6
- };
@@ -1,163 +0,0 @@
1
- import type { CursorResult } from "./cursor-types";
2
- import type { EntityDefinition } from "./fields";
3
- import type { SessionUser, WriteResult } from "./handlers";
4
- import type { DeleteContext, SaveContext } from "./hooks";
5
- import type { EntityId } from "./identifiers";
6
- import type { SearchAdapter } from "./search-adapter";
7
- import type { TenantDb } from "./tenant-db-types";
8
-
9
- // Read-time gate for join-row entities (EntityDefinition.parentRef): the
10
- // registered-entity map the SQL clause checks host candidates against.
11
- // Lives here (not in db/parent-ref-clause.ts) because the Registry only
12
- // exists at request time — the same extension-point shape as
13
- // referenceSearch/referenceSort below (fw#2660/fw#2741).
14
- export type ParentVisibilityOption = {
15
- readonly entities: ReadonlyMap<string, EntityDefinition>;
16
- };
17
-
18
- // Runs the caller's preSave hooks against changes not yet persisted, for
19
- // the executor's create()/update() only — restore/delete/forget have no
20
- // `changes` to shape. See HandlerContext.runPreSave for how this gets bound
21
- // to a specific handler name + AppContext.
22
- export type PreSaveRunner = (
23
- changes: Record<string, unknown>,
24
- previous: Readonly<Record<string, unknown>>,
25
- isNew: boolean,
26
- ) => Promise<Record<string, unknown>>;
27
-
28
- export type EventStoreExecutor = {
29
- create: (
30
- payload: Record<string, unknown>,
31
- user: SessionUser,
32
- db: TenantDb,
33
- options?: { preSave?: PreSaveRunner },
34
- ) => Promise<WriteResult<SaveContext>>;
35
-
36
- update: (
37
- payload: { id: EntityId; version?: number | undefined; changes: Record<string, unknown> },
38
- user: SessionUser,
39
- db: TenantDb,
40
- options?: {
41
- skipOptimisticLock?: boolean;
42
- skipUnchanged?: boolean;
43
- preSave?: PreSaveRunner;
44
- // Declarative precondition for a "genau einmal"-transition (kumiko-
45
- // framework#3024): field/value pairs the row must still hold at write
46
- // time — a `null` expected value matches a null field. Re-read fresh,
47
- // atomically with the write's stream version (not the payload's stale
48
- // `previous`), so a concurrent writer that already moved the row on is
49
- // caught even when it doesn't collide with the stream-version check.
50
- // Mismatch fails the whole update with PreconditionFailedError instead
51
- // of applying it.
52
- // Scalars only (string/number/boolean/null) — the check is `!==`, so an
53
- // object/Date/Instant value would compare by reference and silently
54
- // never match; a timestamp precondition needs its own scalar mirror
55
- // field to check against, not the compound value itself. Also plain
56
- // columns only: the check reads raw column values (no decrypt pass),
57
- // so a pii/encrypted field can't be used here.
58
- expect?: Readonly<Record<string, string | number | boolean | null>>;
59
- },
60
- ) => Promise<WriteResult<SaveContext>>;
61
-
62
- delete: (
63
- payload: { id: EntityId },
64
- user: SessionUser,
65
- db: TenantDb,
66
- ) => Promise<WriteResult<DeleteContext>>;
67
-
68
- // Hard-purge (Art. 17 erasure). Like delete, but emits `<entity>.forgotten`
69
- // which hard-deletes the row even for softDelete entities — and, being an
70
- // auto-verb replayed by the implicit projection, the erasure survives a
71
- // rebuild (created → forgotten → row gone). Reaches soft-deleted rows too.
72
- forget: (
73
- payload: { id: EntityId },
74
- user: SessionUser,
75
- db: TenantDb,
76
- ) => Promise<WriteResult<DeleteContext>>;
77
-
78
- restore: (
79
- payload: { id: EntityId },
80
- user: SessionUser,
81
- db: TenantDb,
82
- ) => Promise<WriteResult<SaveContext>>;
83
-
84
- list: (
85
- payload: {
86
- cursor?: string | undefined;
87
- limit?: number | undefined;
88
- search?: string | undefined;
89
- sort?: string | undefined;
90
- sortDirection?: "asc" | "desc" | undefined;
91
- offset?: number | undefined;
92
- totalCount?: boolean | undefined;
93
- filter?:
94
- | {
95
- readonly field: string;
96
- readonly op: "eq" | "ne" | "lt" | "gt" | "lte" | "gte" | "in";
97
- readonly value: unknown;
98
- }
99
- | undefined;
100
- // User-chosen faceted filters (dynamic, additive to the static
101
- // `filter`). All combined with AND.
102
- filters?:
103
- | ReadonlyArray<{
104
- readonly field: string;
105
- readonly op: "eq" | "ne" | "lt" | "gt" | "lte" | "gte" | "in";
106
- readonly value: unknown;
107
- }>
108
- | undefined;
109
- },
110
- user: SessionUser,
111
- db: TenantDb,
112
- /** Tier 2.7e audit fix: per-call SearchAdapter override. When the
113
- * executor didn't get a SearchAdapter via Options at build time
114
- * (defaultEntityQueryHandler path), the caller (handler) can pass
115
- * one from ctx.searchAdapter here at runtime.
116
- * options.searchAdapter (build-time) wins — the runtime override
117
- * is the fallback for the default wrapper. */
118
- runtimeOptions?: {
119
- readonly searchAdapter?: SearchAdapter;
120
- // Trash query: skip the implicit `isDeleted = FALSE` filter so soft-
121
- // deleted rows are returned too. Tenant + ownership clauses still apply
122
- // — includeDeleted only relaxes the soft-delete predicate, never the
123
- // visibility ones, so it can ride untrusted query input safely.
124
- readonly includeDeleted?: boolean;
125
- // fw#2660 — a text search also matches `searchable: true` reference
126
- // fields (and the implicit tenantId→tenant.name row-meta reference) by
127
- // their target row's labelField, not just the raw FK column. Only
128
- // available at request time (registry access), so it rides the same
129
- // runtime-override extension point as searchAdapter. `fields` and
130
- // `resolveEntity` travel together — one without the other silently
131
- // no-ops, so they're grouped instead of two independent optionals.
132
- readonly referenceSearch?: {
133
- readonly fields: ReadonlyArray<{
134
- readonly fieldName: string;
135
- readonly targetEntityName: string;
136
- readonly labelField: string;
137
- }>;
138
- readonly resolveEntity: (entityName: string) => EntityDefinition | undefined;
139
- };
140
- // fw#2741 — `sortable: true` reference fields order by the target row's
141
- // labelField instead of the raw FK column. Same request-time registry
142
- // dependency (and the same fields/resolveEntity pairing) as referenceSearch.
143
- readonly referenceSort?: {
144
- readonly fields: ReadonlyArray<{
145
- readonly fieldName: string;
146
- readonly targetEntityName: string;
147
- readonly labelField: string;
148
- }>;
149
- readonly resolveEntity: (entityName: string) => EntityDefinition | undefined;
150
- };
151
- // Join-row read-gate (EntityDefinition.parentRef) — same request-time
152
- // registry dependency as referenceSearch/referenceSort above.
153
- readonly parentVisibility?: ParentVisibilityOption;
154
- },
155
- ) => Promise<CursorResult<Record<string, unknown>>>;
156
-
157
- detail: (
158
- payload: { id: EntityId },
159
- user: SessionUser,
160
- db: TenantDb,
161
- options?: { readonly parentVisibility?: ParentVisibilityOption },
162
- ) => Promise<Record<string, unknown> | null>;
163
- };