Clarify safe response and saved-wait recovery after secret denial

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-11-06 00:40:37 -06:00
1 parent b68826b5df
commit f49c92870a
2 files changed
+21 -1

No files matched your search

@@ -169,6 +169,26 @@ describe("secret routes", () => {
expect(mockLogActivity).not.toHaveBeenCalled();
});
it("gives a denied agent safe response and saved-wait options without echoing the submitted value", async () => {
const value = "private-denial-canary-value";
const res = await request(createApp({
type: "agent", agentId: "agent-1", companyId: "company-1", source: "agent_jwt",
})).post("/api/companies/company-1/secrets").send({ name: "Deployment key", value });
expect(res.status).toBe(403);
expect(res.body.error).toContain("finish the current conversation response");
expect(res.body.error).toContain("without claiming that credential setup is complete");
expect(res.body.error).toContain("first create a non-governing secure-save acknowledgment");
expect(res.body.error).toContain("request_human_input");
expect(res.body.error).toContain("request_confirmation");
expect(res.body.error).toContain("never ask for the secret value in that card");
expect(res.body.error).toContain("Wait only on the actual saved request");
expect(JSON.stringify(res.body)).not.toContain(value);
expect(res.body).not.toHaveProperty("details");
expect(mockSecretService.create).not.toHaveBeenCalled();
expect(mockLogActivity).not.toHaveBeenCalled();
});
it.each([undefined, ""])("validates a board caller's missing or empty managed value %j", async (value) => {
const res = await request(createApp()).post("/api/companies/company-1/secrets")
.send({ name: "Deployment key", value });
+1 -1
View File
@@ -888,7 +888,7 @@ export function secretRoutes(db: Db, deps: SecretRoutesDeps = {}) {
const companyId = req.params.companyId as string;
if (req.actor.type === "agent") {
assertCompanyAccess(req, companyId);
throw forbidden("Company secret creation requires a human board operator. Ask the human to enter the value in Settings → Secrets for this company. Do not send secret values in chat or tool calls.");
throw forbidden("Company secret creation requires a human board operator. Ask the human to enter the value in Settings → Secrets for this company. Do not send secret values in chat or tool calls. You can finish the current conversation response with these secure-entry instructions without claiming that credential setup is complete. If you need a resumable wait, first create a non-governing secure-save acknowledgment with request_human_input using request_confirmation; ask only whether secure entry is complete, never ask for the secret value in that card. Wait only on the actual saved request.");
}
assertCompanySecretWrite(req, companyId);
next();