@cosmicdrift/kumiko-framework 0.304.0 → 0.306.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/api/__tests__/extra-route-rejection.test.ts +38 -0
- package/src/api/__tests__/extra-routes.integration.test.ts +30 -0
- package/src/api/__tests__/server-boot-guards.test.ts +1 -0
- package/src/api/__tests__/server-error-logging.test.ts +104 -0
- package/src/api/api-constants.ts +13 -0
- package/src/api/extra-route.ts +33 -4
- package/src/api/index.ts +1 -0
- package/src/api/request-context.ts +5 -4
- package/src/api/routes.ts +26 -1
- package/src/api/server.ts +8 -2
- package/src/bun-db/__tests__/closed-connection-retry.integration.test.ts +159 -0
- package/src/bun-db/__tests__/select-many-retry.integration.test.ts +138 -0
- package/src/bun-db/query.ts +42 -18
- package/src/changes.json +108 -0
- package/src/db/__tests__/pg-error.test.ts +14 -0
- package/src/db/__tests__/system-db-view-export.test.ts +107 -0
- package/src/db/__tests__/tenant-db-no-raw.test.ts +10 -0
- package/src/db/__tests__/with-systemdb-unsafe-raw-grant.test.ts +71 -0
- package/src/db/event-store-executor-write.ts +7 -0
- package/src/db/index.ts +1 -1
- package/src/db/pg-error.ts +13 -0
- package/src/db/queries/__tests__/{unsafe-read-retrying.test.ts → unsafe-read-retrying.integration.test.ts} +28 -28
- package/src/db/tenant-db.ts +140 -16
- package/src/engine/__tests__/boot-validator-gdpr-storage.test.ts +6 -1
- package/src/engine/__tests__/boot-validator-s0-integration.test.ts +2 -2
- package/src/engine/__tests__/boot-validator.test.ts +1 -1
- package/src/engine/__tests__/tier-resolver-extension.test.ts +1 -1
- package/src/engine/boot-validator/access-declarations.ts +5 -66
- package/src/engine/extension-names.ts +55 -25
- package/src/engine/extensions/storage-provider.ts +14 -41
- package/src/engine/extensions/tenant-data.ts +4 -0
- package/src/engine/extensions/tenant-resource.ts +40 -0
- package/src/engine/extensions/user-data.ts +8 -7
- package/src/engine/feature-ast/__tests__/handler-header-roundtrip.test.ts +669 -0
- package/src/engine/feature-ast/__tests__/parse.test.ts +5 -3
- package/src/engine/feature-ast/__tests__/patch-update.test.ts +718 -0
- package/src/engine/feature-ast/__tests__/pattern-change-schema.test.ts +819 -0
- package/src/engine/feature-ast/entity-field-types.ts +41 -0
- package/src/engine/feature-ast/extractors/handlers.ts +217 -84
- package/src/engine/feature-ast/extractors/hooks.ts +72 -15
- package/src/engine/feature-ast/extractors/round2.ts +21 -0
- package/src/engine/feature-ast/extractors/shared.ts +9 -0
- package/src/engine/feature-ast/index.ts +11 -1
- package/src/engine/feature-ast/patch.ts +338 -5
- package/src/engine/feature-ast/patcher.ts +2 -2
- package/src/engine/feature-ast/pattern-change-schema.ts +1411 -0
- package/src/engine/feature-ast/patterns.ts +22 -15
- package/src/engine/feature-ast/render.ts +1 -0
- package/src/engine/feature-ui-extensions.ts +8 -7
- package/src/engine/index.ts +23 -5
- package/src/engine/personal-data-fields.ts +66 -0
- package/src/engine/registry-validate.ts +15 -0
- package/src/engine/registry.ts +2 -0
- package/src/engine/types/extension-options-map.ts +1 -0
- package/src/engine/types/index.ts +8 -0
- package/src/env/__tests__/dry-run.test.ts +43 -3
- package/src/env/dry-run.ts +28 -15
- package/src/errors/__tests__/write-failures.test.ts +47 -4
- package/src/errors/i18n/de.yaml +12 -0
- package/src/errors/i18n/en.yaml +12 -0
- package/src/errors/reasons.ts +4 -0
- package/src/errors/write-error-info.ts +12 -3
- package/src/jobs/__tests__/job-backoff.integration.test.ts +155 -0
- package/src/jobs/__tests__/job-retention.integration.test.ts +316 -0
- package/src/jobs/__tests__/job-retry-enqueue-paths.integration.test.ts +309 -0
- package/src/jobs/__tests__/jobs.integration.test.ts +38 -3
- package/src/jobs/job-runner.ts +170 -19
- package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +113 -26
- package/src/pipeline/__tests__/dispatcher.test.ts +5 -0
- package/src/pipeline/__tests__/hook-systemdb-escape-hatch.integration.test.ts +246 -0
- package/src/pipeline/__tests__/idempotency-transient-failure.integration.test.ts +198 -0
- package/src/pipeline/__tests__/public-intake-runtime-gate.integration.test.ts +425 -0
- package/src/pipeline/__tests__/redis-pipeline.integration.test.ts +59 -0
- package/src/pipeline/active-membership.ts +5 -1
- package/src/pipeline/dispatch-batch.ts +59 -13
- package/src/pipeline/dispatch-query.ts +16 -5
- package/src/pipeline/dispatch-shared.ts +12 -5
- package/src/pipeline/dispatch-stream.ts +7 -2
- package/src/pipeline/dispatch-write.ts +22 -5
- package/src/pipeline/dispatcher.ts +9 -2
- package/src/pipeline/idempotency.ts +16 -0
- package/src/pipeline/member-reader.ts +3 -1
- package/src/pipeline/system-identity-switch.ts +22 -4
- package/src/pipeline/write-origin.ts +107 -0
- package/src/rate-limit/__tests__/middleware.integration.test.ts +40 -0
- package/src/rate-limit/middleware.ts +3 -0
- package/src/stack/__tests__/setup-test-stack-metrics.integration.test.ts +79 -0
- package/src/stack/test-stack.ts +5 -0
- package/src/testing/closed-connection-error.ts +62 -0
- package/src/testing/index.ts +1 -0
- package/src/bun-db/__tests__/select-many-retry.test.ts +0 -79
|
@@ -1,43 +1,16 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// extension point, not just this one. ctx here guarantees tenantId, db, plus
|
|
7
|
-
// the optional fileProviderResolver/log; the richer stage-runner ctx
|
|
8
|
-
// (tenant-lifecycle's DestructionStageCtx) is a structural superset, so a hook
|
|
9
|
-
// typed against this minimal ctx is safely assignable wherever that richer ctx
|
|
10
|
-
// is passed.
|
|
11
|
-
//
|
|
12
|
-
// `db` is a raw DbRunner, NOT a tenant-scoped TenantDb — unlike
|
|
13
|
-
// TenantDataHookCtx.db (EXT_TENANT_DATA), runExtensionDestroyHooks hands every
|
|
14
|
-
// EXT_*_RESOURCE-style hook (this one included) the stage runner's own
|
|
15
|
-
// DestructionStageCtx.db straight through, with no tenant filter and no
|
|
16
|
-
// escapeHatch/unsafeRaw gate — there is nothing to declare, because nothing
|
|
17
|
-
// ever wraps it. That's deliberate for this stage family: wiping a whole
|
|
18
|
-
// search index, an S3 prefix, or infra resources is inherently a cross-tenant,
|
|
19
|
-
// bulk operation, not a row-scoped one. A hook that needs a plain read across
|
|
20
|
-
// tenants (kumiko-framework#3035: does a foreign tenant's file_refs row still
|
|
1
|
+
// EXT_STORAGE_PROVIDER (tenant-destroy binary cleanup) is one of the four
|
|
2
|
+
// EXT_*_RESOURCE-style extension points — see tenant-resource.ts for the
|
|
3
|
+
// shared hook-signature contract. Kept as aliases so the existing public
|
|
4
|
+
// exports/imports stay valid; a hook that needs a plain cross-tenant read
|
|
5
|
+
// (kumiko-framework#3035: does a foreign tenant's file_refs row still
|
|
21
6
|
// reference a key under THIS tenant's storage prefix) uses `db` directly via
|
|
22
|
-
// executeRawQueryRead — there is no `ctx.systemDb` here
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
7
|
+
// executeRawQueryRead — there is no `ctx.systemDb` here.
|
|
8
|
+
import type {
|
|
9
|
+
TenantResourceDestroyHook,
|
|
10
|
+
TenantResourceExtensionHooks,
|
|
11
|
+
TenantResourceHookCtx,
|
|
12
|
+
} from "./tenant-resource";
|
|
28
13
|
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
readonly fileProviderResolver?: FileProviderResolver;
|
|
33
|
-
readonly log?: (message: string) => void;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export type StorageProviderDestroyTenantHook = (
|
|
37
|
-
tenantId: TenantId,
|
|
38
|
-
ctx: StorageProviderHookCtx,
|
|
39
|
-
) => Promise<void>;
|
|
40
|
-
|
|
41
|
-
export interface StorageProviderExtensionHooks {
|
|
42
|
-
readonly destroyTenant: StorageProviderDestroyTenantHook;
|
|
43
|
-
}
|
|
14
|
+
export type StorageProviderHookCtx = TenantResourceHookCtx;
|
|
15
|
+
export type StorageProviderDestroyTenantHook = TenantResourceDestroyHook;
|
|
16
|
+
export type StorageProviderExtensionHooks = TenantResourceExtensionHooks;
|
|
@@ -28,3 +28,7 @@ export type TenantDataDestroyHook = (ctx: TenantDataHookCtx) => Promise<void>;
|
|
|
28
28
|
export interface TenantDataExtensionHooks {
|
|
29
29
|
readonly destroy: TenantDataDestroyHook;
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
export function isTenantDataExtensionHooks(o: unknown): o is TenantDataExtensionHooks {
|
|
33
|
+
return typeof o === "object" && o !== null && "destroy" in o && typeof o.destroy === "function";
|
|
34
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Hook signature types shared by the four EXT_*_RESOURCE-style extension
|
|
2
|
+
// points (storageProvider, searchAdapter, externalResource, infraResource).
|
|
3
|
+
// runExtensionDestroyHooks (tenant-lifecycle/stages.ts) passes tenantId as
|
|
4
|
+
// its own positional arg for all of them, not just storageProvider — the
|
|
5
|
+
// stage runner's DestructionStageCtx is a structural superset of the ctx
|
|
6
|
+
// below, so a hook typed against it is safely assignable wherever the
|
|
7
|
+
// richer ctx is passed.
|
|
8
|
+
//
|
|
9
|
+
// `db` is a raw DbRunner, not a tenant-scoped TenantDb: wiping a whole
|
|
10
|
+
// search index, an S3 prefix, or infra resources is inherently a
|
|
11
|
+
// cross-tenant, bulk operation, not a row-scoped one — there is no
|
|
12
|
+
// escapeHatch/unsafeRaw gate here because nothing ever wraps `db`.
|
|
13
|
+
import type { FileProviderResolver } from "@cosmicdrift/kumiko-types/file-provider-resolver-types";
|
|
14
|
+
import type { DbRunner } from "../../db/connection";
|
|
15
|
+
import type { TenantId } from "../types";
|
|
16
|
+
|
|
17
|
+
export interface TenantResourceHookCtx {
|
|
18
|
+
readonly tenantId: TenantId;
|
|
19
|
+
readonly db: DbRunner;
|
|
20
|
+
readonly fileProviderResolver?: FileProviderResolver;
|
|
21
|
+
readonly log?: (message: string) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type TenantResourceDestroyHook = (
|
|
25
|
+
tenantId: TenantId,
|
|
26
|
+
ctx: TenantResourceHookCtx,
|
|
27
|
+
) => Promise<void>;
|
|
28
|
+
|
|
29
|
+
export interface TenantResourceExtensionHooks {
|
|
30
|
+
readonly destroyTenant: TenantResourceDestroyHook;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isTenantResourceExtensionHooks(o: unknown): o is TenantResourceExtensionHooks {
|
|
34
|
+
return (
|
|
35
|
+
typeof o === "object" &&
|
|
36
|
+
o !== null &&
|
|
37
|
+
"destroyTenant" in o &&
|
|
38
|
+
typeof o.destroyTenant === "function"
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -166,15 +166,16 @@ export type UserDataDeleteHook = (
|
|
|
166
166
|
) => Promise<UserDataDeleteHookResult>;
|
|
167
167
|
|
|
168
168
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* konsumierende Features liefern beide Hooks via
|
|
172
|
-
* `r.useExtension(EXT_USER_DATA, "<entity>", { export, delete })`.
|
|
173
|
-
*
|
|
174
|
-
* Kein Hook ist optional — beide MÜSSEN registriert sein. Boot-Check
|
|
175
|
-
* (Sprint 2) prüft das.
|
|
169
|
+
* Full hook table for EXT_USER_DATA. Export-only is a legitimate partial
|
|
170
|
+
* contract, so registrations are typed by `UserDataExtensionOptions`.
|
|
176
171
|
*/
|
|
177
172
|
export interface UserDataExtensionHooks {
|
|
178
173
|
readonly export: UserDataExportHook;
|
|
179
174
|
readonly delete: UserDataDeleteHook;
|
|
180
175
|
}
|
|
176
|
+
|
|
177
|
+
// At least one hook is required: an empty bag would silently register neither export nor forget.
|
|
178
|
+
export type UserDataExtensionOptions = (
|
|
179
|
+
| { readonly export: UserDataExportHook; readonly delete?: UserDataDeleteHook }
|
|
180
|
+
| { readonly export?: UserDataExportHook; readonly delete: UserDataDeleteHook }
|
|
181
|
+
) & { readonly order?: number };
|