@cosmicdrift/kumiko-framework 0.339.0 → 0.341.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/dist/api/index.d.ts +2 -1
- package/dist/api/index.js +1 -1
- package/dist/api/route-registrars.d.ts +4 -2
- package/dist/api/route-registrars.js +9 -1
- package/dist/api/server.d.ts +2 -1
- package/dist/api/server.js +43 -5
- package/dist/bun-db/index.d.ts +2 -2
- package/dist/bun-db/index.js +1 -1
- package/dist/bun-db/query.d.ts +25 -1
- package/dist/bun-db/query.js +136 -15
- package/dist/db/queries/shadow-swap.d.ts +2 -1
- package/dist/db/queries/shadow-swap.js +70 -7
- package/dist/db/query-api.d.ts +1 -1
- package/dist/db/query.d.ts +1 -1
- package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
- package/dist/engine/boot-validator/entity-handler.js +48 -0
- package/dist/engine/define-handler.js +1 -0
- package/dist/engine/feature-ast/extractors/handlers.d.ts +2 -1
- package/dist/engine/feature-ast/extractors/handlers.js +11 -1
- package/dist/engine/feature-ast/extractors/hooks.d.ts +2 -1
- package/dist/engine/feature-ast/extractors/hooks.js +14 -0
- package/dist/engine/feature-ast/extractors/index.d.ts +1 -1
- package/dist/engine/feature-ast/extractors/index.js +1 -1
- package/dist/engine/feature-ast/patch.js +1 -0
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +20 -0
- package/dist/engine/feature-ast/pattern-change-schema.js +10 -0
- package/dist/engine/feature-ast/patterns.d.ts +2 -1
- package/dist/engine/feature-ast/render.js +3 -0
- package/dist/engine/feature-entity-handlers.d.ts +2 -1
- package/dist/engine/feature-entity-handlers.js +4 -0
- package/dist/engine/feature-ui-extensions.js +9 -0
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/membership-roles.js +5 -1
- package/dist/engine/pattern-library/mixed-schemas.js +5 -0
- package/dist/engine/registry-state.js +38 -5
- package/dist/engine/registry-validate.js +2 -0
- package/dist/engine/steps/unsafe-projection-upsert.js +1 -1
- package/dist/engine/tier-resolver-extension.d.ts +2 -0
- package/dist/engine/types/index.d.ts +2 -2
- package/dist/entrypoint/index.js +25 -6
- package/dist/errors/classes.d.ts +5 -0
- package/dist/errors/classes.js +13 -0
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/files/file-routes.js +7 -2
- package/dist/files/index.d.ts +1 -0
- package/dist/files/index.js +1 -0
- package/dist/files/provider-resolver.d.ts +2 -0
- package/dist/files/provider-resolver.js +16 -1
- package/dist/files/resolve-content-type.d.ts +11 -0
- package/dist/files/resolve-content-type.js +71 -0
- package/dist/files/types.d.ts +1 -1
- package/dist/files/types.js +5 -1
- package/dist/jobs/job-runner.js +1 -1
- package/dist/pipeline/dispatch-shared.d.ts +4 -1
- package/dist/pipeline/dispatch-shared.js +70 -9
- package/dist/pipeline/dispatch-write.js +35 -10
- package/dist/pipeline/dispatcher.d.ts +2 -0
- package/dist/pipeline/dispatcher.js +17 -1
- package/dist/pipeline/projection-rebuild.js +1 -1
- package/dist/rate-limit/bucket.d.ts +4 -0
- package/dist/rate-limit/bucket.js +25 -0
- package/dist/rate-limit/index.d.ts +2 -2
- package/dist/rate-limit/index.js +2 -2
- package/dist/rate-limit/middleware.d.ts +9 -0
- package/dist/rate-limit/middleware.js +33 -2
- package/dist/rate-limit/resolver.js +2 -1
- package/dist/redis/cache-sync-bus.d.ts +24 -0
- package/dist/redis/cache-sync-bus.js +152 -0
- package/dist/redis/cache-sync-topics.d.ts +17 -0
- package/dist/redis/cache-sync-topics.js +22 -0
- package/dist/redis/index.d.ts +4 -0
- package/dist/redis/index.js +2 -0
- package/dist/redis/pubsub-signal.d.ts +1 -0
- package/dist/redis/pubsub-signal.js +28 -0
- package/dist/stack/redis.d.ts +6 -1
- package/dist/stack/redis.js +7 -2
- package/dist/stack/test-stack.d.ts +15 -0
- package/dist/stack/test-stack.js +21 -1
- package/package.json +4 -4
- package/src/changes.json +54 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.341.0",
|
|
4
4
|
"description": "Framework core — engine, pipeline, API, DB, and every other bit that makes Kumiko go.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -206,8 +206,8 @@
|
|
|
206
206
|
"./package.json": "./package.json"
|
|
207
207
|
},
|
|
208
208
|
"dependencies": {
|
|
209
|
-
"@cosmicdrift/kumiko-http": "0.
|
|
210
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
209
|
+
"@cosmicdrift/kumiko-http": "0.341.0",
|
|
210
|
+
"@cosmicdrift/kumiko-types": "0.341.0",
|
|
211
211
|
"bullmq": "^5.76.7",
|
|
212
212
|
"bun-types": "^1.3.13",
|
|
213
213
|
"hono": "^4.13.1",
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
"zod": "^4.4.3"
|
|
224
224
|
},
|
|
225
225
|
"devDependencies": {
|
|
226
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.
|
|
226
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.341.0",
|
|
227
227
|
"bun-types": "^1.3.13",
|
|
228
228
|
"pino-pretty": "^13.1.3"
|
|
229
229
|
},
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,58 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.341.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "rowIdOf on extendEntityProjection for derived row ids",
|
|
6
|
+
"detail": "`r.extendEntityProjection` accepts `rowIdOf`, the row id the extension's applies write for events on its `sources` when that id is not the aggregate id (for example a tenant-salted `uuidv5(tenantId|aggregateId)` over workflow events). The ghost-row guard of the projection rebuild now counts a live row as backed when its id is `rowIdOf` of a source event, so such projections can be rebuilt instead of aborting. The guard stays strict: a row keyed by the raw aggregate id of a derived source still aborts the rebuild.\n`rowIdOf` requires `sources`, must not name the entity's own stream, and must return a uuid; a source shared by several extensions needs the same `rowIdOf` in all of them. Violations fail at boot. `ProjectionDefinition` carries the result as `extraSourceRowIds`, and `assertNoUnreachableLiveRows` takes it as an optional fifth parameter. New type `ProjectionRowIdOf`."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.341.0",
|
|
10
|
+
"type": "improvement",
|
|
11
|
+
"title": "CacheSyncBus keeps tier assignments and file providers in sync across pods",
|
|
12
|
+
"detail": "A Redis-backed CacheSyncBus (one channel, envelope with origin id, echo dropped, malformed messages ignored) now carries typed invalidation topics between pods and fires a debounced resync after a Redis reconnect. Tier assignments are published after commit and reloaded on the other pods with a per-tenant out-of-order guard; the tier cache is swapped atomically on resync. The file provider resolver drops cached providers when tenant config or secrets change on any pod. Prod, worker and dev entrypoints wire one bus per process, and TierResolverPlugin.build accepts an optional cacheSync."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"version": "0.341.0",
|
|
16
|
+
"type": "fix",
|
|
17
|
+
"title": "L3 rate-limit backend failure answers 503 rate_limit_unavailable instead of 500"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"version": "0.341.0",
|
|
21
|
+
"type": "improvement",
|
|
22
|
+
"title": "r.httpRoute rateLimit option",
|
|
23
|
+
"detail": "Per-IP limit enforced through the rate-limit resolver before the route guards; legal-pages and GET /user-export/by-token declare defaults."
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"version": "0.341.0",
|
|
27
|
+
"type": "improvement",
|
|
28
|
+
"title": "Tenant timezone cache is invalidated across processes",
|
|
29
|
+
"detail": "A config write to tenant:config:timezone now invalidates the cached value on every API and worker pod after commit, instead of letting it live until the 5 minute TTL. The signal travels over the new CacheSyncBus (Redis when REDIS_URL is set, process-local otherwise); DispatcherOptions.cacheSync overrides it and null opts out. setupTestStack gains cacheSync, implied by sharedRedisWith, to test two instances on one Redis. This replaces the earlier tenantTimezoneSync option."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"version": "0.341.0",
|
|
33
|
+
"type": "improvement",
|
|
34
|
+
"title": "Per-recipient rate limits on payload fields (additionalRateLimits)",
|
|
35
|
+
"detail": "Write handlers can declare `additionalRateLimits: [{ per: { payloadField: \"email\" }, limit, windowSeconds }]` next to `rateLimit`. The named string field of the validated payload is trimmed, lowercased and HMAC-hashed (key derived from the server's current JWT signing secret) into the bucket key `payload+handler:<handler>:<field>:<digest>`, so one address is limited across all IPs and Redis never holds it in plaintext. The check runs after schema validation and before the handler, answers 429 `rate_limited`, behaves the same for matching and non-matching values, and is skipped for system callers. Rotating the JWT secret only resets these buckets.\nBoot rejects `additionalRateLimits` on an anonymous handler without a real ip-keyed `rateLimit` (the payload bucket only complements the IP bucket), an empty list, a `payloadField` that is not a field of the Zod object schema, and a non-positive `limit` or `windowSeconds`. A handler with `additionalRateLimits` makes `buildServer` wire the rate-limit resolver. The option exists on write handlers only and appears in the feature-ast patterns, render and patch schema.\nBehavior change: `request-contract-termination` and `signup-request` now allow 3 requests per email address per 24 hours, and each token-request endpoint (`request-password-reset`, `request-email-verification`, `request-account-unlock`) allows 5 per address per 24 hours, in addition to the existing per-IP limits. The public `/api/auth` token-request routes still answer `{ isSuccess: true }` when the limit is hit; only the mail is not sent."
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"version": "0.341.0",
|
|
39
|
+
"type": "improvement",
|
|
40
|
+
"title": "429 bodies omit the payload bucket digest",
|
|
41
|
+
"detail": "A 429 caused by a payload bucket (`additionalRateLimits`) no longer carries the HMAC digest of the bucketed value in `details.bucket` or the error message: it reads `payload+handler`. The digest is a stable pseudonym of the address, so anyone who could guess an address could confirm it from the response. Redis keys are unchanged.\n`waitlist:write:submit` additionally limits each email address (case-insensitive) to 3 submits per day, across all IPs, so a botnet cannot flood one address with confirmation mails. `createWaitlistFeature({ emailRateLimits })` overrides it (`[]` disables). The admin notice mail now carries its `locale` (`en` or `de`) in the notify call."
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"version": "0.341.0",
|
|
45
|
+
"type": "fix",
|
|
46
|
+
"title": "429 bodies carry only the rate-limit scope",
|
|
47
|
+
"detail": "429 bodies (`details.bucket` and the message) now carry only the bucket scope tag (`l1`, `http`, `l2`, `user`, `ip+handler`, `payload+handler`, ...) instead of IP, user/tenant id, auth target or payload digest. Fail-closed logging prints only the error message, since Redis errors can carry the bucket key. Redis keys are unchanged."
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"version": "0.340.0",
|
|
51
|
+
"type": "improvement",
|
|
52
|
+
"title": "Typed bun-db helpers for insert-ignore, inner joins, jsonb text filters and key-ordered aggregates",
|
|
53
|
+
"detail": "`insertOnConflictDoNothing(db, table, values, { conflictKeys? })` returns the inserted row, or `undefined` when the conflict target already exists. `selectInnerJoin(db, { left, right, on, leftWhere?, rightWhere?, leftFields?, rightFields?, limit? })` joins two tables on one or more column pairs (casting to text only when the column types differ) and returns `{ left, right }` rows; `rightFields` defaults to none, so secrets on the joined table are only read when named. The where operator `jsonText: { keys, eq }` compares `col->>key` on jsonb columns, with several keys combined through `COALESCE`. `aggregateWhere` accepts `orderByKeys: \"asc\" | \"desc\"` to sort groups by their key before `limit`. All identifiers come from the table metadata and all values are bound parameters. The helpers refuse tenant-scoped tables like the other raw-connection helpers; use the `TenantDb` methods there.",
|
|
54
|
+
"migration": "keine"
|
|
55
|
+
},
|
|
2
56
|
{
|
|
3
57
|
"version": "0.339.0",
|
|
4
58
|
"type": "improvement",
|