@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.
- package/dist/action-icon.d.ts +3 -0
- package/dist/action-icon.js +51 -0
- package/{src/agent-exposure.ts → dist/agent-exposure.d.ts} +8 -15
- package/dist/agent-exposure.js +16 -0
- package/dist/concurrency-mode.d.ts +1 -0
- package/dist/config-scope.d.ts +1 -0
- package/dist/config-scope.js +1 -0
- package/dist/config.d.ts +234 -0
- package/dist/config.js +1 -0
- package/dist/cursor-types.d.ts +16 -0
- package/dist/cursor-types.js +1 -0
- package/dist/db-connection.d.ts +14 -0
- package/dist/db-connection.js +1 -0
- package/dist/define-handler.d.ts +58 -0
- package/dist/define-handler.js +1 -0
- package/dist/derivatives-types.d.ts +53 -0
- package/dist/derivatives-types.js +3 -0
- package/dist/entity-cache.d.ts +16 -0
- package/dist/entity-cache.js +1 -0
- package/dist/entity-handlers.d.ts +54 -0
- package/dist/entity-handlers.js +1 -0
- package/dist/entity-table-meta-types.d.ts +44 -0
- package/dist/entity-table-meta-types.js +6 -0
- package/dist/envelope-cipher-types.d.ts +5 -0
- package/dist/envelope-cipher-types.js +1 -0
- package/dist/event-store-executor-types.d.ts +86 -0
- package/dist/event-store-executor-types.js +1 -0
- package/dist/event-store-types.d.ts +37 -0
- package/dist/event-store-types.js +7 -0
- package/dist/event-type-map.d.ts +8 -0
- package/{src/event-type-map.ts → dist/event-type-map.js} +1 -16
- package/dist/executor-brand.d.ts +8 -0
- package/dist/executor-brand.js +1 -0
- package/dist/extension-options-map.d.ts +9 -0
- package/dist/extension-options-map.js +4 -0
- package/dist/feature.d.ts +518 -0
- package/dist/feature.js +1 -0
- package/dist/field-icon.d.ts +1 -0
- package/dist/field-icon.js +1 -0
- package/dist/fields.d.ts +729 -0
- package/dist/fields.js +50 -0
- package/dist/file-handle-types.d.ts +12 -0
- package/dist/file-handle-types.js +1 -0
- package/dist/file-provider-resolver-types.d.ts +3 -0
- package/dist/file-provider-resolver-types.js +1 -0
- package/dist/file-storage-provider-types.d.ts +17 -0
- package/dist/file-storage-provider-types.js +1 -0
- package/dist/geo-tz.d.ts +17 -0
- package/{src/geo-tz.ts → dist/geo-tz.js} +1 -20
- package/dist/handlers.d.ts +493 -0
- package/dist/handlers.js +49 -0
- package/dist/hook-phase.d.ts +1 -0
- package/dist/hook-phase.js +1 -0
- package/dist/hooks.d.ts +75 -0
- package/dist/hooks.js +1 -0
- package/dist/http-route.d.ts +52 -0
- package/dist/http-route.js +13 -0
- package/dist/identifiers.d.ts +8 -0
- package/{src/identifiers.ts → dist/identifiers.js} +7 -24
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/kms-adapter-types.d.ts +68 -0
- package/dist/kms-adapter-types.js +49 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +1 -0
- package/dist/multi-stream-apply-context-types.d.ts +18 -0
- package/dist/multi-stream-apply-context-types.js +1 -0
- package/dist/nav-icon.d.ts +3 -0
- package/dist/nav-icon.js +100 -0
- package/dist/nav.d.ts +39 -0
- package/dist/nav.js +1 -0
- package/dist/observability/index.d.ts +3 -0
- package/dist/observability/index.js +2 -0
- package/dist/observability/metric.d.ts +34 -0
- package/dist/observability/metric.js +3 -0
- package/dist/observability/provider.d.ts +24 -0
- package/dist/observability/provider.js +4 -0
- package/dist/observability/span.d.ts +32 -0
- package/dist/observability/span.js +4 -0
- package/dist/ownership.d.ts +33 -0
- package/dist/ownership.js +5 -0
- package/dist/projection.d.ts +38 -0
- package/dist/projection.js +1 -0
- package/dist/rate-limit-types.d.ts +19 -0
- package/dist/rate-limit-types.js +1 -0
- package/dist/relations.d.ts +25 -0
- package/dist/relations.js +1 -0
- package/dist/schema-table-types.d.ts +15 -0
- package/{src/schema-table-types.ts → dist/schema-table-types.js} +0 -20
- package/dist/screen.d.ts +1265 -0
- package/dist/screen.js +3 -0
- package/dist/search-adapter.d.ts +32 -0
- package/dist/search-adapter.js +1 -0
- package/dist/secrets-types.d.ts +52 -0
- package/dist/secrets-types.js +30 -0
- package/dist/snapshot-types.d.ts +13 -0
- package/dist/snapshot-types.js +1 -0
- package/dist/step.d.ts +304 -0
- package/dist/step.js +11 -0
- package/dist/target-ref.d.ts +5 -0
- package/{src/target-ref.ts → dist/target-ref.js} +1 -6
- package/dist/tenancy-brand.d.ts +6 -0
- package/dist/tenancy-brand.js +1 -0
- package/dist/tenant-db-types.d.ts +67 -0
- package/dist/tenant-db-types.js +5 -0
- package/dist/tree-node.d.ts +26 -0
- package/dist/tree-node.js +22 -0
- package/dist/tz-context.d.ts +48 -0
- package/dist/tz-context.js +6 -0
- package/dist/websocket-route.d.ts +46 -0
- package/dist/websocket-route.js +10 -0
- package/dist/where-clause-types.d.ts +20 -0
- package/dist/where-clause-types.js +1 -0
- package/dist/workspace.d.ts +10 -0
- package/dist/workspace.js +1 -0
- package/dist/write-error-info-types.d.ts +12 -0
- package/dist/write-error-info-types.js +1 -0
- package/package.json +372 -124
- package/src/changes.json +18 -0
- package/src/__tests__/handlers.test.ts +0 -40
- package/src/__tests__/plural-forms.test.ts +0 -18
- package/src/action-icon.ts +0 -57
- package/src/concurrency-mode.ts +0 -5
- package/src/config-scope.ts +0 -5
- package/src/config.ts +0 -563
- package/src/cursor-types.ts +0 -18
- package/src/db-connection.ts +0 -25
- package/src/define-handler.ts +0 -138
- package/src/derivatives-types.ts +0 -106
- package/src/entity-cache.ts +0 -35
- package/src/entity-handlers.ts +0 -68
- package/src/entity-table-meta-types.ts +0 -101
- package/src/envelope-cipher-types.ts +0 -6
- package/src/event-store-executor-types.ts +0 -163
- package/src/event-store-types.ts +0 -85
- package/src/executor-brand.ts +0 -19
- package/src/extension-options-map.ts +0 -21
- package/src/feature.ts +0 -1141
- package/src/field-icon.ts +0 -23
- package/src/fields.ts +0 -1114
- package/src/file-handle-types.ts +0 -20
- package/src/file-provider-resolver-types.ts +0 -7
- package/src/file-storage-provider-types.ts +0 -54
- package/src/handlers.ts +0 -1246
- package/src/hook-phase.ts +0 -2
- package/src/hooks.ts +0 -170
- package/src/http-route.ts +0 -78
- package/src/kms-adapter-types.ts +0 -128
- package/src/logger.ts +0 -7
- package/src/multi-stream-apply-context-types.ts +0 -52
- package/src/nav-icon.ts +0 -105
- package/src/nav.ts +0 -139
- package/src/observability/index.ts +0 -28
- package/src/observability/metric.ts +0 -56
- package/src/observability/provider.ts +0 -32
- package/src/observability/span.ts +0 -58
- package/src/ownership.ts +0 -83
- package/src/projection.ts +0 -170
- package/src/rate-limit-types.ts +0 -32
- package/src/relations.ts +0 -52
- package/src/screen.ts +0 -1593
- package/src/search-adapter.ts +0 -45
- package/src/secrets-types.ts +0 -182
- package/src/snapshot-types.ts +0 -36
- package/src/step.ts +0 -390
- package/src/tenancy-brand.ts +0 -9
- package/src/tenant-db-types.ts +0 -116
- package/src/tree-node.ts +0 -134
- package/src/tz-context.ts +0 -63
- package/src/websocket-route.ts +0 -68
- package/src/where-clause-types.ts +0 -31
- package/src/workspace.ts +0 -42
- package/src/write-error-info-types.ts +0 -20
- /package/{src/index.ts → dist/concurrency-mode.js} +0 -0
package/src/hook-phase.ts
DELETED
package/src/hooks.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import type { StoredEvent } from "./event-store-types";
|
|
2
|
-
import type { AppContext } from "./handlers";
|
|
3
|
-
import type { HookPhase } from "./hook-phase";
|
|
4
|
-
import type { EntityId } from "./identifiers";
|
|
5
|
-
|
|
6
|
-
// --- Validation ---
|
|
7
|
-
|
|
8
|
-
export type ValidationError = {
|
|
9
|
-
readonly field: string;
|
|
10
|
-
readonly error: string;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type ValidationHookFn = (
|
|
14
|
-
data: Readonly<Record<string, unknown>>,
|
|
15
|
-
) => readonly ValidationError[] | null;
|
|
16
|
-
|
|
17
|
-
// --- Save/Delete Context (what hooks receive) ---
|
|
18
|
-
|
|
19
|
-
export type SaveContext = {
|
|
20
|
-
readonly kind: "save";
|
|
21
|
-
readonly id: EntityId;
|
|
22
|
-
readonly data: Readonly<Record<string, unknown>>;
|
|
23
|
-
readonly changes: Readonly<Record<string, unknown>>;
|
|
24
|
-
readonly previous: Readonly<Record<string, unknown>>;
|
|
25
|
-
readonly isNew: boolean;
|
|
26
|
-
readonly entityName?: string | undefined;
|
|
27
|
-
// The event that produced this save. Populated by the event-store-executor;
|
|
28
|
-
// the pipeline uses it to drive projections inside the same transaction.
|
|
29
|
-
// Optional because hand-crafted SaveContexts (tests, custom executors) may
|
|
30
|
-
// not have an event — projections just skip in that case.
|
|
31
|
-
readonly event?: StoredEvent | undefined;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type DeleteContext = {
|
|
35
|
-
readonly kind: "delete";
|
|
36
|
-
readonly id: EntityId;
|
|
37
|
-
readonly data: Readonly<Record<string, unknown>>;
|
|
38
|
-
readonly entityName?: string | undefined;
|
|
39
|
-
// See SaveContext.event — same semantics.
|
|
40
|
-
readonly event?: StoredEvent | undefined;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export type LifecycleResult = SaveContext | DeleteContext;
|
|
44
|
-
|
|
45
|
-
// --- Lifecycle Hooks ---
|
|
46
|
-
|
|
47
|
-
export type PreSaveHookFn = (
|
|
48
|
-
changes: Record<string, unknown>,
|
|
49
|
-
context: AppContext & {
|
|
50
|
-
readonly previous: Readonly<Record<string, unknown>>;
|
|
51
|
-
readonly isNew: boolean;
|
|
52
|
-
},
|
|
53
|
-
) => Promise<Record<string, unknown>>;
|
|
54
|
-
|
|
55
|
-
export type PostSaveHookFn = (result: SaveContext, context: AppContext) => Promise<void>;
|
|
56
|
-
|
|
57
|
-
// Batch-variant: called once at the end of a dispatcher batch with every
|
|
58
|
-
// successful SaveContext. The per-save PostSaveHookFn still fires for
|
|
59
|
-
// side-effects that need per-entity semantics (SSE); PostSaveBatch exists
|
|
60
|
-
// for adapters that can amortise work across the whole batch (e.g. search
|
|
61
|
-
// index batch-writes, bulk webhook fanout).
|
|
62
|
-
export type PostSaveBatchHookFn = (
|
|
63
|
-
results: readonly SaveContext[],
|
|
64
|
-
context: AppContext,
|
|
65
|
-
) => Promise<void>;
|
|
66
|
-
|
|
67
|
-
export type PreDeleteHookFn = (payload: DeleteContext, context: AppContext) => Promise<void>;
|
|
68
|
-
|
|
69
|
-
export type PostDeleteHookFn = (payload: DeleteContext, context: AppContext) => Promise<void>;
|
|
70
|
-
|
|
71
|
-
export type PostDeleteBatchHookFn = (
|
|
72
|
-
payloads: readonly DeleteContext[],
|
|
73
|
-
context: AppContext,
|
|
74
|
-
) => Promise<void>;
|
|
75
|
-
|
|
76
|
-
export type PreQueryHookFn = (
|
|
77
|
-
payload: Record<string, unknown>,
|
|
78
|
-
context: AppContext,
|
|
79
|
-
) => Promise<Record<string, unknown>>;
|
|
80
|
-
|
|
81
|
-
// postQuery — fires after query-handler-execute, before field-access-read-filter.
|
|
82
|
-
// Hook receives normalized rows + entityName + can mutate rows (e.g., merge
|
|
83
|
-
// custom-fields, add computed-counts, attach related-data). Mutation result
|
|
84
|
-
// replaces original rows. Hook is responsible for its own field-access-logic
|
|
85
|
-
// on added fields (field-access-filter only knows entity's stammfields).
|
|
86
|
-
export type PostQueryHookFn = (
|
|
87
|
-
result: {
|
|
88
|
-
// undefined for standalone queries (no-colon handler names like
|
|
89
|
-
// "ns:dashboard") — those have no backing entity, but handler-keyed
|
|
90
|
-
// postQuery hooks still fire on them.
|
|
91
|
-
readonly entityName: string | undefined;
|
|
92
|
-
readonly rows: ReadonlyArray<Record<string, unknown>>;
|
|
93
|
-
},
|
|
94
|
-
context: AppContext,
|
|
95
|
-
) => Promise<{ rows: ReadonlyArray<Record<string, unknown>> }>;
|
|
96
|
-
|
|
97
|
-
export type LifecycleHookFn =
|
|
98
|
-
| PreSaveHookFn
|
|
99
|
-
| PostSaveHookFn
|
|
100
|
-
| PreDeleteHookFn
|
|
101
|
-
| PostDeleteHookFn
|
|
102
|
-
| PreQueryHookFn
|
|
103
|
-
| PostQueryHookFn;
|
|
104
|
-
|
|
105
|
-
export type { HookPhase } from "./hook-phase";
|
|
106
|
-
|
|
107
|
-
// Owner-tag shared across every hook structure. The lifecycle pipeline uses
|
|
108
|
-
// it to skip hooks whose owning feature is globally disabled:
|
|
109
|
-
// - A concrete feature name like "orders" → subject to the feature-toggle
|
|
110
|
-
// filter (skipped when "orders" is disabled).
|
|
111
|
-
// - "*" (star) → invariant plumbing, never filtered. Reserved for
|
|
112
|
-
// extension-provided hooks and framework-internal hooks that belong to
|
|
113
|
-
// the pipeline itself, not a feature.
|
|
114
|
-
// - Omitted (undefined) → treated as "*". Supports tests that hand-build
|
|
115
|
-
// HookMap objects without caring about ownership.
|
|
116
|
-
export type HookOwner = { readonly featureName?: string };
|
|
117
|
-
|
|
118
|
-
export type PhasedHook<TFn> = {
|
|
119
|
-
readonly fn: TFn;
|
|
120
|
-
readonly phase: HookPhase;
|
|
121
|
-
} & HookOwner;
|
|
122
|
-
|
|
123
|
-
// Flat (non-phased) hook — preSave, preQuery. Same owner contract, no
|
|
124
|
-
// phase semantics because these hooks run exactly once per handler pass
|
|
125
|
-
// before/around the DB transaction.
|
|
126
|
-
export type OwnedFn<TFn> = {
|
|
127
|
-
readonly fn: TFn;
|
|
128
|
-
} & HookOwner;
|
|
129
|
-
|
|
130
|
-
// --- Hook Maps ---
|
|
131
|
-
|
|
132
|
-
// Slots are optional: defineFeature materializes every slot, but hand-built
|
|
133
|
-
// FeatureDefinitions at system boundaries (test fixtures, partial boots —
|
|
134
|
-
// see registry.test.ts "slot robustness") legitimately omit them, and the
|
|
135
|
-
// registry merge paths tolerate undefined. The type mirrors that contract.
|
|
136
|
-
export type HookMap = {
|
|
137
|
-
readonly validation?: Readonly<Record<string, ValidationHookFn>>;
|
|
138
|
-
readonly preSave?: Readonly<Record<string, readonly OwnedFn<PreSaveHookFn>[]>>;
|
|
139
|
-
readonly postSave?: Readonly<Record<string, readonly PhasedHook<PostSaveHookFn>[]>>;
|
|
140
|
-
readonly preDelete?: Readonly<Record<string, readonly PhasedHook<PreDeleteHookFn>[]>>;
|
|
141
|
-
readonly postDelete?: Readonly<Record<string, readonly PhasedHook<PostDeleteHookFn>[]>>;
|
|
142
|
-
readonly preQuery?: Readonly<Record<string, readonly OwnedFn<PreQueryHookFn>[]>>;
|
|
143
|
-
readonly postQuery?: Readonly<Record<string, readonly OwnedFn<PostQueryHookFn>[]>>;
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
export type EntityHookMap = {
|
|
147
|
-
readonly postSave?: Readonly<Record<string, readonly PhasedHook<PostSaveHookFn>[]>>;
|
|
148
|
-
readonly preDelete?: Readonly<Record<string, readonly PhasedHook<PreDeleteHookFn>[]>>;
|
|
149
|
-
readonly postDelete?: Readonly<Record<string, readonly PhasedHook<PostDeleteHookFn>[]>>;
|
|
150
|
-
readonly postQuery?: Readonly<Record<string, readonly OwnedFn<PostQueryHookFn>[]>>;
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// Search-Payload-Extension (F3) — contributor function that adds flat
|
|
154
|
-
// fields to an entity's search-document. Fires synchronously during
|
|
155
|
-
// buildSearchDocument (in `system-hooks.ts`), receives current entity
|
|
156
|
-
// state, returns extra fields to merge into the search-index payload.
|
|
157
|
-
//
|
|
158
|
-
// Use-cases: custom-fields-bundle (merge customFields-jsonb-keys flat
|
|
159
|
-
// into index), tags-bundle (project tags-array as searchable), computed-
|
|
160
|
-
// fields (denormalize related-counts).
|
|
161
|
-
//
|
|
162
|
-
// IMPORTANT: contributor must be deterministic per (entityName, entityId,
|
|
163
|
-
// state). Async-allowed for future-proofing but discouraged — the
|
|
164
|
-
// indexing path runs once per entity-write, sync extension is
|
|
165
|
-
// near-zero-cost.
|
|
166
|
-
export type SearchPayloadContributorFn = (args: {
|
|
167
|
-
readonly entityName: string;
|
|
168
|
-
readonly entityId: EntityId;
|
|
169
|
-
readonly state: Record<string, unknown>;
|
|
170
|
-
}) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
package/src/http-route.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// HTTP route definition — feature-declared HTTP endpoints outside
|
|
2
|
-
// the /api/write|query|batch pipeline. Use case: RSS/Atom feeds, OpenAPI
|
|
3
|
-
// specs, OG image generators, webhook receivers — anything where the
|
|
4
|
-
// feature author controls the wire format themselves.
|
|
5
|
-
//
|
|
6
|
-
// Pattern symmetric to r.queryHandler / r.writeHandler: definition as
|
|
7
|
-
// part of the feature (not the app bootstrapping). Phase-3 multi-tenant
|
|
8
|
-
// becomes trivial because tenant context is picked up via host resolution.
|
|
9
|
-
//
|
|
10
|
-
// Escape-hatch stays: runProdApp.extraRoutes (declarative list with
|
|
11
|
-
// `entry` tier) for hand-rolled routes that have nothing to do with a
|
|
12
|
-
// feature (e.g. platform-specific static-serving logic).
|
|
13
|
-
|
|
14
|
-
import type { Context } from "hono";
|
|
15
|
-
|
|
16
|
-
/** Subset von HTTP-Methoden den wir aktiv unterstützen. Hono spricht
|
|
17
|
-
* alle, aber das hier sind die einzigen die ein Feature-Author
|
|
18
|
-
* realistisch deklariert. */
|
|
19
|
-
export type HttpRouteMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
20
|
-
|
|
21
|
-
/** Dependencies die der Handler vom Framework bekommt. App-Author kann
|
|
22
|
-
* die App selbst aufrufen (`deps.app.fetch(...)` für intern-call) oder
|
|
23
|
-
* direkt per dispatcher Daten ziehen. Db/Redis sind die rohen Connections
|
|
24
|
-
* — wer Tenant-Scope braucht muss durch dispatcher.query gehen.
|
|
25
|
-
*
|
|
26
|
-
* Hono-typing: `Context<any, any>` weil das Hono-Type-Param-Setup nur
|
|
27
|
-
* intern relevant ist. Concrete Hono-app wird im Boot-Path zugewiesen. */
|
|
28
|
-
export type HttpRouteHandlerDeps = {
|
|
29
|
-
/** Die Hono-app — Handler kann via app.fetch(...) interne Routes
|
|
30
|
-
* ansprechen (z.B. /api/query mit der vollen Auth-/Anonymous-Chain). */
|
|
31
|
-
// biome-ignore lint/suspicious/noExplicitAny: Hono's generic-Param ist im Framework-Boundary unsichtbar
|
|
32
|
-
readonly app: import("hono").Hono<any, any>;
|
|
33
|
-
/** Run a query handler in-process, forcing a SPECIFIC tenant — WITHOUT
|
|
34
|
-
* going through the public /api/query HTTP layer (no header parsing, no
|
|
35
|
-
* anonymousAccess tenant resolution). The synthesized caller carries
|
|
36
|
-
* anonymous-level access ONLY (same role a real anonymous request would
|
|
37
|
-
* have, no more) — the primitive forces the tenant, not the privilege
|
|
38
|
-
* level, so it stays safe to call from any `anonymous: true` route
|
|
39
|
-
* without risking a field-level disclosure a real anonymous caller
|
|
40
|
-
* couldn't already get. Use this whenever the route needs a tenant
|
|
41
|
-
* other than the one the request resolves to (e.g. always
|
|
42
|
-
* SYSTEM_TENANT_ID regardless of the visited host) — spoofing that via
|
|
43
|
-
* an internal X-Tenant header on `app.fetch(...)` is indistinguishable
|
|
44
|
-
* from an external client and gets rejected by resolverTrust:
|
|
45
|
-
* "authoritative" anonymousAccess configs (see auth-middleware.ts). */
|
|
46
|
-
readonly systemQuery: (
|
|
47
|
-
type: string,
|
|
48
|
-
payload: unknown,
|
|
49
|
-
tenantId: import("./identifiers").TenantId,
|
|
50
|
-
) => Promise<unknown>;
|
|
51
|
-
/** Caller IP resolved via the server's configured, trustedProxyHops-aware
|
|
52
|
-
* resolver (same one requestIdMiddleware uses for `/api/*`) — a route
|
|
53
|
-
* handler needing the caller's IP (rate limiting, audit) should read
|
|
54
|
-
* this instead of parsing X-Forwarded-For itself, which trusts
|
|
55
|
-
* whichever hop count the deployment actually has in front of it. */
|
|
56
|
-
readonly clientIp: string;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export type HttpRouteHandler = (
|
|
60
|
-
// biome-ignore lint/suspicious/noExplicitAny: Hono Context-Generics sind im Framework-Boundary unsichtbar
|
|
61
|
-
c: Context<any, any>,
|
|
62
|
-
deps: HttpRouteHandlerDeps,
|
|
63
|
-
) => Response | Promise<Response>;
|
|
64
|
-
|
|
65
|
-
export type HttpRouteDefinition = {
|
|
66
|
-
/** HTTP-Methode — bei Hono-Mount via app.{get,post,...}(path). */
|
|
67
|
-
readonly method: HttpRouteMethod;
|
|
68
|
-
/** URL-Pfad (Hono-Pattern, z.B. "/feed.xml" oder "/og/:tenantId.png"). */
|
|
69
|
-
readonly path: string;
|
|
70
|
-
/** true = public, no session required. false = mounted behind the
|
|
71
|
-
* session auth chain (no anonymous fallthrough, PAT rate limit,
|
|
72
|
-
* origin + CSRF guards) — a request without a session gets 401. The
|
|
73
|
-
* handler reads the caller via getUser(c). */
|
|
74
|
-
readonly anonymous: boolean;
|
|
75
|
-
/** Hono-Handler. Bekommt Hono-Context + Framework-Deps; returnt
|
|
76
|
-
* Response (sync oder async). */
|
|
77
|
-
readonly handler: HttpRouteHandler;
|
|
78
|
-
};
|
package/src/kms-adapter-types.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import type { TenantId } from "./identifiers";
|
|
2
|
-
|
|
3
|
-
// The subject a DEK belongs to. User data is shredded on user-forget,
|
|
4
|
-
// tenant data on tenant-destroy, record data on a row-scoped forget —
|
|
5
|
-
// three erase triggers, three subject kinds.
|
|
6
|
-
export type SubjectId =
|
|
7
|
-
| { readonly kind: "user"; readonly userId: string }
|
|
8
|
-
| { readonly kind: "tenant"; readonly tenantId: TenantId }
|
|
9
|
-
| { readonly kind: "record"; readonly entity: string; readonly id: string };
|
|
10
|
-
|
|
11
|
-
// Compact storage key ("user:<uuid>" / "tenant:<uuid>" / "record:<entity>:<id>")
|
|
12
|
-
// — primary key in adapter backends and cache key in the request-level DEK cache.
|
|
13
|
-
export type SubjectKey = string;
|
|
14
|
-
|
|
15
|
-
export function subjectKeyForUser(userId: string): SubjectKey {
|
|
16
|
-
return `user:${userId}`;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function subjectKeyForTenant(tenantId: TenantId): SubjectKey {
|
|
20
|
-
return `tenant:${tenantId}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Registry entity names are identifier-shaped; a free-form aggregate_type
|
|
24
|
-
// (events-schema.ts is a plain text column) could otherwise mint a record
|
|
25
|
-
// key that subjectIdSchema (forget-subject.write.ts) later refuses to
|
|
26
|
-
// shred — enforced once here so minting and shredding can never disagree.
|
|
27
|
-
export const RECORD_ENTITY_PATTERN = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
28
|
-
|
|
29
|
-
export function subjectKeyForRecord(entity: string, id: string): SubjectKey {
|
|
30
|
-
if (!RECORD_ENTITY_PATTERN.test(entity)) {
|
|
31
|
-
throw new Error(
|
|
32
|
-
`Invalid record entity for subject key: "${entity}" — must match ${RECORD_ENTITY_PATTERN}`,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
if (id === "") throw new Error("Invalid record id for subject key: empty");
|
|
36
|
-
return `record:${entity}:${id}`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function subjectIdToKey(subject: SubjectId): SubjectKey {
|
|
40
|
-
switch (subject.kind) {
|
|
41
|
-
case "user":
|
|
42
|
-
return subjectKeyForUser(subject.userId);
|
|
43
|
-
case "tenant":
|
|
44
|
-
return subjectKeyForTenant(subject.tenantId);
|
|
45
|
-
case "record":
|
|
46
|
-
return subjectKeyForRecord(subject.entity, subject.id);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function subjectIdFromKey(key: SubjectKey): SubjectId {
|
|
51
|
-
if (key.startsWith("user:")) return { kind: "user", userId: key.slice("user:".length) };
|
|
52
|
-
if (key.startsWith("tenant:")) {
|
|
53
|
-
return { kind: "tenant", tenantId: key.slice("tenant:".length) as TenantId }; // @cast-boundary parse of a key this module minted
|
|
54
|
-
}
|
|
55
|
-
if (key.startsWith("record:")) {
|
|
56
|
-
const rest = key.slice("record:".length);
|
|
57
|
-
const separatorIndex = rest.indexOf(":");
|
|
58
|
-
const entity = separatorIndex === -1 ? "" : rest.slice(0, separatorIndex);
|
|
59
|
-
const id = separatorIndex === -1 ? "" : rest.slice(separatorIndex + 1);
|
|
60
|
-
if (entity === "" || id === "") throw new Error(`Invalid subject key: ${key}`);
|
|
61
|
-
return { kind: "record", entity, id };
|
|
62
|
-
}
|
|
63
|
-
throw new Error(`Invalid subject key: ${key}`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface KmsContext {
|
|
67
|
-
readonly tenantId?: TenantId;
|
|
68
|
-
readonly requestId: string;
|
|
69
|
-
readonly userId?: string;
|
|
70
|
-
readonly eraseReason?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface KmsHealth {
|
|
74
|
-
readonly ok: boolean;
|
|
75
|
-
readonly latencyMs: number;
|
|
76
|
-
readonly details?: Record<string, unknown>;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// 32-byte AES-256 data-encryption key, unwrapped and ready for local use.
|
|
80
|
-
export type SubjectDek = Buffer;
|
|
81
|
-
|
|
82
|
-
interface KmsAdapterBase {
|
|
83
|
-
/**
|
|
84
|
-
* Creates a fresh subject key. Throws KeyAlreadyExistsError when the
|
|
85
|
-
* subject already has one — including an erased tombstone: a shredded
|
|
86
|
-
* subject must never get a new key, or forget could be undone by
|
|
87
|
-
* re-encrypting under it.
|
|
88
|
-
*/
|
|
89
|
-
createKey(subject: SubjectId, ctx: KmsContext): Promise<void>;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Erases the key material immediately; the tombstone row stays for the
|
|
93
|
-
* audit trail. Idempotent — repeat calls and unknown subjects are no-ops.
|
|
94
|
-
*/
|
|
95
|
-
eraseKey(subject: SubjectId, ctx: KmsContext): Promise<void>;
|
|
96
|
-
|
|
97
|
-
/** Probe for boot + readiness. Throws when the backend is unreachable. */
|
|
98
|
-
health(): Promise<KmsHealth>;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Backends that hand out the plaintext DEK (Pg, InMemory). Encrypt/decrypt
|
|
102
|
-
// happens locally; DEKs are cacheable per request.
|
|
103
|
-
export interface LocalKeyKmsAdapter extends KmsAdapterBase {
|
|
104
|
-
readonly capabilities: { readonly mode: "local-key" };
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Throws KeyErasedError after eraseKey (callers render "[[erased]]"),
|
|
108
|
-
* KeyNotFoundError when the subject never had a key (typically a bug).
|
|
109
|
-
*/
|
|
110
|
-
getKey(subject: SubjectId, ctx: KmsContext): Promise<SubjectDek>;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Backends that never release key material (Vault transit, cloud KMS).
|
|
114
|
-
// Every encrypt/decrypt is a round-trip; nothing is cacheable.
|
|
115
|
-
export interface RemoteCryptoKmsAdapter extends KmsAdapterBase {
|
|
116
|
-
readonly capabilities: { readonly mode: "remote-crypto" };
|
|
117
|
-
|
|
118
|
-
encrypt(subject: SubjectId, plaintext: Uint8Array, ctx: KmsContext): Promise<Uint8Array>;
|
|
119
|
-
|
|
120
|
-
/** Same error contract as LocalKeyKmsAdapter.getKey. */
|
|
121
|
-
decrypt(subject: SubjectId, ciphertext: Uint8Array, ctx: KmsContext): Promise<Uint8Array>;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export type KmsAdapter = LocalKeyKmsAdapter | RemoteCryptoKmsAdapter;
|
|
125
|
-
|
|
126
|
-
export function isLocalKeyKmsAdapter(adapter: KmsAdapter): adapter is LocalKeyKmsAdapter {
|
|
127
|
-
return adapter.capabilities.mode === "local-key";
|
|
128
|
-
}
|
package/src/logger.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export type Logger = {
|
|
2
|
-
info(msg: string, data?: Record<string, unknown>): void;
|
|
3
|
-
warn(msg: string, data?: Record<string, unknown>): void;
|
|
4
|
-
error(msg: string, data?: Record<string, unknown>): void;
|
|
5
|
-
debug(msg: string, data?: Record<string, unknown>): void;
|
|
6
|
-
child(context: Record<string, unknown>): Logger;
|
|
7
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { DerivativesContext } from "./derivatives-types";
|
|
2
|
-
import type { StoredEvent } from "./event-store-types";
|
|
3
|
-
import type { KumikoEventTypeMap } from "./event-type-map";
|
|
4
|
-
import type { Registry } from "./feature";
|
|
5
|
-
import type { FileContext } from "./file-handle-types";
|
|
6
|
-
import type { AppendEventFn, UnsafeAppendEventFn } from "./handlers";
|
|
7
|
-
import type { SecretsContext } from "./secrets-types";
|
|
8
|
-
|
|
9
|
-
// Minimal, read+write surface handed to a MultiStreamProjection's apply()
|
|
10
|
-
// when it needs to produce follow-up events (saga / process-manager
|
|
11
|
-
// pattern). Keeps the MSP feature-decoupled: applies don't reach into
|
|
12
|
-
// handler-bridge (no query/write/writeAs), they just read the aggregate
|
|
13
|
-
// stream and append new events — Marten's session scope for projections.
|
|
14
|
-
//
|
|
15
|
-
// TMap propagates the strict event-type-map (see HandlerContext). Default
|
|
16
|
-
// matches the global KumikoEventTypeMap; runtime-pluggable callers route
|
|
17
|
-
// through unsafeAppendEvent.
|
|
18
|
-
export type MultiStreamApplyContext<TMap extends object = KumikoEventTypeMap> = {
|
|
19
|
-
// Append a domain event onto an aggregate stream in the CURRENT tx.
|
|
20
|
-
// Schema-validated, archive-guarded, stream-version derived. Metadata
|
|
21
|
-
// inherits from the triggering event (correlationId) + requestContext
|
|
22
|
-
// (causationId is already set to the triggering event.id by the
|
|
23
|
-
// dispatcher wrap). Strict against KumikoEventTypeMap — same contract
|
|
24
|
-
// as HandlerContext.appendEvent (compile-time-validated payload).
|
|
25
|
-
readonly appendEvent: AppendEventFn<TMap>;
|
|
26
|
-
// Escape hatch for runtime-pluggable events without compile-time
|
|
27
|
-
// augmentation. Same runtime semantics; type-surface is `payload: unknown`.
|
|
28
|
-
readonly unsafeAppendEvent: UnsafeAppendEventFn;
|
|
29
|
-
// Read an aggregate stream — useful when a saga needs to inspect the
|
|
30
|
-
// current state of a different aggregate before deciding what to emit.
|
|
31
|
-
readonly loadAggregate: (
|
|
32
|
-
aggregateId: string,
|
|
33
|
-
options?: { readonly asOf?: Temporal.Instant },
|
|
34
|
-
) => Promise<readonly StoredEvent[]>;
|
|
35
|
-
// The app registry — same instance HandlerContext/JobContext expose. Lets
|
|
36
|
-
// an apply resolve extension-point usages (registry.getExtensionUsages),
|
|
37
|
-
// e.g. a provider-routed MSP picking a handler by payload discriminant.
|
|
38
|
-
readonly registry: Registry;
|
|
39
|
-
// Binary storage handle factory, mirrors AppContext.files. Present when
|
|
40
|
-
// the app booted with `files.storageProvider`; undefined otherwise.
|
|
41
|
-
// Post-processing MSPs (resize, EXIF-strip, virus-scan) read bytes via
|
|
42
|
-
// `ctx.files.ref(payload.storageKey).read()` and write derivates via
|
|
43
|
-
// `.derive("thumb").write(...)` — binaries never ride through events.
|
|
44
|
-
readonly files?: FileContext;
|
|
45
|
-
// Derive-on-first-use variants, mirrors AppContext.derivatives. Present
|
|
46
|
-
// exactly when `files` is — same file-foundation-provider precondition.
|
|
47
|
-
readonly derivatives?: DerivativesContext;
|
|
48
|
-
// Tenant-scoped secret reads for side-effect MSPs (e.g. step-dispatcher's
|
|
49
|
-
// webhook auth), audited via the read's own auditCtx. Present when the
|
|
50
|
-
// app booted with the secrets feature; undefined otherwise.
|
|
51
|
-
readonly secrets?: SecretsContext;
|
|
52
|
-
};
|
package/src/nav-icon.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// Closed vocabulary of nav and button icon keys. NavDefinition.icon,
|
|
2
|
-
// ScreenNavSugar.icon, ConfigMask.icon and ButtonProps.icon/iconEnd are all
|
|
3
|
-
// typed against this union, so an unregistered key is a compile error at the
|
|
4
|
-
// r.nav()/r.screen()/config-mask/button call site instead of a silent
|
|
5
|
-
// missing-icon at runtime.
|
|
6
|
-
//
|
|
7
|
-
// The renderer-web NAV_ICONS map (packages/renderer-web/src/icons.tsx) is
|
|
8
|
-
// checked against this same union via `satisfies`, so the two can't drift —
|
|
9
|
-
// add a key here only together with its lucide-react entry there, and vice
|
|
10
|
-
// versa.
|
|
11
|
-
//
|
|
12
|
-
// Declared as a runtime tuple (not just a type) so callers that sit outside
|
|
13
|
-
// this repo's `tsc --build` project graph (e.g. samples, external consumers
|
|
14
|
-
// resolving from a stale published type) still get a runtime-checkable
|
|
15
|
-
// vocabulary — the boot-validator's validateActionHasIcon checks a declared
|
|
16
|
-
// icon against NAV_ICON_KEYS instead of trusting "not undefined".
|
|
17
|
-
export const NAV_ICON_KEYS = [
|
|
18
|
-
"dashboard",
|
|
19
|
-
"layout-grid",
|
|
20
|
-
"book-open",
|
|
21
|
-
"clipboard-list",
|
|
22
|
-
"package",
|
|
23
|
-
"gauge",
|
|
24
|
-
"list",
|
|
25
|
-
"table",
|
|
26
|
-
"layers",
|
|
27
|
-
"building",
|
|
28
|
-
"calculator",
|
|
29
|
-
"wallet",
|
|
30
|
-
"coins",
|
|
31
|
-
"credit-card",
|
|
32
|
-
"piggy-bank",
|
|
33
|
-
"receipt",
|
|
34
|
-
"chart",
|
|
35
|
-
"bar-chart",
|
|
36
|
-
"trending",
|
|
37
|
-
"sparkles",
|
|
38
|
-
"wand",
|
|
39
|
-
"calendar",
|
|
40
|
-
"file",
|
|
41
|
-
"folder",
|
|
42
|
-
"folder-open",
|
|
43
|
-
"home",
|
|
44
|
-
"bell",
|
|
45
|
-
"shield",
|
|
46
|
-
"shield-check",
|
|
47
|
-
"send",
|
|
48
|
-
"settings",
|
|
49
|
-
"users",
|
|
50
|
-
"user",
|
|
51
|
-
"search",
|
|
52
|
-
"tag",
|
|
53
|
-
"key",
|
|
54
|
-
"link",
|
|
55
|
-
"palette",
|
|
56
|
-
"share",
|
|
57
|
-
"server",
|
|
58
|
-
"mail",
|
|
59
|
-
"lock",
|
|
60
|
-
"hash",
|
|
61
|
-
"download",
|
|
62
|
-
"upload",
|
|
63
|
-
"rocket",
|
|
64
|
-
"plus",
|
|
65
|
-
"languages",
|
|
66
|
-
"trash",
|
|
67
|
-
"x",
|
|
68
|
-
"check",
|
|
69
|
-
"arrow-left",
|
|
70
|
-
"arrow-right",
|
|
71
|
-
"copy",
|
|
72
|
-
"pencil",
|
|
73
|
-
"eye",
|
|
74
|
-
"eye-off",
|
|
75
|
-
"filter",
|
|
76
|
-
"refresh",
|
|
77
|
-
"more-horizontal",
|
|
78
|
-
"more-vertical",
|
|
79
|
-
"external-link",
|
|
80
|
-
"chevron-down",
|
|
81
|
-
"chevron-right",
|
|
82
|
-
"save",
|
|
83
|
-
"undo",
|
|
84
|
-
"archive",
|
|
85
|
-
"star",
|
|
86
|
-
"flag",
|
|
87
|
-
"clock",
|
|
88
|
-
"map-pin",
|
|
89
|
-
"phone",
|
|
90
|
-
"printer",
|
|
91
|
-
"alert-triangle",
|
|
92
|
-
"info",
|
|
93
|
-
"check-circle",
|
|
94
|
-
"x-circle",
|
|
95
|
-
"loader",
|
|
96
|
-
"mic",
|
|
97
|
-
"circle-stop",
|
|
98
|
-
"image",
|
|
99
|
-
] as const;
|
|
100
|
-
|
|
101
|
-
export type NavIconKey = (typeof NAV_ICON_KEYS)[number];
|
|
102
|
-
|
|
103
|
-
// Alias kept because the union stopped being nav-only — actions and fields
|
|
104
|
-
// (added on this branch) also key their icons against it.
|
|
105
|
-
export type IconKey = NavIconKey;
|