@arcis/node 1.4.3 → 1.5.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.
Files changed (142) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -5
  3. package/dist/astro/index.js +6141 -0
  4. package/dist/astro/index.js.map +1 -0
  5. package/dist/astro/index.mjs +6136 -0
  6. package/dist/astro/index.mjs.map +1 -0
  7. package/dist/bun/index.js +6195 -0
  8. package/dist/bun/index.js.map +1 -0
  9. package/dist/bun/index.mjs +6189 -0
  10. package/dist/bun/index.mjs.map +1 -0
  11. package/dist/core/constants.d.ts +4 -3
  12. package/dist/core/constants.d.ts.map +1 -1
  13. package/dist/core/index.js +8 -4
  14. package/dist/core/index.js.map +1 -1
  15. package/dist/core/index.mjs +8 -4
  16. package/dist/core/index.mjs.map +1 -1
  17. package/dist/core/types.d.ts +43 -0
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/fastify/index.js +6160 -0
  20. package/dist/fastify/index.js.map +1 -0
  21. package/dist/fastify/index.mjs +6155 -0
  22. package/dist/fastify/index.mjs.map +1 -0
  23. package/dist/guards.d.ts +156 -0
  24. package/dist/guards.d.ts.map +1 -0
  25. package/dist/hono/index.js +6159 -0
  26. package/dist/hono/index.js.map +1 -0
  27. package/dist/hono/index.mjs +6154 -0
  28. package/dist/hono/index.mjs.map +1 -0
  29. package/dist/index.d.ts +23 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +7365 -305
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +7327 -306
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/koa/index.js +6158 -0
  36. package/dist/koa/index.js.map +1 -0
  37. package/dist/koa/index.mjs +6153 -0
  38. package/dist/koa/index.mjs.map +1 -0
  39. package/dist/logging/index.js.map +1 -1
  40. package/dist/logging/index.mjs.map +1 -1
  41. package/dist/logging/redactor.d.ts.map +1 -1
  42. package/dist/middleware/astro.d.ts +64 -0
  43. package/dist/middleware/astro.d.ts.map +1 -0
  44. package/dist/middleware/bot-detection.d.ts.map +1 -1
  45. package/dist/middleware/bun.d.ts +75 -0
  46. package/dist/middleware/bun.d.ts.map +1 -0
  47. package/dist/middleware/csrf.d.ts.map +1 -1
  48. package/dist/middleware/error-handler.d.ts.map +1 -1
  49. package/dist/middleware/fastify.d.ts +89 -0
  50. package/dist/middleware/fastify.d.ts.map +1 -0
  51. package/dist/middleware/graphql.d.ts +35 -0
  52. package/dist/middleware/graphql.d.ts.map +1 -0
  53. package/dist/middleware/hono.d.ts +63 -0
  54. package/dist/middleware/hono.d.ts.map +1 -0
  55. package/dist/middleware/index.d.ts +12 -0
  56. package/dist/middleware/index.d.ts.map +1 -1
  57. package/dist/middleware/index.js +6693 -122
  58. package/dist/middleware/index.js.map +1 -1
  59. package/dist/middleware/index.mjs +6683 -123
  60. package/dist/middleware/index.mjs.map +1 -1
  61. package/dist/middleware/koa.d.ts +84 -0
  62. package/dist/middleware/koa.d.ts.map +1 -0
  63. package/dist/middleware/main.d.ts +0 -30
  64. package/dist/middleware/main.d.ts.map +1 -1
  65. package/dist/middleware/mass-assign.d.ts +81 -0
  66. package/dist/middleware/mass-assign.d.ts.map +1 -0
  67. package/dist/middleware/method-allowlist.d.ts +66 -0
  68. package/dist/middleware/method-allowlist.d.ts.map +1 -0
  69. package/dist/middleware/nestjs.d.ts +62 -0
  70. package/dist/middleware/nestjs.d.ts.map +1 -0
  71. package/dist/middleware/nextjs.d.ts +102 -0
  72. package/dist/middleware/nextjs.d.ts.map +1 -0
  73. package/dist/middleware/nuxt.d.ts +61 -0
  74. package/dist/middleware/nuxt.d.ts.map +1 -0
  75. package/dist/middleware/overload.d.ts +92 -0
  76. package/dist/middleware/overload.d.ts.map +1 -0
  77. package/dist/middleware/protect.d.ts +91 -0
  78. package/dist/middleware/protect.d.ts.map +1 -0
  79. package/dist/middleware/rate-limit-sliding.d.ts.map +1 -1
  80. package/dist/middleware/rate-limit-token.d.ts.map +1 -1
  81. package/dist/middleware/rate-limit.d.ts.map +1 -1
  82. package/dist/middleware/response-splitting.d.ts +83 -0
  83. package/dist/middleware/response-splitting.d.ts.map +1 -0
  84. package/dist/middleware/sveltekit.d.ts +68 -0
  85. package/dist/middleware/sveltekit.d.ts.map +1 -0
  86. package/dist/middleware/token-budget.d.ts +75 -0
  87. package/dist/middleware/token-budget.d.ts.map +1 -0
  88. package/dist/nestjs/index.js +1724 -0
  89. package/dist/nestjs/index.js.map +1 -0
  90. package/dist/nestjs/index.mjs +1717 -0
  91. package/dist/nestjs/index.mjs.map +1 -0
  92. package/dist/nextjs/index.js +6184 -0
  93. package/dist/nextjs/index.js.map +1 -0
  94. package/dist/nextjs/index.mjs +6178 -0
  95. package/dist/nextjs/index.mjs.map +1 -0
  96. package/dist/nuxt/index.js +6141 -0
  97. package/dist/nuxt/index.js.map +1 -0
  98. package/dist/nuxt/index.mjs +6136 -0
  99. package/dist/nuxt/index.mjs.map +1 -0
  100. package/dist/sanitizers/encode.d.ts.map +1 -1
  101. package/dist/sanitizers/graphql.d.ts +72 -0
  102. package/dist/sanitizers/graphql.d.ts.map +1 -0
  103. package/dist/sanitizers/headers.d.ts +18 -0
  104. package/dist/sanitizers/headers.d.ts.map +1 -1
  105. package/dist/sanitizers/index.d.ts +6 -2
  106. package/dist/sanitizers/index.d.ts.map +1 -1
  107. package/dist/sanitizers/index.js +339 -197
  108. package/dist/sanitizers/index.js.map +1 -1
  109. package/dist/sanitizers/index.mjs +333 -198
  110. package/dist/sanitizers/index.mjs.map +1 -1
  111. package/dist/sanitizers/prompt-injection.d.ts +62 -0
  112. package/dist/sanitizers/prompt-injection.d.ts.map +1 -0
  113. package/dist/sanitizers/sanitize.d.ts +13 -0
  114. package/dist/sanitizers/sanitize.d.ts.map +1 -1
  115. package/dist/sanitizers/xpath.d.ts +37 -0
  116. package/dist/sanitizers/xpath.d.ts.map +1 -0
  117. package/dist/stores/index.js +4 -4
  118. package/dist/stores/index.js.map +1 -1
  119. package/dist/stores/index.mjs +4 -4
  120. package/dist/stores/index.mjs.map +1 -1
  121. package/dist/stores/redis.d.ts +7 -1
  122. package/dist/stores/redis.d.ts.map +1 -1
  123. package/dist/sveltekit/index.js +6142 -0
  124. package/dist/sveltekit/index.js.map +1 -0
  125. package/dist/sveltekit/index.mjs +6137 -0
  126. package/dist/sveltekit/index.mjs.map +1 -0
  127. package/dist/telemetry/client.d.ts +3 -0
  128. package/dist/telemetry/client.d.ts.map +1 -1
  129. package/dist/telemetry/types.d.ts +12 -0
  130. package/dist/telemetry/types.d.ts.map +1 -1
  131. package/dist/validation/index.d.ts +2 -0
  132. package/dist/validation/index.d.ts.map +1 -1
  133. package/dist/validation/index.js +137 -12
  134. package/dist/validation/index.js.map +1 -1
  135. package/dist/validation/index.mjs +116 -13
  136. package/dist/validation/index.mjs.map +1 -1
  137. package/dist/validation/redirect.d.ts.map +1 -1
  138. package/dist/validation/schema.d.ts.map +1 -1
  139. package/dist/validation/url-async.d.ts +137 -0
  140. package/dist/validation/url-async.d.ts.map +1 -0
  141. package/package.json +52 -4
  142. package/scripts/postinstall.cjs +26 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @module @arcis/node/guards
3
+ *
4
+ * Guards API. Same Arcis decisioning (rate limit, bot detect, prompt
5
+ * injection, token budget) applied to non-HTTP contexts where there's no
6
+ * `req`/`res` pair. Use this for:
7
+ *
8
+ * - Job queue workers (BullMQ, agenda, sidekiq-style)
9
+ * - Agent tool-call handlers (Claude/OpenAI tool dispatch)
10
+ * - WebSocket / SSE / gRPC handlers
11
+ * - Background processors (cron jobs, scheduled tasks)
12
+ *
13
+ * Each call to `guards.run(input)` returns a structured decision: `ok` +
14
+ * (when denied) the `vector`, `severity`, `reason`, and `retryAfterSeconds`
15
+ * the deny was triggered by. The first vector that denies short-circuits
16
+ * the rest, so denial latency stays bounded.
17
+ *
18
+ * @example
19
+ * import { Guards } from '@arcis/node';
20
+ *
21
+ * const guards = new Guards({
22
+ * rateLimit: { max: 50, windowMs: 60_000 },
23
+ * tokenBudget: { maxTokens: 100_000, windowMs: 60 * 60 * 1000 },
24
+ * promptInjection: { redactLow: false },
25
+ * });
26
+ *
27
+ * // In a job handler:
28
+ * const decision = guards.run({
29
+ * key: jobUserId,
30
+ * tokens: estimateTokens(prompt),
31
+ * text: prompt,
32
+ * });
33
+ * if (!decision.ok) {
34
+ * throw new Error(`Job rejected (${decision.vector}): ${decision.reason}`);
35
+ * }
36
+ */
37
+ import { type BotProtectionOptions } from './middleware/bot-detection';
38
+ import { type PromptInjectionSeverity } from './sanitizers/prompt-injection';
39
+ export interface GuardsRateLimitOptions {
40
+ /** Max events per window per key. Default: 100. */
41
+ max?: number;
42
+ /** Window length in milliseconds. Default: 60000 (1 minute). */
43
+ windowMs?: number;
44
+ }
45
+ export interface GuardsTokenBudgetOptions {
46
+ /** Max tokens a single key can spend in one window. Default: 100,000. */
47
+ maxTokens?: number;
48
+ /** Window length in milliseconds. Default: 60 * 60 * 1000 (1 hour). */
49
+ windowMs?: number;
50
+ /**
51
+ * Optional per-call cap. When set, a single call with `tokens > maxRequestTokens`
52
+ * denies BEFORE charging the window budget.
53
+ */
54
+ maxRequestTokens?: number;
55
+ }
56
+ export interface GuardsPromptInjectionOptions {
57
+ /**
58
+ * Minimum severity that triggers a deny. Default: 'medium' (HIGH and
59
+ * MEDIUM matches deny; LOW matches still surface in `decision.matches`
60
+ * but don't deny).
61
+ */
62
+ denyAt?: PromptInjectionSeverity;
63
+ }
64
+ export interface GuardsBotOptions {
65
+ /** Categories that pass through. Default: SEARCH_ENGINE, SOCIAL, MONITORING. */
66
+ allow?: BotProtectionOptions['allow'];
67
+ /** Categories that always deny. Default: AUTOMATED. */
68
+ deny?: BotProtectionOptions['deny'];
69
+ /** Default for uncategorized bots. Default: 'allow'. */
70
+ defaultAction?: BotProtectionOptions['defaultAction'];
71
+ }
72
+ export interface GuardsConfig {
73
+ /** When set, every call is rate-limited per `input.key`. Omit to disable. */
74
+ rateLimit?: GuardsRateLimitOptions;
75
+ /** When set, calls with `input.tokens` charge a per-key sliding-window budget. */
76
+ tokenBudget?: GuardsTokenBudgetOptions;
77
+ /** When set, `input.text` is scanned for prompt-injection signatures. */
78
+ promptInjection?: GuardsPromptInjectionOptions | true;
79
+ /** When set, `input.userAgent` is matched against the bot corpus. */
80
+ bot?: GuardsBotOptions | true;
81
+ }
82
+ export interface GuardsInput {
83
+ /** Identifier for rate-limit / token-budget bucketing. Required. */
84
+ key: string;
85
+ /** Optional text payload for prompt-injection scanning. */
86
+ text?: string;
87
+ /** Optional token cost for token-budget accounting. */
88
+ tokens?: number;
89
+ /** Optional User-Agent string for bot detection. */
90
+ userAgent?: string;
91
+ }
92
+ export type GuardsVector = 'rate-limit' | 'token-budget' | 'prompt-injection' | 'bot';
93
+ export type GuardsSeverity = 'low' | 'medium' | 'high';
94
+ export interface GuardsDecision {
95
+ /** True if the input passes every configured vector. */
96
+ ok: boolean;
97
+ /** Which vector denied. Undefined when `ok` is true. */
98
+ vector?: GuardsVector;
99
+ /** Human-readable reason for the deny. Undefined when `ok` is true. */
100
+ reason?: string;
101
+ /** Severity of the deny. Undefined when `ok` is true. */
102
+ severity?: GuardsSeverity;
103
+ /** How many seconds until the same key can retry (rate-limit / token-budget). */
104
+ retryAfterSeconds?: number;
105
+ /**
106
+ * For prompt-injection: every signature that matched, even when the deny
107
+ * threshold wasn't hit. Lets callers log low-severity matches without
108
+ * blocking on them.
109
+ */
110
+ matches?: ReadonlyArray<{
111
+ rule: string;
112
+ severity: GuardsSeverity;
113
+ }>;
114
+ }
115
+ /**
116
+ * Guards. Apply Arcis decisions to non-HTTP contexts. Construct once with
117
+ * the vectors you care about, then call `.run(input)` per request/event.
118
+ * Internal state (rate-limit buckets, token-budget buckets) lives on the
119
+ * instance. Call `.close()` to release the periodic-cleanup interval.
120
+ */
121
+ export declare class Guards {
122
+ private readonly rl;
123
+ private readonly tb;
124
+ private readonly pi;
125
+ private readonly bot;
126
+ private readonly rlStore;
127
+ private readonly tbStore;
128
+ private readonly cleanup;
129
+ private readonly piDenyRank;
130
+ constructor(config?: GuardsConfig);
131
+ /**
132
+ * Evaluate every configured vector against `input`. Returns a structured
133
+ * decision; the first denying vector short-circuits the rest.
134
+ */
135
+ run(input: GuardsInput): GuardsDecision;
136
+ /** Inspect rate-limit usage for a key. Useful for tests and telemetry. */
137
+ inspectRateLimit(key: string): {
138
+ count: number;
139
+ resetTime: number;
140
+ } | null;
141
+ /** Inspect token-budget usage for a key. */
142
+ inspectTokenBudget(key: string): {
143
+ used: number;
144
+ resetTime: number;
145
+ } | null;
146
+ /** Reset a single key's state, or all keys if `key` is omitted. */
147
+ reset(key?: string): void;
148
+ /** Release the periodic cleanup interval. Idempotent. */
149
+ close(): void;
150
+ private checkRateLimit;
151
+ private checkTokenBudget;
152
+ private checkBot;
153
+ private sweepExpired;
154
+ }
155
+ export default Guards;
156
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}