@sema-agent/server 1.314.0 → 1.315.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 (52) hide show
  1. package/dist/approval-hmac.d.ts +17 -0
  2. package/dist/approval-hmac.js +27 -0
  3. package/dist/config-center/apply-effective.d.ts +22 -0
  4. package/dist/config-center/apply-effective.js +283 -0
  5. package/dist/config-center/http-client.d.ts +23 -0
  6. package/dist/config-center/http-client.js +109 -0
  7. package/dist/config-center/restart-signal.d.ts +12 -0
  8. package/dist/config-center/restart-signal.js +70 -0
  9. package/dist/config-center/skills-mcp.d.ts +13 -0
  10. package/dist/config-center/skills-mcp.js +113 -0
  11. package/dist/config-center/types.d.ts +143 -0
  12. package/dist/config-center/types.js +2 -0
  13. package/dist/fleet/fleet-bus.js +92 -83
  14. package/dist/hooks/hook-runner.js +18 -9
  15. package/dist/http/server.d.ts +95 -69
  16. package/dist/http/server.js +8 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/leader/leader.js +5 -2
  19. package/dist/leader/wire.js +169 -165
  20. package/dist/main.js +462 -451
  21. package/dist/plugins/checkpoint-store-sql.d.ts +67 -0
  22. package/dist/plugins/checkpoint-store-sql.js +224 -0
  23. package/dist/plugins/image-bake-store-sql.d.ts +53 -0
  24. package/dist/plugins/image-bake-store-sql.js +463 -0
  25. package/dist/plugins/k8s-bg-scripts.d.ts +19 -0
  26. package/dist/plugins/k8s-bg-scripts.js +129 -0
  27. package/dist/plugins/k8s-exec-protocol.d.ts +20 -0
  28. package/dist/plugins/k8s-exec-protocol.js +87 -0
  29. package/dist/plugins/pg-checkpoint-store.d.ts +1 -33
  30. package/dist/plugins/pg-checkpoint-store.js +1 -189
  31. package/dist/plugins/pg-cost-quota.js +3 -143
  32. package/dist/plugins/pg-image-bake.d.ts +1 -40
  33. package/dist/plugins/pg-image-bake.js +1 -420
  34. package/dist/plugins/pg-rate-limiter.d.ts +2 -32
  35. package/dist/plugins/pg-rate-limiter.js +4 -147
  36. package/dist/plugins/remote-env-k8s.d.ts +5 -38
  37. package/dist/plugins/remote-env-k8s.js +7 -213
  38. package/dist/plugins/sql-driver.d.ts +25 -0
  39. package/dist/plugins/sql-driver.js +59 -0
  40. package/dist/plugins/tidb-checkpoint-store.d.ts +1 -49
  41. package/dist/plugins/tidb-checkpoint-store.js +1 -191
  42. package/dist/plugins/tidb-image-bake.d.ts +1 -38
  43. package/dist/plugins/tidb-image-bake.js +1 -348
  44. package/dist/plugins/write-behind-counter.d.ts +14 -3
  45. package/dist/plugins/write-behind-counter.js +39 -12
  46. package/dist/principal-jwt.d.ts +44 -0
  47. package/dist/principal-jwt.js +95 -0
  48. package/dist/security.d.ts +2 -58
  49. package/dist/security.js +3 -118
  50. package/dist/sema-registry.d.ts +5 -200
  51. package/dist/sema-registry.js +4 -567
  52. package/package.json +1 -1
@@ -3,7 +3,6 @@ import { type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
3
3
  import type { ServiceConfig } from "./config-types.js";
4
4
  import type { TaskRequestBody } from "./http/wire-types.js";
5
5
  import type { StagingHandle } from "./session-sync-kernel.js";
6
- import type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
7
6
  export { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
8
7
  export type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
9
8
  export interface SessionListItem {
@@ -81,61 +80,6 @@ export declare function setSsoScope(req: IncomingMessage, scope: string): void;
81
80
  export declare function ssoVerifiedScope(req: IncomingMessage): string | undefined;
82
81
  export declare function verifiedPrincipal(req: IncomingMessage, config: ServiceConfig): string | undefined;
83
82
  export { memoryScopeFor, memoryEngineRemoteLanePosture, memoryEngineBackendFor, memorySpecForRequest } from "./memory-scope.js";
84
- export declare function approvalHmacMessage(env: {
85
- sessionId: string;
86
- boundCallId?: string | null;
87
- boundInputHash?: string | null;
88
- decision: string;
89
- reason?: string | null;
90
- }): string;
91
- export declare const MAX_APPROVAL_REASON_CHARS = 4096;
92
- export declare function verifyApprovalHmac(env: {
93
- sessionId: string;
94
- boundCallId?: string | null;
95
- boundInputHash?: string | null;
96
- decision: string;
97
- reason?: string | null;
98
- }, mac: string, kid: string | undefined, keys: ApprovalHmacKey[]): boolean;
99
- export declare function verifyPrincipalJwt(token: string, keys: PrincipalJwtKey[], expect: {
100
- iss: string;
101
- aud: string;
102
- nowSec?: number;
103
- skewSec?: number;
104
- maxTtlSec?: number;
105
- }): {
106
- sub: string;
107
- bnd?: string;
108
- } | null;
109
- export declare function approvalBnd(env: {
110
- sessionId: string;
111
- boundCallId?: string | null;
112
- boundInputHash?: string | null;
113
- }): string;
114
- export declare function verifyDirectDoorProof(proof: {
115
- jwt?: string;
116
- mac?: string;
117
- kid?: string;
118
- }, envelope: {
119
- sessionId: string;
120
- boundCallId?: string | null;
121
- boundInputHash?: string | null;
122
- decision: string;
123
- reason?: string | null;
124
- }, config: {
125
- principalJwtPubkeys: PrincipalJwtKey[];
126
- principalJwtIss?: string;
127
- principalJwtAud?: string;
128
- principalJwtMaxTtlSec?: number;
129
- approvalHmacKeys: ApprovalHmacKey[];
130
- }, opts?: {
131
- actionBinding?: boolean;
132
- }): {
133
- ok: true;
134
- principal: string;
135
- } | {
136
- ok: false;
137
- status: number;
138
- errorCode: string;
139
- error: string;
140
- };
83
+ export { approvalHmacMessage, MAX_APPROVAL_REASON_CHARS, verifyApprovalHmac } from "./approval-hmac.js";
84
+ export { verifyPrincipalJwt, approvalBnd, verifyDirectDoorProof } from "./principal-jwt.js";
141
85
  //# sourceMappingURL=security.d.ts.map
package/dist/security.js CHANGED
@@ -1,8 +1,8 @@
1
- import { createHash, createHmac, createPublicKey, timingSafeEqual, verify as cryptoVerify } from "node:crypto";
2
1
  import { uuidv7 } from "@sema-agent/core";
3
2
  import { PROJECT_ID_REGEX } from "@sema-agent/registry-core";
4
3
  export { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
5
4
  import { memoryScopeFor } from "./memory-scope.js";
5
+ import { verifyPrincipalJwt } from "./principal-jwt.js";
6
6
  const UUIDV7_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
7
7
  export function isUuidV7(s) {
8
8
  return UUIDV7_RE.test(s);
@@ -129,121 +129,6 @@ export function verifiedPrincipal(req, config) {
129
129
  return sub;
130
130
  }
131
131
  export { memoryScopeFor, memoryEngineRemoteLanePosture, memoryEngineBackendFor, memorySpecForRequest } from "./memory-scope.js";
132
- export function approvalHmacMessage(env) {
133
- return JSON.stringify([env.sessionId, env.boundCallId ?? null, env.boundInputHash ?? null, env.decision, env.reason ?? null]);
134
- }
135
- export const MAX_APPROVAL_REASON_CHARS = 4_096;
136
- export function verifyApprovalHmac(env, mac, kid, keys) {
137
- if (keys.length === 0)
138
- return false;
139
- let supplied;
140
- try {
141
- supplied = Buffer.from(mac, "hex");
142
- }
143
- catch {
144
- return false;
145
- }
146
- if (supplied.length === 0)
147
- return false;
148
- const ordered = kid ? [...keys.filter((k) => k.kid === kid), ...keys.filter((k) => k.kid !== kid)] : keys;
149
- const msg = approvalHmacMessage(env);
150
- for (const k of ordered) {
151
- const expected = createHmac("sha256", k.key).update(msg).digest();
152
- if (expected.length === supplied.length && timingSafeEqual(expected, supplied))
153
- return true;
154
- }
155
- return false;
156
- }
157
- function b64urlToBuf(s) {
158
- return Buffer.from(s, "base64url");
159
- }
160
- function verifyJwsSignature(alg, signingInput, sig, pub) {
161
- try {
162
- if (alg === "EdDSA")
163
- return cryptoVerify(null, signingInput, pub, sig);
164
- if (alg === "RS256")
165
- return cryptoVerify("sha256", signingInput, pub, sig);
166
- if (alg === "ES256")
167
- return cryptoVerify("sha256", signingInput, { key: pub, dsaEncoding: "ieee-p1363" }, sig);
168
- return false;
169
- }
170
- catch {
171
- return false;
172
- }
173
- }
174
- export function verifyPrincipalJwt(token, keys, expect) {
175
- if (keys.length === 0)
176
- return null;
177
- const parts = token.split(".");
178
- if (parts.length !== 3)
179
- return null;
180
- const [h, p, s] = parts;
181
- let header;
182
- let payload;
183
- let sig;
184
- try {
185
- header = JSON.parse(b64urlToBuf(h).toString("utf8"));
186
- payload = JSON.parse(b64urlToBuf(p).toString("utf8"));
187
- sig = b64urlToBuf(s);
188
- }
189
- catch {
190
- return null;
191
- }
192
- if (typeof header !== "object" || header === null || typeof payload !== "object" || payload === null)
193
- return null;
194
- if (typeof header.alg !== "string" || typeof header.kid !== "string" || sig.length === 0)
195
- return null;
196
- const key = keys.find((k) => k.kid === header.kid);
197
- if (!key || key.alg !== header.alg)
198
- return null;
199
- let pub;
200
- try {
201
- pub = createPublicKey(key.key);
202
- }
203
- catch {
204
- return null;
205
- }
206
- const signingInput = Buffer.from(`${h}.${p}`, "utf8");
207
- if (!verifyJwsSignature(key.alg, signingInput, sig, pub))
208
- return null;
209
- if (payload.iss !== expect.iss)
210
- return null;
211
- const aud = payload.aud;
212
- const audOk = aud === expect.aud || (Array.isArray(aud) && aud.includes(expect.aud));
213
- if (!audOk)
214
- return null;
215
- if (typeof payload.sub !== "string" || payload.sub.length === 0)
216
- return null;
217
- const now = expect.nowSec ?? Math.floor(Date.now() / 1000);
218
- const skew = expect.skewSec ?? 30;
219
- if (typeof payload.exp !== "number" || payload.exp + skew < now)
220
- return null;
221
- if (payload.nbf !== undefined && (typeof payload.nbf !== "number" || payload.nbf - skew > now))
222
- return null;
223
- if (expect.maxTtlSec && payload.exp - now > expect.maxTtlSec + skew)
224
- return null;
225
- const bnd = typeof payload.cnf?.bnd === "string" ? payload.cnf.bnd : undefined;
226
- return { sub: payload.sub, bnd };
227
- }
228
- export function approvalBnd(env) {
229
- return createHash("sha256").update(JSON.stringify([env.sessionId, env.boundCallId ?? null, env.boundInputHash ?? null])).digest("hex");
230
- }
231
- export function verifyDirectDoorProof(proof, envelope, config, opts) {
232
- const actionBinding = opts?.actionBinding ?? true;
233
- if (!proof.jwt)
234
- return { ok: false, status: 401, errorCode: "principal_unverified", error: "direct door requires a signed principal token (X-Approval-Principal-Token)" };
235
- const verified = verifyPrincipalJwt(proof.jwt, config.principalJwtPubkeys, { iss: config.principalJwtIss ?? "\0", aud: config.principalJwtAud ?? "\0", maxTtlSec: config.principalJwtMaxTtlSec });
236
- if (!verified)
237
- return { ok: false, status: 401, errorCode: "principal_unverified", error: "principal token failed verification" };
238
- if (actionBinding && !envelope.boundInputHash)
239
- return { ok: false, status: 400, errorCode: "approval_mac_required", error: "direct door requires boundInputHash (the bound action) in the body" };
240
- if (verified.bnd !== approvalBnd(envelope))
241
- return { ok: false, status: 401, errorCode: "principal_unbound", error: "principal token is not bound to this decision (cnf.bnd mismatch)" };
242
- if (!proof.mac)
243
- return { ok: false, status: 401, errorCode: "approval_mac_required", error: "direct door requires an approval MAC (X-Approval-Mac)" };
244
- const ok = verifyApprovalHmac({ sessionId: envelope.sessionId, boundCallId: envelope.boundCallId ?? null, boundInputHash: envelope.boundInputHash ?? null, decision: envelope.decision, reason: envelope.reason ?? null }, proof.mac, proof.kid, config.approvalHmacKeys);
245
- if (!ok)
246
- return { ok: false, status: 401, errorCode: "approval_mac_invalid", error: "approval envelope MAC invalid" };
247
- return { ok: true, principal: verified.sub };
248
- }
132
+ export { approvalHmacMessage, MAX_APPROVAL_REASON_CHARS, verifyApprovalHmac } from "./approval-hmac.js";
133
+ export { verifyPrincipalJwt, approvalBnd, verifyDirectDoorProof } from "./principal-jwt.js";
249
134
  //# sourceMappingURL=security.js.map
@@ -1,201 +1,6 @@
1
- import type { McpServerSpec } from "@sema-agent/core";
2
- import { type EntitlementRuntimeCaps } from "@sema-agent/registry-core";
3
- import type { ScopedMcpServer, ServiceConfig } from "./config-types.js";
4
- import { type SealedKeyOpener } from "./sealed-key.js";
5
- import type { Autonomy, CommandRule } from "./runtime-governance.js";
6
- import type { Logger } from "./observability/logger.js";
7
- import type { LoadedSkill } from "./capabilities/skills.js";
8
- import type { ScenarioRuling } from "./capabilities/scenarios.js";
9
- import type { CollabTemplateWire } from "./capabilities/collab-wire.js";
10
- interface CenterModel {
11
- name: string;
12
- id: string;
13
- provider: string;
14
- api: "openai-completions" | "anthropic-messages";
15
- baseUrl?: string;
16
- apiKeyEnv?: string;
17
- sealedApiKey?: {
18
- ciphertext: string;
19
- publicKeyId: string;
20
- alg: string;
21
- setAt?: string;
22
- };
23
- tier?: string;
24
- reasoning?: boolean;
25
- vision?: boolean;
26
- contextWindow?: number;
27
- maxTokens?: number;
28
- autoCompactTokens?: number;
29
- charsPerToken?: number;
30
- cost?: {
31
- input: number;
32
- output: number;
33
- cacheRead?: number;
34
- cacheWrite?: number;
35
- };
36
- quotaWeight?: number;
37
- defaultThinking?: string;
38
- reasoningEffortLevels?: string[];
39
- extraBody?: Record<string, unknown>;
40
- promptGuidance?: string[];
41
- enabled?: boolean;
42
- }
43
- type CenterRoleTarget = {
44
- model: string;
45
- } | {
46
- select: unknown;
47
- };
48
- interface CenterTeam {
49
- name: string;
50
- members: {
51
- role: string;
52
- modelRole?: string;
53
- model?: string;
54
- systemPrompt?: string;
55
- }[];
56
- rounds: number;
57
- synthesizer?: {
58
- role: string;
59
- modelRole?: string;
60
- systemPrompt?: string;
61
- };
62
- scenario?: string;
63
- maxTranscriptTokens?: number;
64
- enabled?: boolean;
65
- }
66
- export interface CenterSkillManifest {
67
- name: string;
68
- description: string;
69
- scenarios: string[];
70
- contentHash: string;
71
- enabled?: boolean;
72
- }
73
- export interface CenterMcpServer {
74
- name: string;
75
- scenarios: string[];
76
- enabled?: boolean;
77
- allowTools?: string[];
78
- elicitation?: boolean;
79
- transport: {
80
- kind: "stdio";
81
- command: string;
82
- args?: string[];
83
- envRefs?: Record<string, string>;
84
- } | {
85
- kind: "http";
86
- url: string;
87
- headerRefs?: Record<string, string>;
88
- principalHeader?: string;
89
- };
90
- }
91
- export interface EffectiveConfig {
92
- version: number;
93
- updatedAt: string;
94
- models: {
95
- models: CenterModel[];
96
- roles: Record<string, CenterRoleTarget>;
97
- atModelAllowlist?: string[];
98
- };
99
- teams?: {
100
- teams: CenterTeam[];
101
- };
102
- collab?: {
103
- templates: CollabTemplateWire[];
104
- };
105
- skills?: {
106
- skills: CenterSkillManifest[];
107
- };
108
- mcp?: {
109
- servers: CenterMcpServer[];
110
- };
111
- scenarios?: {
112
- scenarios: Array<{
113
- name: string;
114
- toolset: string;
115
- enabled?: boolean;
116
- }>;
117
- };
118
- runtime?: {
119
- rateLimitPerMin?: number;
120
- approvalRequire?: string[];
121
- maxTaskCostUsd?: number;
122
- maxTaskTokens?: number;
123
- maxPrincipalCostUsd?: number;
124
- costQuotaWindowSec?: number;
125
- autonomy?: Autonomy;
126
- commandPolicy?: CommandRule[];
127
- };
128
- projects?: {
129
- projects?: Record<string, unknown>;
130
- } | Record<string, unknown>;
131
- governance?: {
132
- autonomy?: Autonomy;
133
- commandPolicy?: CommandRule[];
134
- approvalRequire?: string[];
135
- };
136
- plugins?: {
137
- plugins?: unknown[];
138
- };
139
- prompts?: unknown;
140
- }
141
- export interface ExecutionRuling {
142
- required: boolean;
143
- allowedLanes: string[];
144
- sessionMirror?: SessionMirrorRuling;
145
- }
146
- export interface SessionMirrorRuling {
147
- engineUrl: string;
148
- required: boolean;
149
- }
150
- export declare function fetchEffective(baseUrl: string, token: string, etag: string | undefined, fetchImpl?: typeof fetch, worker?: string): Promise<{
151
- effective: EffectiveConfig;
152
- etag?: string;
153
- } | null>;
154
- export declare function fetchPrincipalCaps(baseUrl: string, token: string, principal: string, etag: string | undefined, fetchImpl?: typeof fetch, worker?: string): Promise<{
155
- runtimeCaps: EntitlementRuntimeCaps | null;
156
- configured: boolean;
157
- scenario?: ScenarioRuling;
158
- execution?: ExecutionRuling;
159
- executionDrift?: string;
160
- etag?: string;
161
- } | null>;
162
- export declare function mutateInPlace<V>(target: Record<string, V>, source: Record<string, V>): void;
163
- export declare function applyEffective(config: ServiceConfig, eff: EffectiveConfig, logger?: Logger, opts?: {
164
- teamsOnly?: boolean;
165
- sealedKeys?: SealedKeyOpener;
166
- deferModelPlane?: boolean;
167
- }): void;
168
- export declare function applyRuntimeGates(config: ServiceConfig, rt: EffectiveConfig["runtime"], logger?: Logger): void;
169
- export declare function applyRuntimeHot(config: ServiceConfig, rt: EffectiveConfig["runtime"], logger?: Logger): void;
170
- export declare function resolveDefaultModelName(eff: EffectiveConfig, has: (name: string) => boolean, fallback: string, onDangling?: (source: string, name: string) => void): {
171
- name: string;
172
- source: string;
173
- };
174
- export declare function logEffectiveDiff(config: ServiceConfig, eff: EffectiveConfig, logger?: Logger): void;
175
- export declare function runtimeHasActiveGate(rt: EffectiveConfig["runtime"]): boolean;
176
- export type RestartSlice = "skills" | "mcp" | "scenarios" | "runtime-gates" | "models-tiers";
177
- export interface RestartSignal {
178
- restartRequired: true;
179
- reasons: RestartSlice[];
180
- version: number;
181
- since: number;
182
- }
183
- export declare function restartReasons(boot: EffectiveConfig | undefined, current: EffectiveConfig): RestartSlice[];
184
- export declare function planeHasActiveTiers(eff: EffectiveConfig): boolean;
185
- export declare function modelPlaneChanged(prev: EffectiveConfig | undefined, next: EffectiveConfig): boolean;
186
- export declare class ConfigCenterHttpError extends Error {
187
- readonly status: number;
188
- constructor(message: string, status: number);
189
- }
190
- export declare function fetchSkillContent(baseUrl: string, token: string, contentHash: string, fetchImpl?: typeof fetch): Promise<string>;
191
- export declare function fetchPromptArtifact(baseUrl: string, token: string, artifactDigest: string, fetchImpl?: typeof fetch): Promise<unknown>;
192
- export declare function fetchPromptBlob(baseUrl: string, token: string, contentDigest: string, fetchImpl?: typeof fetch): Promise<string>;
193
- export declare function applyCenterSkills(baseline: LoadedSkill[], manifest: {
194
- skills: CenterSkillManifest[];
195
- }, baseUrl: string, token: string, logger?: Logger, fetchImpl?: typeof fetch, diskCacheDir?: string): Promise<LoadedSkill[]>;
196
- export declare function resolveMcpServers(mcp: {
197
- servers: CenterMcpServer[];
198
- }, logger?: Logger): ScopedMcpServer[];
199
- export declare function mcpForScenario(servers: ScopedMcpServer[] | undefined, scenario: string): McpServerSpec[] | undefined;
200
- export {};
1
+ export { fetchEffective, fetchPrincipalCaps, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./config-center/http-client.js";
2
+ export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, runtimeHasActiveGate, } from "./config-center/apply-effective.js";
3
+ export { restartReasons, planeHasActiveTiers, modelPlaneChanged, type RestartSlice, type RestartSignal, } from "./config-center/restart-signal.js";
4
+ export { applyCenterSkills, resolveMcpServers, mcpForScenario } from "./config-center/skills-mcp.js";
5
+ export type { CenterSkillManifest, CenterMcpServer, EffectiveConfig, ExecutionRuling, SessionMirrorRuling, } from "./config-center/types.js";
201
6
  //# sourceMappingURL=sema-registry.d.ts.map