@cosmicdrift/kumiko-types 0.352.0 → 0.354.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import type { AgentExposure, AgentHandlerHints } from "./handlers.js";
1
+ import type { AgentExposure, AgentHandlerHints, AgentScreenHints } from "./handlers.js";
2
2
  /** Fail-closed: a handler without a `description` stays invisible to the agent
3
3
  * unless it opts in explicitly. `kind` is a parameter because write and query
4
4
  * handler definitions are structurally indistinguishable at runtime. */
@@ -11,5 +11,5 @@ export declare function resolveAgentExposure(def: {
11
11
  * Reusing `resolveAgentExposure`'s fail-closed default here would silently
12
12
  * drop every screen without a description from the agent's view. */
13
13
  export declare function isAgentVisibleScreen(screen: {
14
- readonly agent?: AgentHandlerHints;
14
+ readonly agent?: AgentScreenHints;
15
15
  }): boolean;
package/dist/config.d.ts CHANGED
@@ -173,6 +173,9 @@ export type JobDefinition = {
173
173
  readonly messageKey: string;
174
174
  readonly subjectFields?: readonly string[] | undefined;
175
175
  } | undefined;
176
+ readonly tenantVisibleRun?: {
177
+ readonly subjectFields?: readonly string[] | undefined;
178
+ } | undefined;
176
179
  };
177
180
  export type NotificationRecipientFn = (result: import("./hooks.js").SaveContext) => string | readonly string[] | {
178
181
  readonly tenant: string;
@@ -13,4 +13,7 @@ export type CursorResult<T> = {
13
13
  /** Optional total row count — only present when the caller sets
14
14
  * `totalCount: true` on the query. */
15
15
  total?: number;
16
+ /** Set when the search backend returned as many candidates as it can in one
17
+ * response, so matches beyond that may be missing from `rows`. */
18
+ searchTruncated?: true;
16
19
  };
@@ -9,13 +9,11 @@ export type EntityHandlerOptions = {
9
9
  * otherwise tenant-scoped entity. Every use reports an
10
10
  * `acknowledge-cross-tenant` escape-hatch audit event. On write handlers
11
11
  * update/delete/restore address the target row's own tenant stream.
12
- * `access` stays the only caller gate. Unlike `escapeHatch` on a
12
+ * `access` stays the only caller gate, except that a write handler's
13
+ * `access` must be SystemAdmin-only. Unlike `escapeHatch` on a
13
14
  * hand-written handler this does NOT grant `ctx.db.unsafeRaw`,
14
15
  * `db.global()` writes or identity switches. */
15
16
  readonly escapeHatch?: EscapeHatchDeclaration;
16
- /** @deprecated Use `escapeHatch: { reason }` — removed in a future release;
17
- * run `scripts/codemod/migrate-cross-tenant.ts`. */
18
- readonly crossTenant?: boolean;
19
17
  };
20
18
  /** Options for the generic create/update handlers. */
21
19
  export type EntityWriteHandlerOptions = EntityHandlerOptions & {
@@ -43,6 +41,9 @@ export type RegisterEntityCrudOptions = {
43
41
  * manifest exposes only the verbs described here (fail-closed, same rule as
44
42
  * hand-written handlers). Falls back to `write.description`/`read.description`. */
45
43
  readonly descriptions?: Partial<Record<EntityCrudVerb, string>>;
44
+ /** Per-verb agent hints; win over `write.agent`/`read.agent`, so one irreversible
45
+ * verb (e.g. a hard delete) can be `risk: "high"` without raising create/update. */
46
+ readonly agents?: Partial<Record<EntityCrudVerb, AgentHandlerHints>>;
46
47
  /** Per-verb `excludeFields` for the generic create/update handlers — see
47
48
  * EntityWriteHandlerOptions. */
48
49
  readonly excludeFields?: Partial<Record<"create" | "update", readonly string[]>>;
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { EntityRelations } from "./relations.js";
2
3
  import type { EntityTenancy } from "./tenancy-brand.js";
3
4
  export type PgType = "uuid" | "text" | "boolean" | "integer" | "double precision" | "bigint" | "serial" | "bigserial" | "jsonb" | "timestamptz" | "timestamptz(3)" | "date" | `numeric(${number},${number})`;
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  // Plain-data types for EntityTableMeta — split from the runtime
2
3
  // (deriveEntityTableMeta, resolveTableName, defineUnmanagedTable) in
3
4
  // entity-table-meta.ts. Prep step for the types-only package extraction
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { TenantId } from "./identifiers.js";
2
3
  export interface VersionConflict extends Error {
3
4
  readonly aggregateId: string;
package/dist/fields.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { VariantSpec } from "./derivatives-types.js";
2
3
  import type { OwnershipMap } from "./ownership.js";
3
4
  import type { EntityTenancy } from "./tenancy-brand.js";
@@ -80,6 +81,9 @@ export type TextFieldDef = {
80
81
  * the i18n label is what users see. */
81
82
  readonly description?: string;
82
83
  readonly maxLength?: number;
84
+ /** Lower bound enforced by the generated write schema, so short input is
85
+ * rejected by validation instead of reaching the handler. */
86
+ readonly minLength?: number;
83
87
  readonly required?: boolean;
84
88
  readonly searchable?: boolean;
85
89
  readonly sortable?: boolean;
@@ -171,7 +175,8 @@ export type BooleanFieldDef = {
171
175
  readonly default?: boolean;
172
176
  readonly access?: FieldAccess;
173
177
  };
174
- export type SelectOptionTone = "ok" | "warn" | "bad" | "neutral";
178
+ export declare const SELECT_OPTION_TONES: readonly ["ok", "warn", "bad", "neutral"];
179
+ export type SelectOptionTone = (typeof SELECT_OPTION_TONES)[number];
175
180
  /** One `optionsQueryPayload` entry: a literal, or `{ field }` = the current value of
176
181
  * a sibling field of the same form (config keys: another key of the owner feature). */
177
182
  export type OptionsQueryPayloadValue = string | number | boolean | {
@@ -182,6 +187,24 @@ export declare function isOptionsQueryFieldRef(value: OptionsQueryPayloadValue):
182
187
  readonly field: string;
183
188
  };
184
189
  export declare function optionsQueryFieldRefs(payload: OptionsQueryPayload | undefined): string[];
190
+ export type FieldCondition = boolean | {
191
+ readonly field: string;
192
+ readonly eq: unknown;
193
+ } | {
194
+ readonly field: string;
195
+ readonly ne: unknown;
196
+ } | {
197
+ readonly field: string;
198
+ readonly in: readonly unknown[];
199
+ } | {
200
+ readonly field: string;
201
+ readonly notIn: readonly unknown[];
202
+ };
203
+ /** Options of a select field that are only available while `when` holds for the row values. */
204
+ export type SelectConditionalOptions<TOption extends string = string> = {
205
+ readonly options: readonly TOption[];
206
+ readonly when: Exclude<FieldCondition, boolean>;
207
+ };
185
208
  export type SelectFieldDef<TOptions extends readonly string[] = readonly string[]> = {
186
209
  readonly type: "select";
187
210
  readonly description?: string;
@@ -221,6 +244,10 @@ export type SelectFieldDef<TOptions extends readonly string[] = readonly string[
221
244
  * are ignored. Static `options` stay authoritative, and the write path must enforce
222
245
  * the same rule (see `withTierOptionGate`), the renderer only mirrors it. */
223
246
  readonly optionsAvailabilityQuery?: string;
247
+ /** Options that are only available while `when` holds for the row values; options
248
+ * in no rule are always available. The write path enforces it, the renderer only
249
+ * filters. Only valid on entity fields. */
250
+ readonly conditionalOptions?: readonly SelectConditionalOptions<TOptions[number]>[];
224
251
  } & ResolvedPiiFlags;
225
252
  export type MultiSelectFieldDef<TOptions extends readonly string[] = readonly string[]> = {
226
253
  readonly type: "multiSelect";
@@ -403,6 +430,12 @@ export type ReferenceFieldDef = {
403
430
  * the read-only display resolves a stored value against these rows and
404
431
  * falls back to the raw id for one it does not find. */
405
432
  readonly optionsQuery?: string;
433
+ /** tenant-handover opt-out: rows of THIS entity that point at a handed-over
434
+ * row through this field stay in the source tenant instead of travelling
435
+ * with it (or failing the claim with `entity_not_transferable`). The
436
+ * reference then deliberately crosses the tenant boundary after the
437
+ * handover. Use it for an entity that must not move with its host. */
438
+ readonly handover?: "stay";
406
439
  } & ResolvedPiiFlags;
407
440
  export type DefaultCurrency = "EUR" | "USD" | "GBP" | "CHF" | "JPY" | "SEK" | "NOK" | "DKK" | "PLN" | "CZK" | "CAD" | "AUD" | "NZD" | "CNY" | "INR";
408
441
  type EmbeddedSubFieldBase = {
package/dist/fields.js CHANGED
@@ -1,4 +1,6 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  // --- Field Types ---
3
+ export const SELECT_OPTION_TONES = ["ok", "warn", "bad", "neutral"];
2
4
  export function isOptionsQueryFieldRef(value) {
3
5
  return typeof value === "object" && value !== null;
4
6
  }
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { Redis } from "ioredis";
2
3
  import type { ZodType } from "zod";
3
4
  import type { CacheSyncBus } from "./cache-sync-types.js";
@@ -254,6 +255,7 @@ export type AppContext = SharedContextFields & {
254
255
  export type HandlerContext<TMap extends object = KumikoEventTypeMap> = SharedContextFields & {
255
256
  readonly db: TenantDb;
256
257
  readonly dbOutsideTransaction: TenantDb | undefined;
258
+ readonly outsideTransaction?: <T>(fn: (db: TenantDb) => Promise<T>) => Promise<T>;
257
259
  readonly systemDb?: UncheckedSystemDb;
258
260
  readonly registry: Registry;
259
261
  /** Aktiver SessionUser des Handler-Aufrufs — Convenience-Alias zu
@@ -404,7 +406,7 @@ export type EventDef<TPayload = unknown, TName extends string = string> = {
404
406
  readonly name: TName;
405
407
  readonly schema: ZodType<TPayload>;
406
408
  readonly version: number;
407
- readonly piiFields?: EventPiiStance;
409
+ readonly piiFields: EventPiiStance;
408
410
  };
409
411
  export type AppendEventArgs = {
410
412
  readonly aggregateId: string;
@@ -499,6 +501,8 @@ export type AgentHandlerHints = {
499
501
  readonly expose?: boolean;
500
502
  readonly risk?: AgentRisk;
501
503
  };
504
+ /** Screens only read `expose`; `risk` ranks handler tool calls, so it is not offered here. */
505
+ export type AgentScreenHints = Pick<AgentHandlerHints, "expose">;
502
506
  export type AgentExposure = {
503
507
  readonly expose: boolean;
504
508
  readonly risk: AgentRisk;
@@ -50,8 +50,10 @@ export type HttpRouteDefinition = {
50
50
  /** URL-Pfad (Hono-Pattern, z.B. "/feed.xml" oder "/og/:tenantId.png"). */
51
51
  readonly path: string;
52
52
  /** true = public, no session required. false = mounted behind the
53
- * session auth chain (no anonymous fallthrough, PAT rate limit,
54
- * origin + CSRF guards) — a request without a session gets 401. The
53
+ * session auth chain (global IP rate limit when configured, PII
54
+ * ciphertext tripwire, no anonymous fallthrough, origin + CSRF guards;
55
+ * PATs are rejected). requestId, body limit and observability are the
56
+ * `/api/*` chain only. A request without a session gets 401. The
55
57
  * handler reads the caller via getUser(c). */
56
58
  readonly anonymous: boolean;
57
59
  /** Hono-Handler. Bekommt Hono-Context + Framework-Deps; returnt
@@ -13,6 +13,7 @@ export type SubjectId = {
13
13
  export type SubjectKey = string;
14
14
  export declare function subjectKeyForUser(userId: string): SubjectKey;
15
15
  export declare function subjectKeyForTenant(tenantId: TenantId): SubjectKey;
16
+ export declare const PII_ERASED_SENTINEL = "[[erased]]";
16
17
  export declare const RECORD_ENTITY_PATTERN: RegExp;
17
18
  export declare function subjectKeyForRecord(entity: string, id: string): SubjectKey;
18
19
  export declare function subjectIdToKey(subject: SubjectId): SubjectKey;
@@ -4,6 +4,9 @@ export function subjectKeyForUser(userId) {
4
4
  export function subjectKeyForTenant(tenantId) {
5
5
  return `tenant:${tenantId}`;
6
6
  }
7
+ // Stands in for a PII value whose subject key was erased; clients map it to a
8
+ // translated label instead of showing it.
9
+ export const PII_ERASED_SENTINEL = "[[erased]]";
7
10
  // Registry entity names are identifier-shaped; a free-form aggregate_type
8
11
  // (events-schema.ts is a plain text column) could otherwise mint a record
9
12
  // key that subjectIdSchema (forget-subject.write.ts) later refuses to
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { DerivativesContext } from "./derivatives-types.js";
2
3
  import type { StoredEvent } from "./event-store-types.js";
3
4
  import type { KumikoEventTypeMap } from "./event-type-map.js";
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { Temporal } from "./temporal.js";
2
3
  export type RateLimitDecision = {
3
4
  readonly allowed: boolean;
package/dist/screen.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { FieldIconKey } from "./field-icon.js";
2
- import type { FieldDefinition, FormFieldDefinition, SelectOptionTone } from "./fields.js";
3
- import type { AccessRule, AgentHandlerHints } from "./handlers.js";
2
+ import type { FieldCondition, FieldDefinition, FormFieldDefinition, SelectOptionTone } from "./fields.js";
3
+ import type { AccessRule, AgentScreenHints } from "./handlers.js";
4
4
  import type { IconKey, NavIconKey } from "./nav-icon.js";
5
5
  export type { FieldIconKey } from "./field-icon.js";
6
6
  export type PlatformComponent = {
@@ -62,19 +62,7 @@ export type FormatSpec = {
62
62
  } & FieldFormatRegistry[K];
63
63
  }[keyof FieldFormatRegistry];
64
64
  export type FieldRenderer = PlatformComponent | string | FormatSpec;
65
- export type FieldCondition = boolean | {
66
- readonly field: string;
67
- readonly eq: unknown;
68
- } | {
69
- readonly field: string;
70
- readonly ne: unknown;
71
- } | {
72
- readonly field: string;
73
- readonly in: readonly unknown[];
74
- } | {
75
- readonly field: string;
76
- readonly notIn: readonly unknown[];
77
- };
65
+ export type { FieldCondition } from "./fields.js";
78
66
  export type ListColumnSpec = string | {
79
67
  readonly field: string;
80
68
  readonly renderer?: FieldRenderer;
@@ -88,6 +76,12 @@ export type ListColumnSpec = string | {
88
76
  * label; without one it is rejected at boot as an unknown field. `field`
89
77
  * is then just a stable column key (pick any unique slug). */
90
78
  readonly label?: string;
79
+ /** Marks a column on a query-backed list (projectionList, relatedList,
80
+ * dashboard list, expandableRow) as drawn by a renderer rather than read
81
+ * from a row field. Without it, a query that declares an `outputSchema`
82
+ * must return `field`; a `label` alone does not exempt the column, since
83
+ * nearly every column carries one. */
84
+ readonly virtual?: boolean;
91
85
  /** Marks this column as a reference lookup instead of a plain value —
92
86
  * for projectionList/relatedList columns, which have no
93
87
  * `EntityDefinition` to carry a real `reference` field type. Same
@@ -395,7 +389,7 @@ export type EntityListScreenDefinition = {
395
389
  readonly nav?: ScreenNavSugar;
396
390
  readonly detailFor?: string;
397
391
  readonly description?: string;
398
- readonly agent?: AgentHandlerHints;
392
+ readonly agent?: AgentScreenHints;
399
393
  /** Screen has no nav entry by design (opened via link or navved by the
400
394
  * app); exempts it from the nav-area boot check. */
401
395
  readonly dormant?: boolean;
@@ -406,6 +400,8 @@ export type EntityListScreenDefinition = {
406
400
  readonly entity: string;
407
401
  /** Short screen id (same feature) the create button opens instead of the entity's default edit screen. */
408
402
  readonly createScreen?: string;
403
+ /** Set by the role projection when `createScreen` is not reachable for the role: the renderer then shows no create button instead of falling back to the entity's edit screen. Not for app authors. */
404
+ readonly createUnavailable?: boolean;
409
405
  readonly columns: readonly ListColumnSpec[];
410
406
  readonly rowRenderer?: PlatformComponent;
411
407
  readonly cardRenderer?: PlatformComponent;
@@ -504,7 +500,7 @@ export type ProjectionListScreenDefinition = {
504
500
  readonly nav?: ScreenNavSugar;
505
501
  readonly detailFor?: string;
506
502
  readonly description?: string;
507
- readonly agent?: AgentHandlerHints;
503
+ readonly agent?: AgentScreenHints;
508
504
  /** Screen has no nav entry by design (opened via link or navved by the
509
505
  * app); exempts it from the nav-area boot check. */
510
506
  readonly dormant?: boolean;
@@ -598,7 +594,7 @@ export type ProjectionDetailScreenDefinition = {
598
594
  readonly nav?: ScreenNavSugar;
599
595
  readonly detailFor?: string;
600
596
  readonly description?: string;
601
- readonly agent?: AgentHandlerHints;
597
+ readonly agent?: AgentScreenHints;
602
598
  /** Screen has no nav entry by design (opened via link or navved by the
603
599
  * app); exempts it from the nav-area boot check. */
604
600
  readonly dormant?: boolean;
@@ -747,6 +743,8 @@ export type DashboardChartTone = "positive" | "negative" | "active" | "neutral";
747
743
  export type DashboardChartMarkerKind = {
748
744
  readonly tone?: DashboardChartTone;
749
745
  readonly color?: string;
746
+ /** i18n key; with `markerLegend: "legend"` the chart legend lists the markers of this kind under it. */
747
+ readonly label?: string;
750
748
  };
751
749
  /** One option of a stacked-area range switch. Without `months` the option
752
750
  * shows every bucket; with it, a window of that many months anchored at
@@ -785,6 +783,17 @@ export type DashboardChartPanel = DashboardPanelQueryOptions & DashboardPanelEmp
785
783
  readonly legendTotals?: boolean;
786
784
  /** Only for chart "stacked-area": range switch in the panel header. */
787
785
  readonly ranges?: DashboardChartRanges;
786
+ /** Only for chart "stacked-area": scrubber under the plot to drag the visible window; starts at today. */
787
+ readonly brush?: boolean;
788
+ /** Only for chart "stacked-area": date format of axis and marker labels.
789
+ * Default automatic: day and month below 18 visible months, month and year above. */
790
+ readonly dateFormat?: "day" | "month";
791
+ /** Only for chart "stacked-area": window the uncontrolled chart starts in.
792
+ * "from-today" starts at today even when `ranges.default` is set. Default "default-range". */
793
+ readonly initialWindow?: "default-range" | "from-today";
794
+ /** Only for chart "stacked-area": "legend" drops the numbered marker list; pins become
795
+ * plain dots with a tooltip and the legend lists marker kinds (see `markerKinds[].label`). Default "list". */
796
+ readonly markerLegend?: "list" | "legend";
788
797
  };
789
798
  export type DashboardListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & DashboardPanelGate & {
790
799
  readonly kind: "list";
@@ -871,7 +880,7 @@ export type DashboardScreenDefinition = {
871
880
  readonly nav?: ScreenNavSugar;
872
881
  readonly detailFor?: string;
873
882
  readonly description?: string;
874
- readonly agent?: AgentHandlerHints;
883
+ readonly agent?: AgentScreenHints;
875
884
  /** Screen has no nav entry by design (opened via link or navved by the
876
885
  * app); exempts it from the nav-area boot check. */
877
886
  readonly dormant?: boolean;
@@ -1044,7 +1053,9 @@ export type EditRelatedListSection = {
1044
1053
  * of a bespoke child-rows handler. Mutually exclusive with `parentParam`
1045
1054
  * (the boot-validator rejects both). `field` must be a real field on the
1046
1055
  * entity behind `query`, and that query's Zod schema must accept
1047
- * `filter` (same requirement `filter`/`facets` already have). */
1056
+ * `filter` (same requirement `filter`/`facets` already have). The filter is
1057
+ * client-supplied: any caller may omit it, so the bound query must authorize
1058
+ * the ENTIRE row set it can return, not just the parent's children. */
1048
1059
  readonly parentFilter?: {
1049
1060
  readonly field: string;
1050
1061
  };
@@ -1205,7 +1216,7 @@ export type EntityEditScreenDefinition = {
1205
1216
  readonly nav?: ScreenNavSugar;
1206
1217
  readonly detailFor?: string;
1207
1218
  readonly description?: string;
1208
- readonly agent?: AgentHandlerHints;
1219
+ readonly agent?: AgentScreenHints;
1209
1220
  /** Screen has no nav entry by design (opened via link or navved by the
1210
1221
  * app); exempts it from the nav-area boot check. */
1211
1222
  readonly dormant?: boolean;
@@ -1301,7 +1312,7 @@ export type ActionFormScreenDefinition = {
1301
1312
  readonly nav?: ScreenNavSugar;
1302
1313
  readonly detailFor?: string;
1303
1314
  readonly description?: string;
1304
- readonly agent?: AgentHandlerHints;
1315
+ readonly agent?: AgentScreenHints;
1305
1316
  /** Screen has no nav entry by design (opened via link or navved by the
1306
1317
  * app); exempts it from the nav-area boot check. */
1307
1318
  readonly dormant?: boolean;
@@ -1311,6 +1322,10 @@ export type ActionFormScreenDefinition = {
1311
1322
  readonly fallback?: string;
1312
1323
  /** Derived by buildAppSchema — see EntityEditScreenDefinition.urlPrefillFields. */
1313
1324
  readonly urlPrefillFields?: readonly string[];
1325
+ /** Submit is enabled without edits: values seeded from navigate `params` count as the
1326
+ * user's intent. Every required field the layout hides with `visible: false` must hold a
1327
+ * value, otherwise submit stays disabled (boot-checked against navigate `params`). */
1328
+ readonly submitPrefilled?: boolean;
1314
1329
  /** Write-Handler-QN der bei Submit gerufen wird. Form-Object landet
1315
1330
  * 1:1 als payload — Handler-Schema (Zod) validiert weiter. */
1316
1331
  readonly handler: string;
@@ -1469,7 +1484,7 @@ export type SecretMintScreenDefinition = {
1469
1484
  readonly nav?: ScreenNavSugar;
1470
1485
  readonly detailFor?: string;
1471
1486
  readonly description?: string;
1472
- readonly agent?: AgentHandlerHints;
1487
+ readonly agent?: AgentScreenHints;
1473
1488
  /** Screen has no nav entry by design (opened via link or navved by the
1474
1489
  * app); exempts it from the nav-area boot check. */
1475
1490
  readonly dormant?: boolean;
@@ -1479,6 +1494,10 @@ export type SecretMintScreenDefinition = {
1479
1494
  readonly fallback?: string;
1480
1495
  /** Derived by buildAppSchema — see EntityEditScreenDefinition.urlPrefillFields. */
1481
1496
  readonly urlPrefillFields?: readonly string[];
1497
+ /** Submit is enabled without edits: values seeded from navigate `params` count as the
1498
+ * user's intent. Every required field the layout hides with `visible: false` must hold a
1499
+ * value, otherwise submit stays disabled (boot-checked against navigate `params`). */
1500
+ readonly submitPrefilled?: boolean;
1482
1501
  /** Write-handler QN dispatched on submit. */
1483
1502
  readonly handler: string;
1484
1503
  readonly fields: Readonly<Record<string, FormFieldDefinition>>;
@@ -1508,8 +1527,7 @@ export type CustomScreenDefinition = {
1508
1527
  readonly nav?: ScreenNavSugar;
1509
1528
  readonly detailFor?: string;
1510
1529
  readonly description?: string;
1511
- /** Only `expose` is read for screens; `risk` ranks handler tool calls. */
1512
- readonly agent?: AgentHandlerHints;
1530
+ readonly agent?: AgentScreenHints;
1513
1531
  readonly renderer: PlatformComponent;
1514
1532
  readonly routes?: readonly CustomScreenRoute[];
1515
1533
  /** Parent list screen for breadcrumb when this detail is not in nav. */
@@ -1540,7 +1558,7 @@ export type ConfigEditScreenDefinition = {
1540
1558
  readonly nav?: ScreenNavSugar;
1541
1559
  readonly detailFor?: string;
1542
1560
  readonly description?: string;
1543
- readonly agent?: AgentHandlerHints;
1561
+ readonly agent?: AgentScreenHints;
1544
1562
  /** Screen has no nav entry by design (opened via link or navved by the
1545
1563
  * app); exempts it from the nav-area boot check. */
1546
1564
  readonly dormant?: boolean;
@@ -1590,7 +1608,7 @@ export type SecretsEditScreenDefinition = {
1590
1608
  readonly nav?: ScreenNavSugar;
1591
1609
  readonly detailFor?: string;
1592
1610
  readonly description?: string;
1593
- readonly agent?: AgentHandlerHints;
1611
+ readonly agent?: AgentScreenHints;
1594
1612
  /** Screen has no nav entry by design (opened via link or navved by the
1595
1613
  * app); exempts it from the nav-area boot check. */
1596
1614
  readonly dormant?: boolean;
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { TenantId } from "./identifiers.js";
2
3
  declare const SecretBrand: unique symbol;
3
4
  export type Secret<T = string> = {
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  // Envelope Encryption types. Separating DEK (per-value) from KEK (central)
2
3
  // is what makes key rotation cheap: on rotation we only re-wrap the small
3
4
  // encryptedDek, never touch the ciphertext.
@@ -1,11 +1,16 @@
1
1
  import type { TargetRef } from "./target-ref.js";
2
2
  export type TreeNodeState = "filled" | "stub" | "empty" | "loading" | "error";
3
- export type TreeAction = {
3
+ type TreeActionBase = {
4
4
  readonly icon: string;
5
5
  readonly label: string;
6
- readonly screen?: string;
7
- readonly target?: TargetRef;
8
6
  };
7
+ export type TreeAction = TreeActionBase & ({
8
+ readonly screen: string;
9
+ readonly target?: never;
10
+ } | {
11
+ readonly target: TargetRef;
12
+ readonly screen?: never;
13
+ });
9
14
  export type TreeNode = {
10
15
  readonly label: string;
11
16
  readonly icon?: string;
@@ -24,3 +29,4 @@ export type TreeActionsHandle<TFeature extends string, TActions extends Record<s
24
29
  readonly id: TFeature;
25
30
  readonly treeActions: TActions;
26
31
  };
32
+ export {};
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  import type { GeoAddress, GeoCoordinates, GeoTzProvider } from "./geo-tz.js";
2
3
  export type LocatedTimestampJson = {
3
4
  /** Wall-clock ISO without offset, e.g. "2026-04-03T10:00:00" */
@@ -1,3 +1,4 @@
1
+ /// <reference types="temporal-polyfill/global" preserve="true" />
1
2
  // TzContext — the type contract for ctx.tz (pure types; the factory lives in
2
3
  // @cosmicdrift/kumiko-framework, time/tz-context.ts).
3
4
  //
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.352.0",
3
+ "version": "0.354.0",
4
4
  "description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren. Enthaelt keine identitaets-sensitiven Runtime-Werte mehr (Error-Klassen leben seit #1629 in kumiko-framework, Brand-Symbole nutzen Symbol.for) und ist deshalb eine plain dependency, keine peerDependency.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -276,7 +276,7 @@
276
276
  },
277
277
  "peerDependencies": {
278
278
  "hono": "^4.13.1",
279
- "postgres": "npm:@bender0oo0/postgres@3.4.9-kumiko.1",
279
+ "postgres": "^3.4.9-0",
280
280
  "temporal-polyfill": "^0.3.2",
281
281
  "zod": "^4.4.3",
282
282
  "ioredis": "^5.10.1"