@relaycast/engine 11.1.1 → 12.0.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/adapters/node/index.d.ts +3 -3
- package/dist/adapters/node/index.d.ts.map +1 -1
- package/dist/adapters/node/index.js +1 -3
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/adapters/node/kv.d.ts +0 -1
- package/dist/adapters/node/kv.d.ts.map +1 -1
- package/dist/adapters/node/kv.js +0 -17
- package/dist/adapters/node/kv.js.map +1 -1
- package/dist/db/migrations/0077_drop_workspace_plan.sql +4 -0
- package/dist/db/schema.d.ts +0 -19
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +0 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/engine/inboundWebhook.d.ts +10 -0
- package/dist/engine/inboundWebhook.d.ts.map +1 -1
- package/dist/engine/inboundWebhook.js +18 -1
- package/dist/engine/inboundWebhook.js.map +1 -1
- package/dist/engine/workspace.d.ts +0 -2
- package/dist/engine/workspace.d.ts.map +1 -1
- package/dist/engine/workspace.js +0 -1
- package/dist/engine/workspace.js.map +1 -1
- package/dist/engine/workspaceDeliveryPolicy.d.ts +1 -2
- package/dist/engine/workspaceDeliveryPolicy.d.ts.map +1 -1
- package/dist/engine/workspaceDeliveryPolicy.js +2 -5
- package/dist/engine/workspaceDeliveryPolicy.js.map +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.js +2 -2
- package/dist/engine.js.map +1 -1
- package/dist/entrypoints/node.d.ts +2 -2
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +1 -1
- package/dist/entrypoints/node.js.map +1 -1
- package/dist/env.d.ts +5 -5
- package/dist/env.d.ts.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/admissionError.d.ts +11 -0
- package/dist/lib/admissionError.d.ts.map +1 -0
- package/dist/lib/admissionError.js +14 -0
- package/dist/lib/admissionError.js.map +1 -0
- package/dist/lib/httpError.d.ts.map +1 -1
- package/dist/lib/httpError.js +4 -3
- package/dist/lib/httpError.js.map +1 -1
- package/dist/middleware/admission.d.ts +42 -0
- package/dist/middleware/admission.d.ts.map +1 -0
- package/dist/middleware/admission.js +82 -0
- package/dist/middleware/admission.js.map +1 -0
- package/dist/middleware/rateLimit.d.ts +2 -0
- package/dist/middleware/rateLimit.d.ts.map +1 -1
- package/dist/middleware/rateLimit.js +22 -25
- package/dist/middleware/rateLimit.js.map +1 -1
- package/dist/ports/admission.d.ts +59 -0
- package/dist/ports/admission.d.ts.map +1 -0
- package/dist/ports/admission.js +2 -0
- package/dist/ports/admission.js.map +1 -0
- package/dist/ports/index.d.ts +10 -4
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/kv.d.ts +1 -16
- package/dist/ports/kv.d.ts.map +1 -1
- package/dist/ports/workspaceDelivery.d.ts +3 -4
- package/dist/ports/workspaceDelivery.d.ts.map +1 -1
- package/dist/routes/dm.js +3 -3
- package/dist/routes/dm.js.map +1 -1
- package/dist/routes/groupDm.js +3 -3
- package/dist/routes/groupDm.js.map +1 -1
- package/dist/routes/inboundWebhook.js +8 -0
- package/dist/routes/inboundWebhook.js.map +1 -1
- package/dist/routes/message.js +3 -3
- package/dist/routes/message.js.map +1 -1
- package/dist/routes/thread.js +3 -3
- package/dist/routes/thread.js.map +1 -1
- package/package.json +3 -3
- package/dist/engine/usage.d.ts +0 -35
- package/dist/engine/usage.d.ts.map +0 -1
- package/dist/engine/usage.js +0 -59
- package/dist/engine/usage.js.map +0 -1
- package/dist/lib/planLimitError.d.ts +0 -26
- package/dist/lib/planLimitError.d.ts.map +0 -1
- package/dist/lib/planLimitError.js +0 -16
- package/dist/lib/planLimitError.js.map +0 -1
- package/dist/middleware/planLimits.d.ts +0 -36
- package/dist/middleware/planLimits.d.ts.map +0 -1
- package/dist/middleware/planLimits.js +0 -190
- package/dist/middleware/planLimits.js.map +0 -1
- package/dist/middleware/usageTracker.d.ts +0 -3
- package/dist/middleware/usageTracker.d.ts.map +0 -1
- package/dist/middleware/usageTracker.js +0 -11
- package/dist/middleware/usageTracker.js.map +0 -1
- package/dist/ports/entitlements.d.ts +0 -65
- package/dist/ports/entitlements.d.ts.map +0 -1
- package/dist/ports/entitlements.js +0 -2
- package/dist/ports/entitlements.js.map +0 -1
- package/dist/providers/static-entitlements.d.ts +0 -25
- package/dist/providers/static-entitlements.d.ts.map +0 -1
- package/dist/providers/static-entitlements.js +0 -55
- package/dist/providers/static-entitlements.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpError.js","sourceRoot":"","sources":["../../src/lib/httpError.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"httpError.js","sourceRoot":"","sources":["../../src/lib/httpError.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import type { AppEnv } from '../env.js';
|
|
3
|
+
import type { AdmissionAction, AdmissionDenial } from '../ports/admission.js';
|
|
4
|
+
import type { Workspace } from '../ports/auth.js';
|
|
5
|
+
/**
|
|
6
|
+
* Ask the host whether `action` may proceed. No hook, or a hook that throws,
|
|
7
|
+
* admits it: a host's metering outage must not take messaging down.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveAdmission(c: Context<AppEnv>, workspace: Workspace, action: AdmissionAction): Promise<AdmissionDenial | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Render a denial as the error envelope, with `Retry-After` when the host gave
|
|
12
|
+
* one. Without `retryAt` no retry clears the denial, so the per-minute reset
|
|
13
|
+
* `rateLimit` already set is withdrawn rather than advertised.
|
|
14
|
+
*/
|
|
15
|
+
export declare function admissionDeniedResponse(c: Context, denial: AdmissionDenial): Response & import("hono").TypedResponse<{
|
|
16
|
+
ok: false;
|
|
17
|
+
error: {
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
}, -1 | 100 | 102 | 103 | 200 | 201 | 202 | 203 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511, "json">;
|
|
22
|
+
/** Report a successful, non-replayed action to the host without holding the response. */
|
|
23
|
+
export declare function reportCommitted(c: Context<AppEnv>, workspace: Workspace, action: AdmissionAction): void;
|
|
24
|
+
/**
|
|
25
|
+
* Admit message sends through the host's `message` hook.
|
|
26
|
+
*
|
|
27
|
+
* Mounted after `rateLimit` on the routes that create a message (channel post,
|
|
28
|
+
* DM, group DM, thread reply). Idempotency is preserved: a denied request
|
|
29
|
+
* without an `Idempotency-Key` is refused here; a keyed one reaches the route
|
|
30
|
+
* so a replay of an earlier successful send still returns its stored receipt,
|
|
31
|
+
* and the route refuses only a fresh send ({@link assertMessageAdmitted},
|
|
32
|
+
* called inside the idempotent operation). Only a fresh successful send is
|
|
33
|
+
* reported as committed.
|
|
34
|
+
*/
|
|
35
|
+
export declare const admitMessage: import("hono").MiddlewareHandler<AppEnv, string, {}, Response>;
|
|
36
|
+
/**
|
|
37
|
+
* Refuse a fresh send when `admitMessage` found it denied. Call it first inside
|
|
38
|
+
* a message route's idempotent `operation`, which runs only for a new send —
|
|
39
|
+
* never for a replay of a stored receipt.
|
|
40
|
+
*/
|
|
41
|
+
export declare function assertMessageAdmitted(c: Context<AppEnv>): void;
|
|
42
|
+
//# sourceMappingURL=admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../src/middleware/admission.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAKlD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAClB,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQjC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe;;;;;;iXAW1E;AAED,yFAAyF;AACzF,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAUvG;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,gEAavB,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAG9D"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createMiddleware } from 'hono/factory';
|
|
2
|
+
import { AdmissionDeniedError } from '../lib/admissionError.js';
|
|
3
|
+
import { setRetryContract } from '../lib/throttle.js';
|
|
4
|
+
import { runInBackground } from '../routes/background.js';
|
|
5
|
+
/**
|
|
6
|
+
* Ask the host whether `action` may proceed. No hook, or a hook that throws,
|
|
7
|
+
* admits it: a host's metering outage must not take messaging down.
|
|
8
|
+
*/
|
|
9
|
+
export async function resolveAdmission(c, workspace, action) {
|
|
10
|
+
const admission = c.get('engine').admission;
|
|
11
|
+
if (!admission?.admit)
|
|
12
|
+
return null;
|
|
13
|
+
try {
|
|
14
|
+
return (await admission.admit({ workspace, action })) ?? null;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Render a denial as the error envelope, with `Retry-After` when the host gave
|
|
22
|
+
* one. Without `retryAt` no retry clears the denial, so the per-minute reset
|
|
23
|
+
* `rateLimit` already set is withdrawn rather than advertised.
|
|
24
|
+
*/
|
|
25
|
+
export function admissionDeniedResponse(c, denial) {
|
|
26
|
+
if (denial.retryAt !== undefined && Number.isFinite(denial.retryAt)) {
|
|
27
|
+
setRetryContract(c, denial.retryAt);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
c.header('X-RateLimit-Reset', undefined);
|
|
31
|
+
c.header('Retry-After', undefined);
|
|
32
|
+
}
|
|
33
|
+
return c.json({ ok: false, error: { ...denial.details, code: denial.code, message: denial.message } }, denial.status);
|
|
34
|
+
}
|
|
35
|
+
/** Report a successful, non-replayed action to the host without holding the response. */
|
|
36
|
+
export function reportCommitted(c, workspace, action) {
|
|
37
|
+
const admission = c.get('engine').admission;
|
|
38
|
+
if (!admission?.committed)
|
|
39
|
+
return;
|
|
40
|
+
if (c.res.status < 200 || c.res.status >= 300)
|
|
41
|
+
return;
|
|
42
|
+
if (c.res.headers.get('Idempotency-Replayed') === 'true')
|
|
43
|
+
return;
|
|
44
|
+
runInBackground(c, Promise.resolve().then(() => admission.committed({ workspace, action })), `admission committed: ${action}`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Admit message sends through the host's `message` hook.
|
|
48
|
+
*
|
|
49
|
+
* Mounted after `rateLimit` on the routes that create a message (channel post,
|
|
50
|
+
* DM, group DM, thread reply). Idempotency is preserved: a denied request
|
|
51
|
+
* without an `Idempotency-Key` is refused here; a keyed one reaches the route
|
|
52
|
+
* so a replay of an earlier successful send still returns its stored receipt,
|
|
53
|
+
* and the route refuses only a fresh send ({@link assertMessageAdmitted},
|
|
54
|
+
* called inside the idempotent operation). Only a fresh successful send is
|
|
55
|
+
* reported as committed.
|
|
56
|
+
*/
|
|
57
|
+
export const admitMessage = createMiddleware(async (c, next) => {
|
|
58
|
+
const workspace = c.get('workspace');
|
|
59
|
+
if (!workspace || !c.get('engine').admission) {
|
|
60
|
+
await next();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const denial = await resolveAdmission(c, workspace, 'message');
|
|
64
|
+
if (denial) {
|
|
65
|
+
if (!c.req.header('Idempotency-Key'))
|
|
66
|
+
return admissionDeniedResponse(c, denial);
|
|
67
|
+
c.set('messageAdmissionDenial', denial);
|
|
68
|
+
}
|
|
69
|
+
await next();
|
|
70
|
+
reportCommitted(c, workspace, 'message');
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* Refuse a fresh send when `admitMessage` found it denied. Call it first inside
|
|
74
|
+
* a message route's idempotent `operation`, which runs only for a new send —
|
|
75
|
+
* never for a replay of a stored receipt.
|
|
76
|
+
*/
|
|
77
|
+
export function assertMessageAdmitted(c) {
|
|
78
|
+
const denial = c.get('messageAdmissionDenial');
|
|
79
|
+
if (denial)
|
|
80
|
+
throw new AdmissionDeniedError(denial);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../../src/middleware/admission.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { AppEnv } from '../env.js';
|
|
2
|
+
/** Per-workspace requests-per-minute ceiling when the host configures none. */
|
|
3
|
+
export declare const DEFAULT_RATE_LIMIT_PER_MINUTE = 30000;
|
|
2
4
|
export declare const ROUTE_MULTIPLIERS: Record<string, number>;
|
|
3
5
|
export declare function getRouteKey(method: string, path: string): string | null;
|
|
4
6
|
export declare const rateLimit: import("hono").MiddlewareHandler<AppEnv, string, {}, Response>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rateLimit.d.ts","sourceRoot":"","sources":["../../src/middleware/rateLimit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"rateLimit.d.ts","sourceRoot":"","sources":["../../src/middleware/rateLimit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAMxC,+EAA+E;AAC/E,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAQpD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmCpD,CAAC;AAEF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8BvE;AAED,eAAO,MAAM,SAAS,gEAmDpB,CAAC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createMiddleware } from 'hono/factory';
|
|
2
2
|
import { jsonError } from '../lib/httpResponse.js';
|
|
3
3
|
import { RATE_LIMIT_WINDOW_MS, rateLimitWindow, rateLimitWindowResetAt, setRetryContract } from '../lib/throttle.js';
|
|
4
|
-
import {
|
|
4
|
+
import { admissionDeniedResponse, reportCommitted, resolveAdmission } from './admission.js';
|
|
5
5
|
import { presenceRefresh } from './presenceRefresh.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
/** Per-workspace requests-per-minute ceiling when the host configures none. */
|
|
7
|
+
export const DEFAULT_RATE_LIMIT_PER_MINUTE = 30_000;
|
|
8
|
+
function validRatePerMinute(value) {
|
|
9
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined;
|
|
10
|
+
}
|
|
11
11
|
// Per-route rate limit multipliers (fraction of the global per-minute limit).
|
|
12
12
|
// POST endpoints get tighter limits, GET endpoints get looser.
|
|
13
13
|
export const ROUTE_MULTIPLIERS = {
|
|
@@ -83,29 +83,21 @@ export const rateLimit = createMiddleware(async (c, next) => {
|
|
|
83
83
|
await next();
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
|
-
|
|
87
|
-
const planResponse = await checkApiCallPlanLimit(c, async () => {
|
|
88
|
-
planAllowed = true;
|
|
89
|
-
});
|
|
90
|
-
if (!planAllowed) {
|
|
91
|
-
return planResponse;
|
|
92
|
-
}
|
|
93
|
-
const { entitlements, rateLimiter } = c.get('engine');
|
|
86
|
+
const { admission, config, rateLimiter } = c.get('engine');
|
|
94
87
|
// Apply route-specific multiplier if applicable
|
|
95
88
|
const routeKey = getRouteKey(c.req.method, c.req.path);
|
|
96
89
|
// The rate limiter port is not workspace-scoped, so the workspace id is part
|
|
97
90
|
// of the bucket key (the Cloudflare adapter previously scoped via the DO id).
|
|
98
91
|
const now = Date.now();
|
|
99
92
|
const bucketKey = `${workspace.id}:${routeKey ?? 'global'}:${rateLimitWindow(now)}`;
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
globalLimit = FALLBACK_RATE_PER_MIN;
|
|
93
|
+
// An invalid ceiling (config or hook) or a failing hook degrades to the next
|
|
94
|
+
// valid one, never to no limit or to refusing everything.
|
|
95
|
+
let globalLimit = validRatePerMinute(config.rateLimitPerMinute) ?? DEFAULT_RATE_LIMIT_PER_MINUTE;
|
|
96
|
+
if (admission?.rateLimitPerMinute) {
|
|
97
|
+
try {
|
|
98
|
+
globalLimit = validRatePerMinute(await admission.rateLimitPerMinute(workspace)) ?? globalLimit;
|
|
99
|
+
}
|
|
100
|
+
catch { /* keep the configured ceiling */ }
|
|
109
101
|
}
|
|
110
102
|
const limit = routeKey ? Math.ceil(globalLimit * ROUTE_MULTIPLIERS[routeKey]) : globalLimit;
|
|
111
103
|
try {
|
|
@@ -118,14 +110,19 @@ export const rateLimit = createMiddleware(async (c, next) => {
|
|
|
118
110
|
// Transient by construction: the bucket is keyed to this minute, so the
|
|
119
111
|
// advertised wait is the real one.
|
|
120
112
|
setRetryContract(c, resetAt, now);
|
|
121
|
-
return jsonError(c, 'rate_limit_exceeded', `Rate limit exceeded. ${limit} requests per minute allowed
|
|
113
|
+
return jsonError(c, 'rate_limit_exceeded', `Rate limit exceeded. ${limit} requests per minute allowed.`, 429);
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
116
|
catch {
|
|
125
117
|
// Only the limiter backend failing is fail-open — a transient infra hiccup
|
|
126
118
|
// shouldn't 500 the request (the limit was still computed above).
|
|
127
119
|
}
|
|
120
|
+
// After the bucket, so a flood is throttled without reaching host admission.
|
|
121
|
+
const denial = await resolveAdmission(c, workspace, 'request');
|
|
122
|
+
if (denial)
|
|
123
|
+
return admissionDeniedResponse(c, denial);
|
|
128
124
|
await presenceRefresh(c, async () => { });
|
|
129
|
-
|
|
125
|
+
await next();
|
|
126
|
+
reportCommitted(c, workspace, 'request');
|
|
130
127
|
});
|
|
131
128
|
//# sourceMappingURL=rateLimit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../src/middleware/rateLimit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACrH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../src/middleware/rateLimit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Workspace } from './auth.js';
|
|
2
|
+
/**
|
|
3
|
+
* What an admitted request is about to do.
|
|
4
|
+
*
|
|
5
|
+
* - `request`: any authenticated, rate-limited request.
|
|
6
|
+
* - `message`: a message send (channel post, DM, group DM, thread reply).
|
|
7
|
+
*/
|
|
8
|
+
export type AdmissionAction = 'request' | 'message';
|
|
9
|
+
export interface AdmissionContext {
|
|
10
|
+
workspace: Workspace;
|
|
11
|
+
action: AdmissionAction;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A host refusal, rendered as `{ ok: false, error: { code, message, ...details } }`
|
|
15
|
+
* with `status`.
|
|
16
|
+
*/
|
|
17
|
+
export interface AdmissionDenial {
|
|
18
|
+
/** HTTP status, 4xx. */
|
|
19
|
+
status: number;
|
|
20
|
+
code: string;
|
|
21
|
+
message: string;
|
|
22
|
+
/** Additive fields on `error`, e.g. the limit that was reached. */
|
|
23
|
+
details?: Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Unix ms at which retrying can succeed; sets `Retry-After`. Omit when no
|
|
26
|
+
* retry clears the refusal.
|
|
27
|
+
*/
|
|
28
|
+
retryAt?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Host hooks for admitting and metering workspace activity.
|
|
32
|
+
*
|
|
33
|
+
* The engine enforces no quotas of its own. A host that bills or meters
|
|
34
|
+
* (the hosted product) implements these; self-host passes none, and every
|
|
35
|
+
* request is admitted. Every hook is optional, and a hook that throws admits
|
|
36
|
+
* the request.
|
|
37
|
+
*/
|
|
38
|
+
export interface AdmissionHooks {
|
|
39
|
+
/**
|
|
40
|
+
* Decide whether an action may proceed. Return a denial to refuse it, or
|
|
41
|
+
* `null`/`undefined` to admit it.
|
|
42
|
+
*
|
|
43
|
+
* A `message` denial on a request carrying an `Idempotency-Key` refuses only
|
|
44
|
+
* a fresh send: a replay of an earlier successful send still returns its
|
|
45
|
+
* stored receipt.
|
|
46
|
+
*/
|
|
47
|
+
admit?(ctx: AdmissionContext): Promise<AdmissionDenial | null | undefined>;
|
|
48
|
+
/**
|
|
49
|
+
* Called after an admitted action succeeds (2xx, not an idempotent replay).
|
|
50
|
+
* The response does not wait on it.
|
|
51
|
+
*/
|
|
52
|
+
committed?(ctx: AdmissionContext): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* The workspace's requests-per-minute ceiling. Falls back to
|
|
55
|
+
* `EngineConfig.rateLimitPerMinute` when absent or failing.
|
|
56
|
+
*/
|
|
57
|
+
rateLimitPerMinute?(workspace: Workspace): Promise<number>;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../src/ports/admission.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAE3E;;;OAGG;IACH,SAAS,CAAC,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;OAGG;IACH,kBAAkB,CAAC,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../../src/ports/admission.ts"],"names":[],"mappings":""}
|
package/dist/ports/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - **Ports** — infrastructure the engine needs (db, realtime, presence, rate
|
|
10
10
|
* limiting, file blobs, key/value).
|
|
11
11
|
* - **Providers** — the open-core "hosting" seam the cloud layer overrides
|
|
12
|
-
* (auth,
|
|
12
|
+
* (auth, admission, telemetry). Each ships an OSS default or is optional.
|
|
13
13
|
*/
|
|
14
14
|
export type { EngineDb, TransactionCapability, BatchCapability, AtomicWrite, AtomicWriteBuilder, AtomicWriteInput, } from './database.js';
|
|
15
15
|
export { runAtomic, runAtomicWrites } from './database.js';
|
|
@@ -21,7 +21,7 @@ export type { FileStorage } from './files.js';
|
|
|
21
21
|
export type { KeyValueStore } from './kv.js';
|
|
22
22
|
export type { EventQueue, QueuedEvent } from './event-queue.js';
|
|
23
23
|
export type { AuthProvider, AuthResult, AuthRequire, Workspace, Agent, } from './auth.js';
|
|
24
|
-
export type {
|
|
24
|
+
export type { AdmissionAction, AdmissionContext, AdmissionDenial, AdmissionHooks, } from './admission.js';
|
|
25
25
|
export { ENGINE_OBSERVATION_FACTS } from './telemetry.js';
|
|
26
26
|
export type { TelemetrySink, TelemetryEvent, EngineObservation, EngineObservationKind, EngineObservationFacts } from './telemetry.js';
|
|
27
27
|
export type { EngineLogRecord, EngineLogExport } from './logging.js';
|
|
@@ -33,7 +33,7 @@ import type { FileStorage } from './files.js';
|
|
|
33
33
|
import type { KeyValueStore } from './kv.js';
|
|
34
34
|
import type { EventQueue } from './event-queue.js';
|
|
35
35
|
import type { AuthProvider } from './auth.js';
|
|
36
|
-
import type {
|
|
36
|
+
import type { AdmissionHooks } from './admission.js';
|
|
37
37
|
import type { TelemetrySink } from './telemetry.js';
|
|
38
38
|
import type { EngineLogExport } from './logging.js';
|
|
39
39
|
/** Infrastructure ports the engine reads off the request context. */
|
|
@@ -51,7 +51,8 @@ export interface EnginePorts {
|
|
|
51
51
|
/** The open-core hosting seam — each has an OSS default in `../auth`, etc. */
|
|
52
52
|
export interface EngineProviders {
|
|
53
53
|
auth: AuthProvider;
|
|
54
|
-
|
|
54
|
+
/** Host admission and metering hooks. Omitted: every request is admitted. */
|
|
55
|
+
admission?: AdmissionHooks;
|
|
55
56
|
telemetry?: TelemetrySink;
|
|
56
57
|
}
|
|
57
58
|
/** Everything `createEngine` needs. */
|
|
@@ -102,6 +103,11 @@ export interface EngineConfig {
|
|
|
102
103
|
* narrowly scoped recovery capability and the secret remains server-only.
|
|
103
104
|
*/
|
|
104
105
|
workspaceBootstrapProofRequired?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Per-workspace requests-per-minute ceiling. Default 30,000.
|
|
108
|
+
* `AdmissionHooks.rateLimitPerMinute` overrides it per workspace.
|
|
109
|
+
*/
|
|
110
|
+
rateLimitPerMinute?: number;
|
|
105
111
|
/**
|
|
106
112
|
* Opt-in for the self-serve `POST /v1/workspace/rotate-key` route. Defaults
|
|
107
113
|
* to disabled: the route mints a live workspace credential, so a deployment
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ports/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,YAAY,EACV,QAAQ,EACR,qBAAqB,EACrB,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC3D,YAAY,EACV,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,sBAAsB,EACtB,WAAW,EACX,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,YAAY,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,SAAS,EACT,KAAK,GACN,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ports/index.ts"],"names":[],"mappings":"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"}
|
package/dist/ports/kv.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Key/value store port — replaces the Cloudflare KV namespace.
|
|
3
3
|
*
|
|
4
|
-
* Used for idempotency records/locks (`middleware/idempotency.ts`)
|
|
5
|
-
* counters (`middleware/planLimits.ts`, `middleware/usageTracker.ts`). The surface
|
|
4
|
+
* Used for idempotency records/locks (`middleware/idempotency.ts`). The surface
|
|
6
5
|
* is intentionally the small subset of `KVNamespace` the engine actually calls, so
|
|
7
6
|
* a Cloudflare `KVNamespace` is structurally assignable to it. The Node adapter
|
|
8
7
|
* implements it with an in-memory map (TTL via timestamps) or a SQLite table.
|
|
@@ -13,19 +12,5 @@ export interface KeyValueStore {
|
|
|
13
12
|
expirationTtl?: number;
|
|
14
13
|
}): Promise<void>;
|
|
15
14
|
delete(key: string): Promise<void>;
|
|
16
|
-
/**
|
|
17
|
-
* Atomically add `delta` to the integer value at `key` (treating a missing or
|
|
18
|
-
* non-numeric value as 0) and return the new total. Exists because usage
|
|
19
|
-
* counters were previously a racy get→parse→put read-modify-write that lost
|
|
20
|
-
* concurrent increments. Adapters must implement this without a lost-update
|
|
21
|
-
* window (the Cloudflare adapter routes it through a Durable Object).
|
|
22
|
-
*
|
|
23
|
-
* `ttlSeconds` sets the expiry when the key is first created (an existing
|
|
24
|
-
* key keeps its expiry, so a counter isn't extended by its own traffic).
|
|
25
|
-
* Adapters that can't express a TTL may ignore it: period-scoped counters
|
|
26
|
-
* carry their period in the key, so ignoring it only leaks a dead key rather
|
|
27
|
-
* than breaking the reset.
|
|
28
|
-
*/
|
|
29
|
-
increment(key: string, delta: number, ttlSeconds?: number): Promise<number>;
|
|
30
15
|
}
|
|
31
16
|
//# sourceMappingURL=kv.d.ts.map
|
package/dist/ports/kv.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../../src/ports/kv.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../../src/ports/kv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC"}
|
|
@@ -17,15 +17,14 @@ export interface WorkspaceDeliveryPolicyConfig {
|
|
|
17
17
|
reserve?: number;
|
|
18
18
|
} | undefined>;
|
|
19
19
|
/**
|
|
20
|
-
* Server-only async resolver for dynamic, request-time
|
|
21
|
-
*
|
|
22
|
-
* static `cap`/`workspaces` fields, so a host
|
|
20
|
+
* Server-only async resolver for a dynamic, request-time policy (e.g. one
|
|
21
|
+
* keyed by the host's own tier for the workspace). When present it takes
|
|
22
|
+
* precedence over the static `cap`/`workspaces` fields, so a host does not
|
|
23
23
|
* have to flatten every workspace into static config. Never source this from
|
|
24
24
|
* a client request.
|
|
25
25
|
*/
|
|
26
26
|
resolve?: (workspace: {
|
|
27
27
|
id: string;
|
|
28
|
-
plan: string;
|
|
29
28
|
}) => Promise<WorkspaceDeliveryPolicy | undefined>;
|
|
30
29
|
}
|
|
31
30
|
//# sourceMappingURL=workspaceDelivery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaceDelivery.d.ts","sourceRoot":"","sources":["../../src/ports/workspaceDelivery.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,6BAA6B;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IAC5E;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"workspaceDelivery.d.ts","sourceRoot":"","sources":["../../src/ports/workspaceDelivery.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,6BAA6B;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IAC5E;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAAC;CACvF"}
|
package/dist/routes/dm.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Hono } from 'hono';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { requireAgentToken } from '../middleware/auth.js';
|
|
4
4
|
import { rateLimit } from '../middleware/rateLimit.js';
|
|
5
|
-
import {
|
|
5
|
+
import { admitMessage, assertMessageAdmitted } from '../middleware/admission.js';
|
|
6
6
|
import { jsonIdempotentOk, parseIdempotencyKey, runIdempotent } from '../middleware/idempotency.js';
|
|
7
7
|
import { sha256Hex } from '../lib/crypto.js';
|
|
8
8
|
import * as dmEngine from '../engine/dm.js';
|
|
@@ -36,7 +36,7 @@ const listDmConversationsQuerySchema = z.object({
|
|
|
36
36
|
limit: positiveIntQueryParam({ max: 100 }),
|
|
37
37
|
});
|
|
38
38
|
// POST /v1/dm - send a DM
|
|
39
|
-
dmRoutes.post('/dm', requireAgentToken, rateLimit,
|
|
39
|
+
dmRoutes.post('/dm', requireAgentToken, rateLimit, admitMessage, async (c) => {
|
|
40
40
|
try {
|
|
41
41
|
const db = c.get('db');
|
|
42
42
|
const workspace = c.get('workspace');
|
|
@@ -119,7 +119,7 @@ dmRoutes.post('/dm', requireAgentToken, rateLimit, checkMessageAllowance, async
|
|
|
119
119
|
ttlSecondsForResult: (result) => result._idempotency_ttl_seconds,
|
|
120
120
|
kv: c.get('engine').kv,
|
|
121
121
|
operation: async () => {
|
|
122
|
-
|
|
122
|
+
assertMessageAdmitted(c);
|
|
123
123
|
const hasWebhookSubscriptions = await shouldEnqueueWebhookEvent(c, workspace.id, 'dm.received');
|
|
124
124
|
return dmEngine.sendDm(db, workspace.id, agent.id, {
|
|
125
125
|
to,
|
package/dist/routes/dm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dm.js","sourceRoot":"","sources":["../../src/routes/dm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"dm.js","sourceRoot":"","sources":["../../src/routes/dm.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/groupDm.js
CHANGED
|
@@ -3,7 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { errorResponse } from '../lib/httpError.js';
|
|
4
4
|
import { requireAgentToken } from '../middleware/auth.js';
|
|
5
5
|
import { rateLimit } from '../middleware/rateLimit.js';
|
|
6
|
-
import {
|
|
6
|
+
import { admitMessage, assertMessageAdmitted } from '../middleware/admission.js';
|
|
7
7
|
import { jsonIdempotentOk, parseIdempotencyKey, runIdempotent } from '../middleware/idempotency.js';
|
|
8
8
|
import * as groupDmEngine from '../engine/groupDm.js';
|
|
9
9
|
import { resolveMailboxConfig } from '../engine/mailboxConfig.js';
|
|
@@ -54,7 +54,7 @@ groupDmRoutes.post('/dm/group', requireAgentToken, rateLimit, async (c) => {
|
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
// POST /v1/dm/:conversation_id/messages - post to group DM
|
|
57
|
-
groupDmRoutes.post('/dm/:conversation_id/messages', requireAgentToken, rateLimit,
|
|
57
|
+
groupDmRoutes.post('/dm/:conversation_id/messages', requireAgentToken, rateLimit, admitMessage, async (c) => {
|
|
58
58
|
try {
|
|
59
59
|
const db = c.get('db');
|
|
60
60
|
const workspace = c.get('workspace');
|
|
@@ -127,7 +127,7 @@ groupDmRoutes.post('/dm/:conversation_id/messages', requireAgentToken, rateLimit
|
|
|
127
127
|
compatibleFingerprints: legacyFingerprint === fingerprint ? [] : [legacyFingerprint],
|
|
128
128
|
kv: c.get('engine').kv,
|
|
129
129
|
operation: async () => {
|
|
130
|
-
|
|
130
|
+
assertMessageAdmitted(c);
|
|
131
131
|
return groupDmEngine.postGroupMessage(db, workspace.id, conversationId, agent.id, {
|
|
132
132
|
text,
|
|
133
133
|
attachments: normalizedAttachments,
|