@relaycast/engine 12.2.0 → 12.3.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/actor/credential-tag.d.ts +14 -0
- package/dist/adapters/actor/credential-tag.d.ts.map +1 -0
- package/dist/adapters/actor/credential-tag.js +30 -0
- package/dist/adapters/actor/credential-tag.js.map +1 -0
- package/dist/adapters/actor/database.d.ts +50 -0
- package/dist/adapters/actor/database.d.ts.map +1 -0
- package/dist/adapters/actor/database.js +86 -0
- package/dist/adapters/actor/database.js.map +1 -0
- package/dist/adapters/actor/ephemeral-outbox.d.ts +16 -0
- package/dist/adapters/actor/ephemeral-outbox.d.ts.map +1 -0
- package/dist/adapters/actor/ephemeral-outbox.js +53 -0
- package/dist/adapters/actor/ephemeral-outbox.js.map +1 -0
- package/dist/adapters/actor/event-queue.d.ts +23 -0
- package/dist/adapters/actor/event-queue.d.ts.map +1 -0
- package/dist/adapters/actor/event-queue.js +31 -0
- package/dist/adapters/actor/event-queue.js.map +1 -0
- package/dist/adapters/actor/files.d.ts +66 -0
- package/dist/adapters/actor/files.d.ts.map +1 -0
- package/dist/adapters/actor/files.js +83 -0
- package/dist/adapters/actor/files.js.map +1 -0
- package/dist/adapters/actor/http.d.ts +19 -0
- package/dist/adapters/actor/http.d.ts.map +1 -0
- package/dist/adapters/actor/http.js +2 -0
- package/dist/adapters/actor/http.js.map +1 -0
- package/dist/adapters/actor/index.d.ts +90 -0
- package/dist/adapters/actor/index.d.ts.map +1 -0
- package/dist/adapters/actor/index.js +299 -0
- package/dist/adapters/actor/index.js.map +1 -0
- package/dist/adapters/actor/kv.d.ts +21 -0
- package/dist/adapters/actor/kv.d.ts.map +1 -0
- package/dist/adapters/actor/kv.js +33 -0
- package/dist/adapters/actor/kv.js.map +1 -0
- package/dist/adapters/actor/migrations.d.ts +15 -0
- package/dist/adapters/actor/migrations.d.ts.map +1 -0
- package/dist/adapters/actor/migrations.generated.d.ts +5 -0
- package/dist/adapters/actor/migrations.generated.d.ts.map +1 -0
- package/dist/adapters/actor/migrations.generated.js +842 -0
- package/dist/adapters/actor/migrations.generated.js.map +1 -0
- package/dist/adapters/actor/migrations.js +32 -0
- package/dist/adapters/actor/migrations.js.map +1 -0
- package/dist/adapters/node/files.d.ts +2 -0
- package/dist/adapters/node/files.d.ts.map +1 -1
- package/dist/adapters/node/files.js +31 -3
- package/dist/adapters/node/files.js.map +1 -1
- package/dist/adapters/node/index.js +1 -1
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/auth/credentialTags.d.ts +43 -0
- package/dist/auth/credentialTags.d.ts.map +1 -0
- package/dist/auth/credentialTags.js +106 -0
- package/dist/auth/credentialTags.js.map +1 -0
- package/dist/auth/credentials.d.ts +103 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +147 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/index.d.ts +7 -4
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +115 -61
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/tokenKind.d.ts +17 -26
- package/dist/auth/tokenKind.d.ts.map +1 -1
- package/dist/auth/tokenKind.js +17 -46
- package/dist/auth/tokenKind.js.map +1 -1
- package/dist/auth/workspaceExpiry.d.ts +2 -0
- package/dist/auth/workspaceExpiry.d.ts.map +1 -1
- package/dist/auth/workspaceExpiry.js +7 -0
- package/dist/auth/workspaceExpiry.js.map +1 -1
- package/dist/bin/secretEnv.d.ts +17 -0
- package/dist/bin/secretEnv.d.ts.map +1 -0
- package/dist/bin/secretEnv.js +33 -0
- package/dist/bin/secretEnv.js.map +1 -0
- package/dist/bin/serve.js +42 -4
- package/dist/bin/serve.js.map +1 -1
- package/dist/config/credentialEnv.d.ts +19 -0
- package/dist/config/credentialEnv.d.ts.map +1 -0
- package/dist/config/credentialEnv.js +53 -0
- package/dist/config/credentialEnv.js.map +1 -0
- package/dist/db/migrations/0078_dm_participant_read_cursor.sql +15 -0
- package/dist/db/migrations/0079_credential_upgrades.sql +17 -0
- package/dist/db/schema.d.ts +183 -2
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +23 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/engine/a2a.d.ts +1 -1
- package/dist/engine/a2a.d.ts.map +1 -1
- package/dist/engine/a2a.js +2 -2
- package/dist/engine/a2a.js.map +1 -1
- package/dist/engine/a2aEgress.d.ts +3 -2
- package/dist/engine/a2aEgress.d.ts.map +1 -1
- package/dist/engine/a2aEgress.js +5 -4
- package/dist/engine/a2aEgress.js.map +1 -1
- package/dist/engine/action.d.ts +12 -0
- package/dist/engine/action.d.ts.map +1 -1
- package/dist/engine/action.js +45 -1
- package/dist/engine/action.js.map +1 -1
- package/dist/engine/agent.d.ts.map +1 -1
- package/dist/engine/agent.js +2 -1
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/agentIdentity.d.ts.map +1 -1
- package/dist/engine/agentIdentity.js +2 -1
- package/dist/engine/agentIdentity.js.map +1 -1
- package/dist/engine/credentialUpgrade.d.ts +48 -0
- package/dist/engine/credentialUpgrade.d.ts.map +1 -0
- package/dist/engine/credentialUpgrade.js +176 -0
- package/dist/engine/credentialUpgrade.js.map +1 -0
- package/dist/engine/delivery.d.ts.map +1 -1
- package/dist/engine/delivery.js +70 -31
- package/dist/engine/delivery.js.map +1 -1
- package/dist/engine/eventDispatch.d.ts.map +1 -1
- package/dist/engine/eventDispatch.js +3 -2
- package/dist/engine/eventDispatch.js.map +1 -1
- package/dist/engine/eventSubscription.d.ts +4 -4
- package/dist/engine/file.d.ts +8 -0
- package/dist/engine/file.d.ts.map +1 -1
- package/dist/engine/file.js +18 -5
- package/dist/engine/file.js.map +1 -1
- package/dist/engine/inboundWebhook.d.ts +2 -0
- package/dist/engine/inboundWebhook.d.ts.map +1 -1
- package/dist/engine/inboundWebhook.js +10 -4
- package/dist/engine/inboundWebhook.js.map +1 -1
- package/dist/engine/inbox.d.ts.map +1 -1
- package/dist/engine/inbox.js +10 -5
- package/dist/engine/inbox.js.map +1 -1
- package/dist/engine/internalAdmin.d.ts +80 -0
- package/dist/engine/internalAdmin.d.ts.map +1 -0
- package/dist/engine/internalAdmin.js +329 -0
- package/dist/engine/internalAdmin.js.map +1 -0
- package/dist/engine/invocationCompletion.d.ts.map +1 -1
- package/dist/engine/invocationCompletion.js +23 -5
- package/dist/engine/invocationCompletion.js.map +1 -1
- package/dist/engine/node.d.ts +38 -1
- package/dist/engine/node.d.ts.map +1 -1
- package/dist/engine/node.js +166 -11
- package/dist/engine/node.js.map +1 -1
- package/dist/engine/nodeContext.d.ts +2 -1
- package/dist/engine/nodeContext.d.ts.map +1 -1
- package/dist/engine/nodeContext.js +1 -1
- package/dist/engine/nodeContext.js.map +1 -1
- package/dist/engine/nodeDeliver.d.ts +2 -1
- package/dist/engine/nodeDeliver.d.ts.map +1 -1
- package/dist/engine/nodeDeliver.js +1 -1
- package/dist/engine/nodeDeliver.js.map +1 -1
- package/dist/engine/observerToken.d.ts +4 -0
- package/dist/engine/observerToken.d.ts.map +1 -1
- package/dist/engine/observerToken.js +14 -5
- package/dist/engine/observerToken.js.map +1 -1
- package/dist/engine/receipt.d.ts +100 -0
- package/dist/engine/receipt.d.ts.map +1 -1
- package/dist/engine/receipt.js +12 -0
- package/dist/engine/receipt.js.map +1 -1
- package/dist/engine/taskInvocation.d.ts +1 -1
- package/dist/engine/tokenRotate.d.ts.map +1 -1
- package/dist/engine/tokenRotate.js +4 -3
- package/dist/engine/tokenRotate.js.map +1 -1
- package/dist/engine/workspace.d.ts +8 -2
- package/dist/engine/workspace.d.ts.map +1 -1
- package/dist/engine/workspace.js +70 -21
- package/dist/engine/workspace.js.map +1 -1
- package/dist/engine/wsAuth.d.ts.map +1 -1
- package/dist/engine/wsAuth.js +14 -3
- package/dist/engine/wsAuth.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +31 -0
- package/dist/engine.js.map +1 -1
- package/dist/entrypoints/node.d.ts +3 -1
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +33 -1
- package/dist/entrypoints/node.js.map +1 -1
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/gateway.d.ts +11 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +16 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/credentialNotice.d.ts +32 -0
- package/dist/lib/credentialNotice.d.ts.map +1 -0
- package/dist/lib/credentialNotice.js +76 -0
- package/dist/lib/credentialNotice.js.map +1 -0
- package/dist/lib/fileTokens.d.ts +30 -0
- package/dist/lib/fileTokens.d.ts.map +1 -0
- package/dist/lib/fileTokens.js +76 -0
- package/dist/lib/fileTokens.js.map +1 -0
- package/dist/lib/httpError.d.ts +1 -1
- package/dist/lib/httpResponse.d.ts +6 -6
- package/dist/middleware/admission.d.ts +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +22 -31
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +1 -1
- package/dist/middleware/logger.d.ts.map +1 -1
- package/dist/middleware/logger.js +4 -1
- package/dist/middleware/logger.js.map +1 -1
- package/dist/ports/database.d.ts.map +1 -1
- package/dist/ports/database.js +8 -2
- package/dist/ports/database.js.map +1 -1
- package/dist/ports/files.d.ts +7 -1
- package/dist/ports/files.d.ts.map +1 -1
- package/dist/ports/index.d.ts +64 -1
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +4 -0
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/telemetry.d.ts +1 -0
- package/dist/ports/telemetry.d.ts.map +1 -1
- package/dist/ports/telemetry.js +1 -0
- package/dist/ports/telemetry.js.map +1 -1
- package/dist/routes/action.d.ts.map +1 -1
- package/dist/routes/action.js +2 -1
- package/dist/routes/action.js.map +1 -1
- package/dist/routes/credential.d.ts +4 -0
- package/dist/routes/credential.d.ts.map +1 -0
- package/dist/routes/credential.js +97 -0
- package/dist/routes/credential.js.map +1 -0
- package/dist/routes/file.js +10 -4
- package/dist/routes/file.js.map +1 -1
- package/dist/routes/inboundWebhook.d.ts.map +1 -1
- package/dist/routes/inboundWebhook.js +11 -2
- package/dist/routes/inboundWebhook.js.map +1 -1
- package/dist/routes/internal.d.ts +14 -0
- package/dist/routes/internal.d.ts.map +1 -0
- package/dist/routes/internal.js +157 -0
- package/dist/routes/internal.js.map +1 -0
- package/dist/routes/node.d.ts.map +1 -1
- package/dist/routes/node.js +44 -2
- package/dist/routes/node.js.map +1 -1
- package/dist/routes/observerToken.js +1 -1
- package/dist/routes/observerToken.js.map +1 -1
- package/dist/routes/reaction.d.ts.map +1 -1
- package/dist/routes/reaction.js +3 -2
- package/dist/routes/reaction.js.map +1 -1
- package/dist/routes/receipt.d.ts.map +1 -1
- package/dist/routes/receipt.js +2 -1
- package/dist/routes/receipt.js.map +1 -1
- package/dist/routes/workspace.d.ts.map +1 -1
- package/dist/routes/workspace.js +12 -1
- package/dist/routes/workspace.js.map +1 -1
- package/package.json +12 -3
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { parseCredential } from '@relaycast/types';
|
|
3
|
+
import { eq } from 'drizzle-orm';
|
|
4
|
+
import { WORKSPACE_EXPIRED_CODE, WORKSPACE_EXPIRED_MESSAGE, authenticateUnexpired, isWorkspaceExpired, } from '../auth/workspaceExpiry.js';
|
|
5
|
+
import { workspaces } from '../db/schema.js';
|
|
6
|
+
import { DEFAULT_LEGACY_CREDENTIAL_GRACE_SECONDS, upgradeLegacyCredential, webhookForToken, } from '../engine/credentialUpgrade.js';
|
|
7
|
+
import { jsonError, jsonOk } from '../lib/httpResponse.js';
|
|
8
|
+
import { errorResponse } from '../lib/httpError.js';
|
|
9
|
+
import { noteAuthenticatedCredential } from '../lib/credentialNotice.js';
|
|
10
|
+
import { rateLimitWindow, rateLimitWindowResetAt, setRetryContract } from '../lib/throttle.js';
|
|
11
|
+
export const credentialRoutes = new Hono();
|
|
12
|
+
/** Upgrades per principal per minute. */
|
|
13
|
+
const UPGRADES_PER_MINUTE = 10;
|
|
14
|
+
const RATE_LIMIT_WINDOW_MS = 60_000;
|
|
15
|
+
const REQUIRE = {
|
|
16
|
+
workspace: 'workspace',
|
|
17
|
+
agent: 'agent',
|
|
18
|
+
node: 'node',
|
|
19
|
+
observer: 'observer',
|
|
20
|
+
};
|
|
21
|
+
// POST /v1/credentials/upgrade - exchange a legacy credential for an ar_ one
|
|
22
|
+
// standing for the same principal. The legacy credential keeps working for
|
|
23
|
+
// EngineConfig.legacyCredentialGraceSeconds (default 30 days). Workspace keys
|
|
24
|
+
// upgrade only where the engine owns them (EngineConfig.allowWorkspaceKeyRotation).
|
|
25
|
+
credentialRoutes.post('/credentials/upgrade', async (c) => {
|
|
26
|
+
try {
|
|
27
|
+
const header = c.req.header('Authorization');
|
|
28
|
+
const token = header?.startsWith('Bearer ') ? header.slice(7) : undefined;
|
|
29
|
+
if (!token)
|
|
30
|
+
return jsonError(c, 'unauthorized', 'Missing or invalid Authorization header', 401);
|
|
31
|
+
const parsed = parseCredential(token);
|
|
32
|
+
if (!parsed)
|
|
33
|
+
return jsonError(c, 'unauthorized', 'Invalid token format', 401);
|
|
34
|
+
if (parsed.family === 'ar') {
|
|
35
|
+
return jsonError(c, 'credential_not_legacy', 'This credential is already an ar_ credential', 409);
|
|
36
|
+
}
|
|
37
|
+
const db = c.get('db');
|
|
38
|
+
let principal;
|
|
39
|
+
if (parsed.kind === 'webhook') {
|
|
40
|
+
const webhook = await webhookForToken(db, token);
|
|
41
|
+
if (!webhook)
|
|
42
|
+
return jsonError(c, 'webhook_token_invalid', 'Invalid webhook token', 401);
|
|
43
|
+
// The same expiry gate every other kind passes through authenticateUnexpired.
|
|
44
|
+
const [workspace] = await db.select({ expiresAt: workspaces.expiresAt }).from(workspaces)
|
|
45
|
+
.where(eq(workspaces.id, webhook.workspaceId));
|
|
46
|
+
if (!workspace || isWorkspaceExpired(workspace)) {
|
|
47
|
+
return jsonError(c, WORKSPACE_EXPIRED_CODE, WORKSPACE_EXPIRED_MESSAGE, 401);
|
|
48
|
+
}
|
|
49
|
+
principal = { id: webhook.id, workspaceId: webhook.workspaceId, currentHash: webhook.tokenHash };
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const result = await authenticateUnexpired(c.get('engine').auth, { token, require: REQUIRE[parsed.kind], db });
|
|
53
|
+
if (!result.ok)
|
|
54
|
+
return jsonError(c, result.code, result.message, result.status);
|
|
55
|
+
const row = parsed.kind === 'workspace' ? { id: result.workspace.id, tokenHash: result.workspace.apiKeyHash }
|
|
56
|
+
: parsed.kind === 'agent' ? result.agent
|
|
57
|
+
: parsed.kind === 'node' ? result.node
|
|
58
|
+
: result.observerToken;
|
|
59
|
+
if (!row)
|
|
60
|
+
return jsonError(c, 'unauthorized', 'Invalid token format', 401);
|
|
61
|
+
principal = { id: row.id, workspaceId: result.workspace.id, currentHash: 'tokenHash' in row ? row.tokenHash : null };
|
|
62
|
+
}
|
|
63
|
+
noteAuthenticatedCredential(c, token, principal.workspaceId);
|
|
64
|
+
// A workspace key owned by an external control plane is replaced there and
|
|
65
|
+
// pushed here; one minted here would be unknown to that plane, and its next
|
|
66
|
+
// push would invalidate it.
|
|
67
|
+
if (parsed.kind === 'workspace' && !c.get('engine').config.allowWorkspaceKeyRotation) {
|
|
68
|
+
return jsonError(c, 'workspace_key_rotation_disabled', 'Workspace key upgrade is disabled on this deployment; upgrade through the managing control plane', 403);
|
|
69
|
+
}
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
const bucketKey = `credential-upgrade:${parsed.kind}:${principal.id}:${rateLimitWindow(now)}`;
|
|
72
|
+
const limit = await c.get('engine').rateLimiter
|
|
73
|
+
.check({ bucketKey, limit: UPGRADES_PER_MINUTE, windowMs: RATE_LIMIT_WINDOW_MS })
|
|
74
|
+
.catch(() => ({ allowed: true }));
|
|
75
|
+
if (!limit.allowed) {
|
|
76
|
+
setRetryContract(c, rateLimitWindowResetAt(now), now);
|
|
77
|
+
return jsonError(c, 'rate_limit_exceeded', `Rate limit exceeded. ${UPGRADES_PER_MINUTE} upgrades per minute allowed.`, 429);
|
|
78
|
+
}
|
|
79
|
+
const upgraded = await upgradeLegacyCredential(db, {
|
|
80
|
+
legacyToken: token,
|
|
81
|
+
kind: parsed.kind,
|
|
82
|
+
principalId: principal.id,
|
|
83
|
+
workspaceId: principal.workspaceId,
|
|
84
|
+
currentHash: principal.currentHash,
|
|
85
|
+
graceSeconds: c.get('engine').config.legacyCredentialGraceSeconds ?? DEFAULT_LEGACY_CREDENTIAL_GRACE_SECONDS,
|
|
86
|
+
});
|
|
87
|
+
return jsonOk(c, {
|
|
88
|
+
credential: upgraded.credential,
|
|
89
|
+
kind: upgraded.kind,
|
|
90
|
+
legacy_expires_at: upgraded.legacyExpiresAt.toISOString(),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
return errorResponse(c, err);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../../src/routes/credential.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/file.js
CHANGED
|
@@ -15,7 +15,7 @@ export const fileRoutes = new Hono();
|
|
|
15
15
|
const fileUploadSchema = z.object({
|
|
16
16
|
filename: z.string().min(1),
|
|
17
17
|
content_type: z.string().min(1),
|
|
18
|
-
size_bytes: z.number().
|
|
18
|
+
size_bytes: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
19
19
|
});
|
|
20
20
|
const listFilesQuerySchema = LimitQuerySchema.extend({
|
|
21
21
|
uploaded_by: z.string().optional(),
|
|
@@ -23,13 +23,15 @@ const listFilesQuerySchema = LimitQuerySchema.extend({
|
|
|
23
23
|
function uploadInvalidMessage(failure) {
|
|
24
24
|
const hasFilenameIssue = failure.error.issues.some((issue) => issue.path[0] === 'filename');
|
|
25
25
|
const hasContentTypeIssue = failure.error.issues.some((issue) => issue.path[0] === 'content_type');
|
|
26
|
-
const
|
|
26
|
+
const sizeBytesIssue = failure.error.issues.find((issue) => issue.path[0] === 'size_bytes');
|
|
27
27
|
return hasFilenameIssue
|
|
28
28
|
? 'filename is required'
|
|
29
29
|
: hasContentTypeIssue
|
|
30
30
|
? 'content_type is required'
|
|
31
|
-
:
|
|
32
|
-
? '
|
|
31
|
+
: sizeBytesIssue
|
|
32
|
+
? (sizeBytesIssue.code === 'invalid_type' && sizeBytesIssue.expected !== 'int'
|
|
33
|
+
? 'size_bytes is required'
|
|
34
|
+
: 'size_bytes must be a positive integer')
|
|
33
35
|
: 'invalid upload body';
|
|
34
36
|
}
|
|
35
37
|
// POST /v1/files/upload — Returns presigned PUT URL
|
|
@@ -44,6 +46,10 @@ fileRoutes.post('/files/upload', requireAgentToken, rateLimit, async (c) => {
|
|
|
44
46
|
return parsed.response;
|
|
45
47
|
}
|
|
46
48
|
const { filename, content_type, size_bytes } = parsed.data;
|
|
49
|
+
const maxUploadBytes = c.get('engine').config.maxUploadBytes;
|
|
50
|
+
if (maxUploadBytes !== undefined && size_bytes > maxUploadBytes) {
|
|
51
|
+
return jsonError(c, 'file_too_large', `size_bytes exceeds the ${maxUploadBytes}-byte upload limit`, 413);
|
|
52
|
+
}
|
|
47
53
|
const result = await fileEngine.createUpload(db, storage, workspace.id, agent.id, { filename, content_type, size_bytes });
|
|
48
54
|
emitServerEvent(c, workspace.id, 'file.upload.requested', {
|
|
49
55
|
file_id: result.id,
|
package/dist/routes/file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/routes/file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,WAAW,EACX,SAAS,EACT,aAAa,EACb,YAAY,EACZ,MAAM,EACN,aAAa,EACb,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,IAAI,EAAU,CAAC;AAE7C,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/routes/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inboundWebhook.d.ts","sourceRoot":"","sources":["../../src/routes/inboundWebhook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"inboundWebhook.d.ts","sourceRoot":"","sources":["../../src/routes/inboundWebhook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AA0BxC,eAAO,MAAM,oBAAoB,qDAAqB,CAAC"}
|
|
@@ -14,7 +14,10 @@ import { routeDeliveryOutcomes } from './deliveryRouting.js';
|
|
|
14
14
|
import { runInBackground } from './background.js';
|
|
15
15
|
import { sendWebhookEvent } from './webhookOutbox.js';
|
|
16
16
|
import { emitServerEvent } from '../lib/serverTelemetry.js';
|
|
17
|
-
import {
|
|
17
|
+
import { noteAuthenticatedCredential } from '../lib/credentialNotice.js';
|
|
18
|
+
import { acceptsOnlyAr } from '../auth/credentials.js';
|
|
19
|
+
import { parseCredential } from '@relaycast/types';
|
|
20
|
+
import { jsonCreated, jsonError, jsonNoContent, jsonNotFound, jsonOk, parseJsonBody, } from '../lib/httpResponse.js';
|
|
18
21
|
export const inboundWebhookRoutes = new Hono();
|
|
19
22
|
const createInboundWebhookSchema = z.object({
|
|
20
23
|
name: z.string().min(1).optional(),
|
|
@@ -99,6 +102,9 @@ inboundWebhookRoutes.post('/hooks/:webhookId', async (c) => {
|
|
|
99
102
|
try {
|
|
100
103
|
const db = c.get('db');
|
|
101
104
|
const token = extractBearerToken(c.req.header('Authorization'));
|
|
105
|
+
if (token && acceptsOnlyAr(db) && parseCredential(token)?.family !== 'ar') {
|
|
106
|
+
return jsonError(c, 'webhook_token_invalid', 'Invalid webhook bearer token', 401);
|
|
107
|
+
}
|
|
102
108
|
const parsed = await parseJsonBody(c, triggerInboundWebhookSchema, 'invalid webhook payload');
|
|
103
109
|
if (!parsed.ok) {
|
|
104
110
|
return parsed.response;
|
|
@@ -124,7 +130,10 @@ inboundWebhookRoutes.post('/hooks/:webhookId', async (c) => {
|
|
|
124
130
|
if (!result) {
|
|
125
131
|
return jsonNotFound(c, 'webhook_not_found', 'Webhook not found or inactive');
|
|
126
132
|
}
|
|
127
|
-
|
|
133
|
+
// Only a token the webhook required and verified authenticated this call.
|
|
134
|
+
if (token && result._token_verified)
|
|
135
|
+
noteAuthenticatedCredential(c, token, result.workspace_id);
|
|
136
|
+
const { workspace_id, channel_id, agent_id, _deliveries, _delivery_rejections, _token_verified, ...responseData } = result;
|
|
128
137
|
const eventData = { ...responseData, id: responseData.message_id, channel_id, agent_id };
|
|
129
138
|
const messageEventData = buildMessageCreatedEventData(eventData, { channelName: result.channel, fromName: result.author });
|
|
130
139
|
runInBackground(c, routeDeliveryOutcomes(c, _deliveries, 'message.created', messageEventData, { workspaceId: workspace_id }), 'route webhook deliveries');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inboundWebhook.js","sourceRoot":"","sources":["../../src/routes/inboundWebhook.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"inboundWebhook.js","sourceRoot":"","sources":["../../src/routes/inboundWebhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { AppEnv } from '../env.js';
|
|
3
|
+
/**
|
|
4
|
+
* Internal admin API for a trusted control plane (self-host).
|
|
5
|
+
*
|
|
6
|
+
* Mounted at `/internal`. Enabled only when `config.internalSecret` is set
|
|
7
|
+
* (RELAYCAST_INTERNAL_SECRET); otherwise every route answers the generic 404
|
|
8
|
+
* so the surface is indistinguishable from an engine that has none. Callers
|
|
9
|
+
* authenticate with `Authorization: Bearer <secret>`, compared in constant
|
|
10
|
+
* time. Request and response shapes match the hosted gateway's
|
|
11
|
+
* `/internal/capabilities` and `/internal/workspaces/:id/api-key`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const internalRoutes: Hono<AppEnv, import("hono/types").BlankSchema, "/">;
|
|
14
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/routes/internal.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAoBxC;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,qDAAqB,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { isArWorkspaceId, parseCredential } from '@relaycast/types';
|
|
2
|
+
import { AR_WORKSPACE_ID_REQUIRED, acceptsOnlyAr, credentialFormat } from '../auth/credentials.js';
|
|
3
|
+
import { Hono } from 'hono';
|
|
4
|
+
import { createMiddleware } from 'hono/factory';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { WorkspaceMetadataSchema } from '@relaycast/types';
|
|
7
|
+
import { constantTimeEqual } from '../lib/crypto.js';
|
|
8
|
+
import { errorResponse } from '../lib/httpError.js';
|
|
9
|
+
import { jsonCreated, jsonError, jsonNotFound, jsonOk, parseJsonBody, parseOptionalJsonBody, } from '../lib/httpResponse.js';
|
|
10
|
+
import { emitServerEvent } from '../lib/serverTelemetry.js';
|
|
11
|
+
import * as workspaceEngine from '../engine/workspace.js';
|
|
12
|
+
import { beginInternalWorkspaceDeletion, INTERNAL_CAPABILITIES, pushWorkspaceKey, } from '../engine/internalAdmin.js';
|
|
13
|
+
import { WORKSPACE_KEY_MAX_GRACE_MS } from '../engine/tokenRotate.js';
|
|
14
|
+
/**
|
|
15
|
+
* Internal admin API for a trusted control plane (self-host).
|
|
16
|
+
*
|
|
17
|
+
* Mounted at `/internal`. Enabled only when `config.internalSecret` is set
|
|
18
|
+
* (RELAYCAST_INTERNAL_SECRET); otherwise every route answers the generic 404
|
|
19
|
+
* so the surface is indistinguishable from an engine that has none. Callers
|
|
20
|
+
* authenticate with `Authorization: Bearer <secret>`, compared in constant
|
|
21
|
+
* time. Request and response shapes match the hosted gateway's
|
|
22
|
+
* `/internal/capabilities` and `/internal/workspaces/:id/api-key`.
|
|
23
|
+
*/
|
|
24
|
+
export const internalRoutes = new Hono();
|
|
25
|
+
const WORKSPACE_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
26
|
+
const WORKSPACE_KEY_PATTERN = /^rk_live_[A-Za-z0-9_-]{32,256}$/;
|
|
27
|
+
const requireInternalSecret = createMiddleware(async (c, next) => {
|
|
28
|
+
const expected = c.get('engine').config.internalSecret;
|
|
29
|
+
if (!expected) {
|
|
30
|
+
return jsonNotFound(c, 'not_found', 'Route not found');
|
|
31
|
+
}
|
|
32
|
+
const header = c.req.header('Authorization') ?? '';
|
|
33
|
+
const presented = header.startsWith('Bearer ') ? header.slice('Bearer '.length).trim() : '';
|
|
34
|
+
if (!(await constantTimeEqual(presented, expected))) {
|
|
35
|
+
return jsonError(c, 'unauthorized', 'Invalid internal token', 401);
|
|
36
|
+
}
|
|
37
|
+
await next();
|
|
38
|
+
});
|
|
39
|
+
internalRoutes.use('*', requireInternalSecret);
|
|
40
|
+
// GET /internal/capabilities — non-mutating capability advertisement.
|
|
41
|
+
internalRoutes.get('/capabilities', (c) => jsonOk(c, INTERNAL_CAPABILITIES));
|
|
42
|
+
const createWorkspaceSchema = z.object({
|
|
43
|
+
name: z.string().trim().min(1).max(128),
|
|
44
|
+
metadata: WorkspaceMetadataSchema.optional(),
|
|
45
|
+
}).strict();
|
|
46
|
+
// POST /internal/workspaces — create a workspace and reveal its key once.
|
|
47
|
+
// Self-host extension; the hosted control plane creates workspaces implicitly
|
|
48
|
+
// through the upsert on /internal/workspaces/:id/api-key.
|
|
49
|
+
internalRoutes.post('/workspaces', async (c) => {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = await parseJsonBody(c, createWorkspaceSchema, 'name is required (1-128 characters)');
|
|
52
|
+
if (!parsed.ok)
|
|
53
|
+
return parsed.response;
|
|
54
|
+
const result = await workspaceEngine.createWorkspace(c.get('db'), parsed.data.name, {
|
|
55
|
+
...(parsed.data.metadata === undefined ? {} : { metadata: parsed.data.metadata }),
|
|
56
|
+
});
|
|
57
|
+
emitServerEvent(c, result.workspace.workspace_id, 'workspace.created', {});
|
|
58
|
+
return jsonCreated(c, {
|
|
59
|
+
...result.workspace,
|
|
60
|
+
name: parsed.data.name,
|
|
61
|
+
api_key_generation: 0,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
return errorResponse(c, err);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// DELETE /internal/workspaces/:id — authoritative, idempotent deletion for a
|
|
69
|
+
// trusted control plane. Unlike the public route this authenticates with the
|
|
70
|
+
// internal secret, so a retry remains distinguishable from a wrong workspace
|
|
71
|
+
// key after the workspace row (and its key hash) is already gone.
|
|
72
|
+
internalRoutes.delete('/workspaces/:id', async (c) => {
|
|
73
|
+
const workspaceId = c.req.param('id');
|
|
74
|
+
if (!WORKSPACE_ID_PATTERN.test(workspaceId)) {
|
|
75
|
+
return jsonError(c, 'invalid_request', 'Invalid workspace id', 400);
|
|
76
|
+
}
|
|
77
|
+
const fence = beginInternalWorkspaceDeletion(c.get('db'), workspaceId);
|
|
78
|
+
try {
|
|
79
|
+
await workspaceEngine.deleteWorkspace(c.get('db'), c.get('engine').files, workspaceId);
|
|
80
|
+
fence.commit();
|
|
81
|
+
return c.body(null, 204);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
fence.release();
|
|
85
|
+
return errorResponse(c, err);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
const pushKeySchema = z.object({
|
|
89
|
+
// `rk_live_` + 32..256 URL-safe characters: the engine mints 32 hex chars and
|
|
90
|
+
// the cloud control plane mints base64url(32 bytes), so `-`/`_` are allowed.
|
|
91
|
+
// Not trimmed: the stored hash must match the exact bearer callers send,
|
|
92
|
+
// so surrounding whitespace is refused by the pattern instead.
|
|
93
|
+
// Or an `ar_ws_` workspace key naming this workspace (checked below).
|
|
94
|
+
api_key: z.string().refine((key) => WORKSPACE_KEY_PATTERN.test(key) || parseCredential(key)?.kind === 'workspace' && parseCredential(key)?.family === 'ar', 'api_key must be an rk_live_ workspace key (rk_live_ followed by 32-256 characters of [A-Za-z0-9_-]) or an ar_ws_ workspace key').optional(),
|
|
95
|
+
// Accepted for wire compatibility with the hosted gateway; the self-host
|
|
96
|
+
// engine has no plan entitlements, so the value is validated and ignored.
|
|
97
|
+
plan: z.string().min(1).optional(),
|
|
98
|
+
key_generation: z.number().int()
|
|
99
|
+
.min(1, 'key_generation must be a positive integer')
|
|
100
|
+
.max(Number.MAX_SAFE_INTEGER, 'key_generation must be a safe integer')
|
|
101
|
+
.optional(),
|
|
102
|
+
grace_ms: z.number().int().min(0).max(WORKSPACE_KEY_MAX_GRACE_MS).optional(),
|
|
103
|
+
}).refine((body) => body.grace_ms === undefined || body.key_generation !== undefined || body.api_key === undefined, {
|
|
104
|
+
message: 'grace_ms requires key_generation',
|
|
105
|
+
});
|
|
106
|
+
// POST /internal/workspaces/:id/api-key — register (upsert) or rotate a
|
|
107
|
+
// workspace key. Hosted shape: body `{ api_key, key_generation?, grace_ms?,
|
|
108
|
+
// plan? }` → `{ workspace_id, api_key_generation }` (201 when the push created
|
|
109
|
+
// the workspace). Self-host extension: omit `api_key` and the engine mints the
|
|
110
|
+
// replacement, returned once as `api_key`.
|
|
111
|
+
internalRoutes.post('/workspaces/:id/api-key', async (c) => {
|
|
112
|
+
try {
|
|
113
|
+
const workspaceId = c.req.param('id');
|
|
114
|
+
if (!WORKSPACE_ID_PATTERN.test(workspaceId)) {
|
|
115
|
+
return jsonError(c, 'invalid_request', 'Invalid workspace id', 400);
|
|
116
|
+
}
|
|
117
|
+
// A deployment that mints ar_ credentials carries the workspace in each
|
|
118
|
+
// one as a 64-bit snowflake, so it registers no other ids.
|
|
119
|
+
if (credentialFormat(c.get('db')) === 'ar' && !isArWorkspaceId(workspaceId)) {
|
|
120
|
+
return jsonError(c, 'invalid_request', AR_WORKSPACE_ID_REQUIRED, 400);
|
|
121
|
+
}
|
|
122
|
+
const parsed = await parseOptionalJsonBody(c, pushKeySchema, (result) => result.error.issues[0]?.message ?? 'Invalid key push body');
|
|
123
|
+
if (!parsed.ok)
|
|
124
|
+
return parsed.response;
|
|
125
|
+
const body = parsed.data;
|
|
126
|
+
if (body.api_key !== undefined) {
|
|
127
|
+
const key = parseCredential(body.api_key);
|
|
128
|
+
if (key?.family === 'ar' && key.workspaceId !== workspaceId) {
|
|
129
|
+
return jsonError(c, 'invalid_request', 'api_key names another workspace', 400);
|
|
130
|
+
}
|
|
131
|
+
// A deployment that accepts only ar_ credentials never holds a legacy key.
|
|
132
|
+
if (key?.family !== 'ar' && acceptsOnlyAr(c.get('db'))) {
|
|
133
|
+
return jsonError(c, 'invalid_request', 'api_key must be an ar_ws_ workspace key on this deployment', 400);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const result = await pushWorkspaceKey(c.get('db'), workspaceId, {
|
|
137
|
+
...(body.api_key === undefined ? {} : { apiKey: body.api_key }),
|
|
138
|
+
...(body.key_generation === undefined ? {} : { keyGeneration: body.key_generation }),
|
|
139
|
+
...(body.grace_ms === undefined ? {} : { graceMs: body.grace_ms }),
|
|
140
|
+
});
|
|
141
|
+
if (result.mintedApiKey) {
|
|
142
|
+
emitServerEvent(c, workspaceId, 'workspace.key.rotated', {
|
|
143
|
+
grace_seconds: Math.floor((body.grace_ms ?? 0) / 1000),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const data = {
|
|
147
|
+
workspace_id: result.workspaceId,
|
|
148
|
+
api_key_generation: result.apiKeyGeneration,
|
|
149
|
+
...(result.mintedApiKey ? { api_key: result.mintedApiKey } : {}),
|
|
150
|
+
};
|
|
151
|
+
return result.created ? jsonCreated(c, data) : jsonOk(c, data);
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
return errorResponse(c, err);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=internal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../../src/routes/internal.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/routes/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/routes/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAmCxC,eAAO,MAAM,UAAU,qDAAqB,CAAC"}
|
package/dist/routes/node.js
CHANGED
|
@@ -20,6 +20,8 @@ import { sendWebhookEvent } from './webhookOutbox.js';
|
|
|
20
20
|
import { emitServerEvent } from '../lib/serverTelemetry.js';
|
|
21
21
|
import { canonicalJson } from '../engine/messageMetadata.js';
|
|
22
22
|
import { getObserverTokenFromContext, normalizeObserverFilters, observerAllowsAgent, } from '../engine/observerToken.js';
|
|
23
|
+
import { derivationFamilies, credentialFromHex } from '../auth/credentials.js';
|
|
24
|
+
import { ephemeralEventFetch } from '../ports/index.js';
|
|
23
25
|
export const nodeRoutes = new Hono();
|
|
24
26
|
const nodeKindSchema = z.enum(['ws', 'http_push', 'poll']);
|
|
25
27
|
const nodeRoleSchema = z.enum(['direct', 'broker']);
|
|
@@ -182,8 +184,14 @@ async function enrollNode(c, data) {
|
|
|
182
184
|
idempotencyKey,
|
|
183
185
|
requestDigest,
|
|
184
186
|
]));
|
|
187
|
+
// The replacement is derived in every family the first attempt may
|
|
188
|
+
// have committed it in, so a retry after a family switch or a
|
|
189
|
+
// keyring rotation still recovers it.
|
|
190
|
+
const db = c.get('db');
|
|
191
|
+
const workspaceId = c.get('workspace').id;
|
|
192
|
+
const families = await derivationFamilies(db, workspaceId);
|
|
185
193
|
return {
|
|
186
|
-
|
|
194
|
+
replacementTokens: await Promise.all(families.map((family) => credentialFromHex(db, family.format, 'node', workspaceId, replacementDigest, family.format === 'ar' ? family.tag : undefined))),
|
|
187
195
|
idempotencyKeyHash: await sha256Hex(idempotencyKey),
|
|
188
196
|
requestDigest,
|
|
189
197
|
};
|
|
@@ -354,7 +362,7 @@ nodeRoutes.post('/nodes/:node/actions/:name/invoke', requireAuth, rateLimit, asy
|
|
|
354
362
|
nodeConnections: c.get('engine').nodeConnections,
|
|
355
363
|
environment: c.get('engine').config?.environment,
|
|
356
364
|
httpPushProxy: c.get('engine').config?.httpPushProxy,
|
|
357
|
-
|
|
365
|
+
ephemeralEventFetch: ephemeralEventFetch(c.get('engine').config),
|
|
358
366
|
workspaceId: workspace.id,
|
|
359
367
|
}, {
|
|
360
368
|
agentIds: [agent.id],
|
|
@@ -388,6 +396,40 @@ nodeRoutes.delete('/nodes/:node/providers/:name', requireWorkspaceKey, rateLimit
|
|
|
388
396
|
return errorResponse(c, err);
|
|
389
397
|
}
|
|
390
398
|
});
|
|
399
|
+
const NODE_DELETE_CONFLICTS = {
|
|
400
|
+
node_online: 'Node is online; pass force=true to delete it anyway',
|
|
401
|
+
node_has_actions: 'Node hosts registered actions; pass force=true to delete them with it',
|
|
402
|
+
node_delete_conflict: 'Node changed during deletion; retry',
|
|
403
|
+
};
|
|
404
|
+
// DELETE /v1/nodes/:name?force= - delete a node by id or name
|
|
405
|
+
nodeRoutes.delete('/nodes/:name', requireWorkspaceKey, rateLimit, async (c) => {
|
|
406
|
+
try {
|
|
407
|
+
const db = c.get('db');
|
|
408
|
+
const workspace = c.get('workspace');
|
|
409
|
+
const idOrName = c.req.param('name');
|
|
410
|
+
const node = await nodeEngine.getNodeById(db, workspace.id, idOrName)
|
|
411
|
+
?? await nodeEngine.getNodeByName(db, workspace.id, idOrName);
|
|
412
|
+
if (!node) {
|
|
413
|
+
return jsonNotFound(c, 'node_not_found', 'Node not found');
|
|
414
|
+
}
|
|
415
|
+
// Serialize with node-control operations so a register/heartbeat in this
|
|
416
|
+
// isolate cannot interleave; the engine's guarded DELETE covers the rest.
|
|
417
|
+
// Only the resolved id crosses the lock: re-resolving the path inside it
|
|
418
|
+
// could pick a different node after a concurrent delete.
|
|
419
|
+
const result = await serializeNodeOp(workspace.id, node.id, () => nodeEngine.deleteNode(db, c.get('engine'), workspace.id, node.id, {
|
|
420
|
+
force: c.req.query('force') === 'true',
|
|
421
|
+
}));
|
|
422
|
+
if (!result.ok) {
|
|
423
|
+
return result.code === 'node_not_found'
|
|
424
|
+
? jsonNotFound(c, 'node_not_found', 'Node not found')
|
|
425
|
+
: jsonError(c, result.code, NODE_DELETE_CONFLICTS[result.code], 409);
|
|
426
|
+
}
|
|
427
|
+
return jsonOk(c, { id: result.id, name: result.name, deleted: true, cascaded_actions: result.cascadedActions });
|
|
428
|
+
}
|
|
429
|
+
catch (err) {
|
|
430
|
+
return errorResponse(c, err);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
391
433
|
// GET /v1/nodes/:name - single node roster entry
|
|
392
434
|
// GET /v1/node/me - the node a node token belongs to. A service handed the
|
|
393
435
|
// token (Cloud, recording who owns a node) proves which node it is without
|