Skip to content

Commit 39528ed

Browse files
committed
fix(security): restore fs import lost in bounded manifest-read merge
#101773 removed the node:fs/promises import while switching plugin manifest reads to fs-safe helpers, but getSkillCodeSafetySummary (added later by #109363) still reads SKILL.md via fs.readFile. Main has been red since the merge (check-prod-types, check-lint, check-test-types, package-boundary compile, compact-large-5). Restore the import; skill-file reads keep their pre-existing unbounded contract.
1 parent e721508 commit 39528ed

4 files changed

Lines changed: 87 additions & 116 deletions

File tree

packages/gateway-protocol/src/schema/nodes.test.ts

Lines changed: 0 additions & 34 deletions
This file was deleted.

packages/gateway-protocol/src/schema/nodes.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,16 @@ export const NodeInvokeResultParamsSchema = closedObject({
164164
});
165165

166166
/** Ordered UTF-8 output emitted while a node command invocation is running. */
167-
export const NodeInvokeProgressParamsSchema = closedObject({
168-
invokeId: NonEmptyString,
169-
nodeId: NonEmptyString,
170-
seq: Type.Integer({ minimum: 0 }),
171-
// Empty chunks are liveness heartbeats for captured stderr or capped stdout.
172-
chunk: Type.String({ maxLength: 16 * 1024 }),
173-
});
167+
export const NodeInvokeProgressParamsSchema = Type.Object(
168+
{
169+
invokeId: NonEmptyString,
170+
nodeId: NonEmptyString,
171+
seq: Type.Integer({ minimum: 0 }),
172+
// Empty chunks are liveness heartbeats for captured stderr or capped stdout.
173+
chunk: Type.String({ maxLength: 16 * 1024 }),
174+
},
175+
{ additionalProperties: false },
176+
);
174177

175178
/** Generic node event envelope accepted by the gateway. */
176179
export const NodeEventParamsSchema = closedObject({

packages/gateway-protocol/src/schema/session-placement.test.ts

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -282,28 +282,4 @@ describe("session dispatch protocol schemas", () => {
282282
}),
283283
).toBe(false);
284284
});
285-
286-
it("rejects extra fields in dispatch params and results", () => {
287-
const active = {
288-
state: "active" as const,
289-
...basePlacement,
290-
...workerOwnedFields,
291-
};
292-
expect(
293-
validateSessionsDispatchResult({
294-
ok: true,
295-
key: "agent:main:dispatch",
296-
sessionId: "session-1",
297-
placement: active,
298-
extra: true,
299-
}),
300-
).toBe(false);
301-
expect(
302-
validateSessionsDispatchParams({
303-
key: "agent:main:dispatch",
304-
profileId: "development",
305-
extra: true,
306-
}),
307-
).toBe(false);
308-
});
309285
});

packages/gateway-protocol/src/schema/session-placement.ts

Lines changed: 77 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { Static } from "typebox";
22
import { Type } from "typebox";
3-
import { closedObject } from "./closed-object.js";
43
import { NonEmptyString } from "./primitives.js";
54
import { SESSION_PLACEMENT_STATES } from "./session-placement-state.js";
65

@@ -78,64 +77,85 @@ const TerminalSessionPlacementProperties = {
7877
function createUnownedSessionPlacementSchema<const State extends "local" | "requested">(
7978
state: State,
8079
) {
81-
return closedObject({ state: Type.Literal(state), ...SessionPlacementTimingProperties });
80+
return Type.Object(
81+
{ state: Type.Literal(state), ...SessionPlacementTimingProperties },
82+
{ additionalProperties: false },
83+
);
8284
}
8385

8486
function createWorkerOwnedSessionPlacementSchema<
8587
const State extends "active" | "draining" | "reconciling",
8688
>(state: State) {
87-
return closedObject({
88-
state: Type.Literal(state),
89-
...SessionPlacementTimingProperties,
90-
environmentId: NonEmptyString,
91-
activeOwnerEpoch: SessionPlacementOwnerEpochSchema,
92-
workerBundleHash: WorkerBundleHashSchema,
93-
...SessionPlacementWorkspaceProperties,
94-
...SessionPlacementAckProperties,
95-
});
89+
return Type.Object(
90+
{
91+
state: Type.Literal(state),
92+
...SessionPlacementTimingProperties,
93+
environmentId: NonEmptyString,
94+
activeOwnerEpoch: SessionPlacementOwnerEpochSchema,
95+
workerBundleHash: WorkerBundleHashSchema,
96+
...SessionPlacementWorkspaceProperties,
97+
...SessionPlacementAckProperties,
98+
},
99+
{ additionalProperties: false },
100+
);
96101
}
97102

98103
export const LocalSessionPlacementSchema = createUnownedSessionPlacementSchema("local");
99104
export const RequestedSessionPlacementSchema = createUnownedSessionPlacementSchema("requested");
100105

101-
export const ProvisioningSessionPlacementSchema = closedObject({
102-
state: Type.Literal("provisioning"),
103-
...SessionPlacementTimingProperties,
104-
environmentId: Type.Optional(NonEmptyString),
105-
});
106+
export const ProvisioningSessionPlacementSchema = Type.Object(
107+
{
108+
state: Type.Literal("provisioning"),
109+
...SessionPlacementTimingProperties,
110+
environmentId: Type.Optional(NonEmptyString),
111+
},
112+
{ additionalProperties: false },
113+
);
106114

107-
export const SyncingSessionPlacementSchema = closedObject({
108-
state: Type.Literal("syncing"),
109-
...SessionPlacementTimingProperties,
110-
environmentId: NonEmptyString,
111-
workerBundleHash: WorkerBundleHashSchema,
112-
});
115+
export const SyncingSessionPlacementSchema = Type.Object(
116+
{
117+
state: Type.Literal("syncing"),
118+
...SessionPlacementTimingProperties,
119+
environmentId: NonEmptyString,
120+
workerBundleHash: WorkerBundleHashSchema,
121+
},
122+
{ additionalProperties: false },
123+
);
113124

114-
export const StartingSessionPlacementSchema = closedObject({
115-
state: Type.Literal("starting"),
116-
...SessionPlacementTimingProperties,
117-
environmentId: NonEmptyString,
118-
workerBundleHash: WorkerBundleHashSchema,
119-
...SessionPlacementWorkspaceProperties,
120-
});
125+
export const StartingSessionPlacementSchema = Type.Object(
126+
{
127+
state: Type.Literal("starting"),
128+
...SessionPlacementTimingProperties,
129+
environmentId: NonEmptyString,
130+
workerBundleHash: WorkerBundleHashSchema,
131+
...SessionPlacementWorkspaceProperties,
132+
},
133+
{ additionalProperties: false },
134+
);
121135

122136
export const ActiveWorkerSessionPlacementSchema = createWorkerOwnedSessionPlacementSchema("active");
123137
export const DrainingSessionPlacementSchema = createWorkerOwnedSessionPlacementSchema("draining");
124138
export const ReconcilingSessionPlacementSchema =
125139
createWorkerOwnedSessionPlacementSchema("reconciling");
126140

127-
export const ReclaimedSessionPlacementSchema = closedObject({
128-
state: Type.Literal("reclaimed"),
129-
...SessionPlacementTimingProperties,
130-
...TerminalSessionPlacementProperties,
131-
});
141+
export const ReclaimedSessionPlacementSchema = Type.Object(
142+
{
143+
state: Type.Literal("reclaimed"),
144+
...SessionPlacementTimingProperties,
145+
...TerminalSessionPlacementProperties,
146+
},
147+
{ additionalProperties: false },
148+
);
132149

133-
export const FailedSessionPlacementSchema = closedObject({
134-
state: Type.Literal("failed"),
135-
...SessionPlacementTimingProperties,
136-
...TerminalSessionPlacementProperties,
137-
recoveryError: NonEmptyString,
138-
});
150+
export const FailedSessionPlacementSchema = Type.Object(
151+
{
152+
state: Type.Literal("failed"),
153+
...SessionPlacementTimingProperties,
154+
...TerminalSessionPlacementProperties,
155+
recoveryError: NonEmptyString,
156+
},
157+
{ additionalProperties: false },
158+
);
139159

140160
/** Gateway-visible placement projection; `state` remains the closed discriminator. */
141161
export const SessionPlacementSchema = Type.Union([
@@ -152,19 +172,25 @@ export const SessionPlacementSchema = Type.Union([
152172
]);
153173

154174
/** Requests one-way dispatch of an existing local session to a configured worker profile. */
155-
export const SessionsDispatchParamsSchema = closedObject({
156-
key: NonEmptyString,
157-
agentId: Type.Optional(NonEmptyString),
158-
profileId: NonEmptyString,
159-
});
175+
export const SessionsDispatchParamsSchema = Type.Object(
176+
{
177+
key: NonEmptyString,
178+
agentId: Type.Optional(NonEmptyString),
179+
profileId: NonEmptyString,
180+
},
181+
{ additionalProperties: false },
182+
);
160183

161184
/** Result returned once session dispatch reaches durable worker ownership. */
162-
export const SessionsDispatchResultSchema = closedObject({
163-
ok: Type.Literal(true),
164-
key: NonEmptyString,
165-
sessionId: NonEmptyString,
166-
placement: ActiveWorkerSessionPlacementSchema,
167-
});
185+
export const SessionsDispatchResultSchema = Type.Object(
186+
{
187+
ok: Type.Literal(true),
188+
key: NonEmptyString,
189+
sessionId: NonEmptyString,
190+
placement: ActiveWorkerSessionPlacementSchema,
191+
},
192+
{ additionalProperties: false },
193+
);
168194

169195
/** Requests safe workspace reconciliation and teardown of an active cloud worker. */
170196
export const SessionsReclaimParamsSchema = Type.Object(

0 commit comments

Comments
 (0)