Cover expired invocation scope and schema-scoped secret refs

This commit is contained in:
Dotta committed 2026-07-06 13:47:05 +00:00
1 parent 30a13285c5
commit 59b5d2f1c2
2 files changed
+62

No files matched your search

@@ -172,4 +172,30 @@ describe("createHostClientHandlers invocation company scope", () => {
).rejects.toBeInstanceOf(InvocationScopeDeniedError);
expect(searchAudit).not.toHaveBeenCalled();
});
it("fails closed when an authorization read arrives with an expired invocation scope", async () => {
const searchAudit = vi.fn(async () => []);
const services = {
authorization: {
searchAudit,
},
} as unknown as HostServices;
const handlers = createHostClientHandlers({
pluginId: "paperclip.test",
capabilities: ["authorization.audit.read"],
services,
});
await expect(
handlers["authorization.audit.search"](
{ companyId: "company-a" },
{ invalidInvocationScope: true },
),
).rejects.toMatchObject({
name: "InvocationScopeDeniedError",
code: PLUGIN_RPC_ERROR_CODES.INVOCATION_SCOPE_DENIED,
message: expect.stringContaining("missing, expired, or unknown invocation scope"),
});
expect(searchAudit).not.toHaveBeenCalled();
});
});
@@ -1,10 +1,46 @@
import { describe, expect, it } from "vitest";
import {
createPluginSecretsHandler,
extractSecretRefPathsFromConfig,
PLUGIN_SECRET_REFS_DISABLED_MESSAGE,
} from "../services/plugin-secrets-handler.js";
describe("createPluginSecretsHandler", () => {
it("ignores UUID-looking metadata outside schema-declared secret-ref paths", () => {
const secretRef = "77777777-7777-4777-8777-777777777777";
const refs = extractSecretRefPathsFromConfig(
{
credentials: {
apiKey: secretRef,
},
metadata: {
leakedLookingUuid: "88888888-8888-4888-8888-888888888888",
},
},
{
type: "object",
properties: {
credentials: {
type: "object",
properties: {
apiKey: { type: "string", format: "secret-ref" },
},
},
metadata: {
type: "object",
properties: {
leakedLookingUuid: { type: "string" },
},
},
},
},
);
expect(Array.from(refs.entries())).toEqual([
[secretRef, new Set(["credentials.apiKey"])],
]);
});
it("fails closed for plugin secret resolution until company scoping lands", async () => {
const handler = createPluginSecretsHandler({
db: {} as never,