@cosmicdrift/kumiko-types 0.372.0 → 0.373.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.
@@ -513,7 +513,8 @@ export type EntityRef = {
513
513
  export type HandlerRef = {
514
514
  readonly name: string;
515
515
  };
516
- export type RateLimitPer = "user" | "tenant" | "ip" | "user+handler" | "tenant+handler" | "ip+handler";
516
+ export declare const RATE_LIMIT_PERS: readonly ["user", "tenant", "ip", "user+handler", "tenant+handler", "ip+handler"];
517
+ export type RateLimitPer = (typeof RATE_LIMIT_PERS)[number];
517
518
  export type RateLimitOption = {
518
519
  readonly per: RateLimitPer;
519
520
  readonly limit: number;
@@ -531,11 +532,14 @@ export type PayloadRateLimitOption = {
531
532
  readonly cost?: number;
532
533
  readonly normalize?: PayloadBucketNormalization;
533
534
  };
535
+ export declare function isRateLimitOption(value: unknown): value is RateLimitOption;
536
+ export type RateLimitOptions = readonly [RateLimitOption, ...RateLimitOption[]];
534
537
  export type RateLimitDisabled = {
535
538
  readonly disabled: true;
536
539
  readonly reason: string;
537
540
  };
538
- export type RateLimitDeclaration = RateLimitOption | RateLimitDisabled;
541
+ export type RateLimitDeclaration = RateLimitOption | RateLimitOptions | RateLimitDisabled;
542
+ export declare function declaredRateLimitOptions(declaration: RateLimitDeclaration | undefined): readonly RateLimitOption[];
539
543
  export declare function isRateLimitDisabled(v: RateLimitDeclaration | undefined): v is RateLimitDisabled;
540
544
  export type AgentRisk = "low" | "mid" | "high";
541
545
  /** Per-handler hints for the AI-agent manifest. `expose` overrides the
package/dist/handlers.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { isOneOf, propertyOf } from "./type-guards.js";
1
2
  export const ESCAPE_HATCH_GRANTS = ["systemIdentity", "globalWrites", "unsafeRaw"];
2
3
  export function isEscapeHatchGrant(value) {
3
4
  return ESCAPE_HATCH_GRANTS.some((grant) => grant === value);
@@ -98,8 +99,41 @@ export function normalizeEventPiiSubject(spec) {
98
99
  return { kind: "self" };
99
100
  return { kind: "user", ownerField: spec.personal.of, whenAbsent: spec.personal.whenAbsent };
100
101
  }
102
+ // --- Handler Definitions (stored in feature/registry) ---
103
+ // Per-handler rate limit. Bucket key derived from `per`:
104
+ // "user" → userId
105
+ // "tenant" → tenantId
106
+ // "ip" → request IP
107
+ // "user+handler" → userId + handlerName
108
+ // "tenant+handler" → tenantId + handlerName
109
+ // "ip+handler" → IP + handlerName (anonymous endpoints)
110
+ // `cost` is the tokens this handler-call deducts. Default 1 — bump for
111
+ // expensive operations (bulk export, bulk import).
112
+ export const RATE_LIMIT_PERS = [
113
+ "user",
114
+ "tenant",
115
+ "ip",
116
+ "user+handler",
117
+ "tenant+handler",
118
+ "ip+handler",
119
+ ];
120
+ export function isRateLimitOption(value) {
121
+ const cost = propertyOf(value, "cost");
122
+ return (isOneOf(RATE_LIMIT_PERS, propertyOf(value, "per")) &&
123
+ typeof propertyOf(value, "limit") === "number" &&
124
+ typeof propertyOf(value, "windowSeconds") === "number" &&
125
+ (cost === undefined || typeof cost === "number"));
126
+ }
127
+ export function declaredRateLimitOptions(declaration) {
128
+ if (declaration === undefined || isRateLimitDisabled(declaration))
129
+ return [];
130
+ return isRateLimitOptionList(declaration) ? declaration : [declaration];
131
+ }
132
+ function isRateLimitOptionList(declaration) {
133
+ return Array.isArray(declaration);
134
+ }
101
135
  export function isRateLimitDisabled(v) {
102
- return v !== undefined && "disabled" in v && v.disabled === true;
136
+ return v !== undefined && !Array.isArray(v) && "disabled" in v && v.disabled === true;
103
137
  }
104
138
  // Marker set by defineEntityQueryHandler on both of its verbs. A string, not
105
139
  // a Symbol(), for the same reason as PAGED_QUERY_HANDLER_BRAND: a symlinked
@@ -13,8 +13,13 @@ export type RateLimitConfig = {
13
13
  readonly windowSeconds: number;
14
14
  readonly cost?: number;
15
15
  };
16
+ export type RateLimitBucketRequest = {
17
+ readonly bucket: string;
18
+ readonly config: RateLimitConfig;
19
+ };
16
20
  export type RateLimitResolver = {
17
21
  check(bucket: string, config: RateLimitConfig): Promise<RateLimitDecision>;
18
22
  enforce(bucket: string, config: RateLimitConfig): Promise<RateLimitDecision>;
23
+ enforceAll(requests: readonly RateLimitBucketRequest[]): Promise<readonly RateLimitDecision[]>;
19
24
  peek(bucket: string, config: Omit<RateLimitConfig, "cost">): Promise<RateLimitDecision>;
20
25
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.372.0",
3
+ "version": "0.373.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>",