@stigmer/sdk 3.35.0 → 3.37.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/activity.d.ts.map +1 -1
- package/activity.js.map +1 -1
- package/artifact-routing.d.ts.map +1 -1
- package/artifact-routing.js.map +1 -1
- package/authorization-config.d.ts.map +1 -1
- package/authorization-config.js.map +1 -1
- package/billing.d.ts.map +1 -1
- package/billing.js.map +1 -1
- package/config.d.ts.map +1 -1
- package/config.js.map +1 -1
- package/cursor-accounts.d.ts.map +1 -1
- package/cursor-accounts.js.map +1 -1
- package/ensure-identity-account.d.ts.map +1 -1
- package/ensure-identity-account.js.map +1 -1
- package/errors.d.ts.map +1 -1
- package/errors.js.map +1 -1
- package/execution/approval-provenance.d.ts.map +1 -1
- package/execution/approval-provenance.js.map +1 -1
- package/execution/conversation-rules.d.ts.map +1 -1
- package/execution/conversation-rules.js.map +1 -1
- package/execution/execution-phases.d.ts.map +1 -1
- package/execution/execution-phases.js.map +1 -1
- package/execution/file-review-fold.d.ts.map +1 -1
- package/execution/file-review-fold.js.map +1 -1
- package/execution/to-display-file-change.d.ts.map +1 -1
- package/execution/to-display-file-change.js.map +1 -1
- package/execution/tool-view.d.ts.map +1 -1
- package/execution/tool-view.js.map +1 -1
- package/execution/transcript.d.ts.map +1 -1
- package/execution/transcript.js.map +1 -1
- package/gen/agent.d.ts.map +1 -1
- package/gen/agent.js.map +1 -1
- package/gen/agentchannel.d.ts.map +1 -1
- package/gen/agentchannel.js.map +1 -1
- package/gen/agentexecution.d.ts.map +1 -1
- package/gen/agentexecution.js.map +1 -1
- package/gen/agentinstance.d.ts.map +1 -1
- package/gen/agentinstance.js.map +1 -1
- package/gen/agentshare.d.ts.map +1 -1
- package/gen/agentshare.js.map +1 -1
- package/gen/apikey.d.ts.map +1 -1
- package/gen/apikey.js.map +1 -1
- package/gen/artifact.d.ts.map +1 -1
- package/gen/artifact.js.map +1 -1
- package/gen/authorization-config.d.ts.map +1 -1
- package/gen/authorization-config.js +2 -2
- package/gen/authorization-config.js.map +1 -1
- package/gen/bidi-stream.d.ts.map +1 -1
- package/gen/bidi-stream.js.map +1 -1
- package/gen/channelapp.d.ts.map +1 -1
- package/gen/channelapp.js.map +1 -1
- package/gen/client.d.ts.map +1 -1
- package/gen/client.js.map +1 -1
- package/gen/environment.d.ts.map +1 -1
- package/gen/environment.js.map +1 -1
- package/gen/errors.d.ts.map +1 -1
- package/gen/errors.js.map +1 -1
- package/gen/executioncontext.d.ts.map +1 -1
- package/gen/executioncontext.js.map +1 -1
- package/gen/iampolicy.d.ts.map +1 -1
- package/gen/iampolicy.js.map +1 -1
- package/gen/identityaccount.d.ts.map +1 -1
- package/gen/identityaccount.js.map +1 -1
- package/gen/identityprovider.d.ts.map +1 -1
- package/gen/identityprovider.js.map +1 -1
- package/gen/invitation.d.ts.map +1 -1
- package/gen/invitation.js.map +1 -1
- package/gen/license.d.ts.map +1 -1
- package/gen/license.js.map +1 -1
- package/gen/mcpserver.d.ts.map +1 -1
- package/gen/mcpserver.js.map +1 -1
- package/gen/memory.d.ts.map +1 -1
- package/gen/memory.js.map +1 -1
- package/gen/oauthapp.d.ts.map +1 -1
- package/gen/oauthapp.js.map +1 -1
- package/gen/organization.d.ts.map +1 -1
- package/gen/organization.js.map +1 -1
- package/gen/plan.d.ts.map +1 -1
- package/gen/plan.js.map +1 -1
- package/gen/platformclient.d.ts.map +1 -1
- package/gen/platformclient.js.map +1 -1
- package/gen/plugin.d.ts.map +1 -1
- package/gen/plugin.js.map +1 -1
- package/gen/proto-utils.d.ts.map +1 -1
- package/gen/proto-utils.js.map +1 -1
- package/gen/resource-availability.d.ts.map +1 -1
- package/gen/resource-availability.js.map +1 -1
- package/gen/schedule.d.ts.map +1 -1
- package/gen/schedule.js.map +1 -1
- package/gen/session.d.ts.map +1 -1
- package/gen/session.js.map +1 -1
- package/gen/skill.d.ts.map +1 -1
- package/gen/skill.js.map +1 -1
- package/gen/subscription.d.ts.map +1 -1
- package/gen/subscription.js.map +1 -1
- package/gen/team.d.ts.map +1 -1
- package/gen/team.js.map +1 -1
- package/gen/types.d.ts.map +1 -1
- package/gen/types.js.map +1 -1
- package/gen/workflow.d.ts.map +1 -1
- package/gen/workflow.js.map +1 -1
- package/gen/workflowexecution.d.ts.map +1 -1
- package/gen/workflowexecution.js.map +1 -1
- package/gen/workflowinstance.d.ts.map +1 -1
- package/gen/workflowinstance.js.map +1 -1
- package/github.d.ts.map +1 -1
- package/github.js.map +1 -1
- package/guest-auth.d.ts.map +1 -1
- package/guest-auth.js.map +1 -1
- package/iam-principal.d.ts +6 -0
- package/iam-principal.d.ts.map +1 -1
- package/iam-principal.js +19 -0
- package/iam-principal.js.map +1 -1
- package/iam-role.d.ts.map +1 -1
- package/iam-role.js.map +1 -1
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/internal/interceptors.d.ts.map +1 -1
- package/internal/interceptors.js.map +1 -1
- package/manifest/client.d.ts.map +1 -1
- package/manifest/client.js.map +1 -1
- package/manifest/document.d.ts.map +1 -1
- package/manifest/document.js.map +1 -1
- package/manifest/index.d.ts.map +1 -1
- package/manifest/index.js.map +1 -1
- package/manifest/parse.d.ts.map +1 -1
- package/manifest/parse.js.map +1 -1
- package/manifest/redaction.d.ts.map +1 -1
- package/manifest/redaction.js.map +1 -1
- package/manifest/registry.d.ts.map +1 -1
- package/manifest/registry.js.map +1 -1
- package/manifest/serialize.d.ts.map +1 -1
- package/manifest/serialize.js.map +1 -1
- package/mcpserver-connect.d.ts.map +1 -1
- package/mcpserver-connect.js.map +1 -1
- package/node.d.ts.map +1 -1
- package/node.js.map +1 -1
- package/package.json +2 -2
- package/platform-client-auth.d.ts.map +1 -1
- package/platform-client-auth.js.map +1 -1
- package/platform.d.ts.map +1 -1
- package/platform.js.map +1 -1
- package/plugin.d.ts.map +1 -1
- package/plugin.js.map +1 -1
- package/provider-standing.d.ts.map +1 -1
- package/provider-standing.js.map +1 -1
- package/resource-availability.d.ts.map +1 -1
- package/resource-availability.js.map +1 -1
- package/runner-adapter.d.ts.map +1 -1
- package/runner-adapter.js.map +1 -1
- package/search.d.ts.map +1 -1
- package/search.js.map +1 -1
- package/session.d.ts.map +1 -1
- package/session.js.map +1 -1
- package/sharing.d.ts.map +1 -1
- package/sharing.js.map +1 -1
- package/skill.d.ts.map +1 -1
- package/skill.js.map +1 -1
- package/src/gen/authorization-config.ts +2 -2
- package/src/iam-principal.ts +24 -0
- package/src/index.ts +1 -0
- package/stigmer.d.ts.map +1 -1
- package/stigmer.js.map +1 -1
- package/transport.d.ts.map +1 -1
- package/transport.js.map +1 -1
- package/__tests__/billing.test.d.ts +0 -2
- package/__tests__/billing.test.d.ts.map +0 -1
- package/__tests__/billing.test.js +0 -120
- package/__tests__/billing.test.js.map +0 -1
- package/__tests__/config.test.d.ts +0 -2
- package/__tests__/config.test.d.ts.map +0 -1
- package/__tests__/config.test.js +0 -35
- package/__tests__/config.test.js.map +0 -1
- package/__tests__/ensure-identity-account.test.d.ts +0 -2
- package/__tests__/ensure-identity-account.test.d.ts.map +0 -1
- package/__tests__/ensure-identity-account.test.js +0 -108
- package/__tests__/ensure-identity-account.test.js.map +0 -1
- package/__tests__/errors.test.d.ts +0 -2
- package/__tests__/errors.test.d.ts.map +0 -1
- package/__tests__/errors.test.js +0 -228
- package/__tests__/errors.test.js.map +0 -1
- package/__tests__/gen/errors.test.d.ts +0 -2
- package/__tests__/gen/errors.test.d.ts.map +0 -1
- package/__tests__/gen/errors.test.js +0 -97
- package/__tests__/gen/errors.test.js.map +0 -1
- package/__tests__/gen/invitation-client.test.d.ts +0 -2
- package/__tests__/gen/invitation-client.test.d.ts.map +0 -1
- package/__tests__/gen/invitation-client.test.js +0 -106
- package/__tests__/gen/invitation-client.test.js.map +0 -1
- package/__tests__/gen/proto-utils.test.d.ts +0 -2
- package/__tests__/gen/proto-utils.test.d.ts.map +0 -1
- package/__tests__/gen/proto-utils.test.js +0 -85
- package/__tests__/gen/proto-utils.test.js.map +0 -1
- package/__tests__/gen/session-client.test.d.ts +0 -2
- package/__tests__/gen/session-client.test.d.ts.map +0 -1
- package/__tests__/gen/session-client.test.js +0 -152
- package/__tests__/gen/session-client.test.js.map +0 -1
- package/__tests__/guest-auth.test.d.ts +0 -2
- package/__tests__/guest-auth.test.d.ts.map +0 -1
- package/__tests__/guest-auth.test.js +0 -223
- package/__tests__/guest-auth.test.js.map +0 -1
- package/__tests__/iam-principal.test.d.ts +0 -2
- package/__tests__/iam-principal.test.d.ts.map +0 -1
- package/__tests__/iam-principal.test.js +0 -65
- package/__tests__/iam-principal.test.js.map +0 -1
- package/__tests__/manifest.test.d.ts +0 -2
- package/__tests__/manifest.test.d.ts.map +0 -1
- package/__tests__/manifest.test.js +0 -306
- package/__tests__/manifest.test.js.map +0 -1
- package/__tests__/mcpserver-connect.test.d.ts +0 -2
- package/__tests__/mcpserver-connect.test.d.ts.map +0 -1
- package/__tests__/mcpserver-connect.test.js +0 -146
- package/__tests__/mcpserver-connect.test.js.map +0 -1
- package/__tests__/node.test.d.ts +0 -2
- package/__tests__/node.test.d.ts.map +0 -1
- package/__tests__/node.test.js +0 -67
- package/__tests__/node.test.js.map +0 -1
- package/__tests__/platform-client-auth.test.d.ts +0 -2
- package/__tests__/platform-client-auth.test.d.ts.map +0 -1
- package/__tests__/platform-client-auth.test.js +0 -59
- package/__tests__/platform-client-auth.test.js.map +0 -1
- package/__tests__/platform.test.d.ts +0 -2
- package/__tests__/platform.test.d.ts.map +0 -1
- package/__tests__/platform.test.js +0 -52
- package/__tests__/platform.test.js.map +0 -1
- package/__tests__/plugin.test.d.ts +0 -2
- package/__tests__/plugin.test.d.ts.map +0 -1
- package/__tests__/plugin.test.js +0 -74
- package/__tests__/plugin.test.js.map +0 -1
- package/__tests__/resource-availability.test.d.ts +0 -2
- package/__tests__/resource-availability.test.d.ts.map +0 -1
- package/__tests__/resource-availability.test.js +0 -80
- package/__tests__/resource-availability.test.js.map +0 -1
- package/__tests__/runner-adapter.test.d.ts +0 -2
- package/__tests__/runner-adapter.test.d.ts.map +0 -1
- package/__tests__/runner-adapter.test.js +0 -88
- package/__tests__/runner-adapter.test.js.map +0 -1
- package/__tests__/session.test.d.ts +0 -6
- package/__tests__/session.test.d.ts.map +0 -1
- package/__tests__/session.test.js +0 -50
- package/__tests__/session.test.js.map +0 -1
- package/__tests__/sharing.test.d.ts +0 -2
- package/__tests__/sharing.test.d.ts.map +0 -1
- package/__tests__/sharing.test.js +0 -106
- package/__tests__/sharing.test.js.map +0 -1
- package/__tests__/skill.test.d.ts +0 -2
- package/__tests__/skill.test.d.ts.map +0 -1
- package/__tests__/skill.test.js +0 -117
- package/__tests__/skill.test.js.map +0 -1
- package/__tests__/stigmer.test.d.ts +0 -2
- package/__tests__/stigmer.test.d.ts.map +0 -1
- package/__tests__/stigmer.test.js +0 -127
- package/__tests__/stigmer.test.js.map +0 -1
- package/__tests__/update-input-roundtrip.test.d.ts +0 -2
- package/__tests__/update-input-roundtrip.test.d.ts.map +0 -1
- package/__tests__/update-input-roundtrip.test.js +0 -775
- package/__tests__/update-input-roundtrip.test.js.map +0 -1
- package/__tests__/update-input.test.d.ts +0 -2
- package/__tests__/update-input.test.d.ts.map +0 -1
- package/__tests__/update-input.test.js +0 -188
- package/__tests__/update-input.test.js.map +0 -1
- package/execution/__tests__/approval-provenance.test.d.ts +0 -2
- package/execution/__tests__/approval-provenance.test.d.ts.map +0 -1
- package/execution/__tests__/approval-provenance.test.js +0 -42
- package/execution/__tests__/approval-provenance.test.js.map +0 -1
- package/execution/__tests__/file-review-fold.corpus.test.d.ts +0 -2
- package/execution/__tests__/file-review-fold.corpus.test.d.ts.map +0 -1
- package/execution/__tests__/file-review-fold.corpus.test.js +0 -82
- package/execution/__tests__/file-review-fold.corpus.test.js.map +0 -1
- package/execution/__tests__/file-review-fold.test.d.ts +0 -2
- package/execution/__tests__/file-review-fold.test.d.ts.map +0 -1
- package/execution/__tests__/file-review-fold.test.js +0 -184
- package/execution/__tests__/file-review-fold.test.js.map +0 -1
- package/execution/__tests__/to-display-file-change.test.d.ts +0 -2
- package/execution/__tests__/to-display-file-change.test.d.ts.map +0 -1
- package/execution/__tests__/to-display-file-change.test.js +0 -81
- package/execution/__tests__/to-display-file-change.test.js.map +0 -1
- package/execution/__tests__/tool-view.file-changes.test.d.ts +0 -2
- package/execution/__tests__/tool-view.file-changes.test.d.ts.map +0 -1
- package/execution/__tests__/tool-view.file-changes.test.js +0 -86
- package/execution/__tests__/tool-view.file-changes.test.js.map +0 -1
- package/execution/__tests__/tool-view.fixtures.test.d.ts +0 -2
- package/execution/__tests__/tool-view.fixtures.test.d.ts.map +0 -1
- package/execution/__tests__/tool-view.fixtures.test.js +0 -152
- package/execution/__tests__/tool-view.fixtures.test.js.map +0 -1
- package/execution/__tests__/tool-view.output-ref.test.d.ts +0 -2
- package/execution/__tests__/tool-view.output-ref.test.d.ts.map +0 -1
- package/execution/__tests__/tool-view.output-ref.test.js +0 -64
- package/execution/__tests__/tool-view.output-ref.test.js.map +0 -1
- package/execution/__tests__/tool-view.read.test.d.ts +0 -2
- package/execution/__tests__/tool-view.read.test.d.ts.map +0 -1
- package/execution/__tests__/tool-view.read.test.js +0 -56
- package/execution/__tests__/tool-view.read.test.js.map +0 -1
- package/execution/__tests__/tool-view.search.test.d.ts +0 -2
- package/execution/__tests__/tool-view.search.test.d.ts.map +0 -1
- package/execution/__tests__/tool-view.search.test.js +0 -200
- package/execution/__tests__/tool-view.search.test.js.map +0 -1
- package/execution/__tests__/tool-view.shell.test.d.ts +0 -2
- package/execution/__tests__/tool-view.shell.test.d.ts.map +0 -1
- package/execution/__tests__/tool-view.shell.test.js +0 -104
- package/execution/__tests__/tool-view.shell.test.js.map +0 -1
- package/execution/__tests__/transcript.test.d.ts +0 -2
- package/execution/__tests__/transcript.test.d.ts.map +0 -1
- package/execution/__tests__/transcript.test.js +0 -591
- package/execution/__tests__/transcript.test.js.map +0 -1
- package/node.test.d.ts +0 -2
- package/node.test.d.ts.map +0 -1
- package/node.test.js +0 -35
- package/node.test.js.map +0 -1
- package/src/__tests__/billing.test.ts +0 -146
- package/src/__tests__/config.test.ts +0 -52
- package/src/__tests__/ensure-identity-account.test.ts +0 -146
- package/src/__tests__/errors.test.ts +0 -349
- package/src/__tests__/gen/errors.test.ts +0 -138
- package/src/__tests__/gen/invitation-client.test.ts +0 -132
- package/src/__tests__/gen/proto-utils.test.ts +0 -99
- package/src/__tests__/gen/session-client.test.ts +0 -208
- package/src/__tests__/guest-auth.test.ts +0 -287
- package/src/__tests__/iam-principal.test.ts +0 -82
- package/src/__tests__/manifest.test.ts +0 -362
- package/src/__tests__/mcpserver-connect.test.ts +0 -181
- package/src/__tests__/node.test.ts +0 -74
- package/src/__tests__/platform-client-auth.test.ts +0 -76
- package/src/__tests__/platform.test.ts +0 -74
- package/src/__tests__/plugin.test.ts +0 -92
- package/src/__tests__/resource-availability.test.ts +0 -118
- package/src/__tests__/runner-adapter.test.ts +0 -122
- package/src/__tests__/session.test.ts +0 -66
- package/src/__tests__/sharing.test.ts +0 -159
- package/src/__tests__/skill.test.ts +0 -150
- package/src/__tests__/stigmer.test.ts +0 -170
- package/src/__tests__/update-input-roundtrip.test.ts +0 -1007
- package/src/__tests__/update-input.test.ts +0 -250
- package/src/execution/__tests__/approval-provenance.test.ts +0 -60
- package/src/execution/__tests__/file-review-fold.corpus.test.ts +0 -127
- package/src/execution/__tests__/file-review-fold.test.ts +0 -281
- package/src/execution/__tests__/to-display-file-change.test.ts +0 -106
- package/src/execution/__tests__/tool-view.file-changes.test.ts +0 -100
- package/src/execution/__tests__/tool-view.fixtures.test.ts +0 -225
- package/src/execution/__tests__/tool-view.output-ref.test.ts +0 -76
- package/src/execution/__tests__/tool-view.read.test.ts +0 -71
- package/src/execution/__tests__/tool-view.search.test.ts +0 -264
- package/src/execution/__tests__/tool-view.shell.test.ts +0 -127
- package/src/execution/__tests__/transcript.golden.md +0 -100
- package/src/execution/__tests__/transcript.test.ts +0 -697
- package/src/node.test.ts +0 -38
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { create } from "@bufbuild/protobuf";
|
|
3
|
-
import { MintGuestTokenResponseSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/token_pb";
|
|
4
|
-
import { ConnectError, Code } from "@connectrpc/connect";
|
|
5
|
-
// Intercept the token client so no transport is exercised. The mock
|
|
6
|
-
// preserves the real module (create/Code/ConnectError) and only stubs
|
|
7
|
-
// createClient, which GuestAuth uses to build its RPC client.
|
|
8
|
-
const mintGuestToken = vi.fn();
|
|
9
|
-
vi.mock("@connectrpc/connect", async (importOriginal) => {
|
|
10
|
-
const actual = await importOriginal();
|
|
11
|
-
return {
|
|
12
|
-
...actual,
|
|
13
|
-
createClient: () => ({ mintGuestToken }),
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
import { createGuestAuth, GuestAuth } from "../guest-auth";
|
|
17
|
-
const CONFIG = {
|
|
18
|
-
baseUrl: "https://api.stigmer.ai",
|
|
19
|
-
org: "acme",
|
|
20
|
-
slug: "support-agent",
|
|
21
|
-
};
|
|
22
|
-
function createMemoryStorage() {
|
|
23
|
-
const store = new Map();
|
|
24
|
-
return {
|
|
25
|
-
store,
|
|
26
|
-
getItem: (key) => store.get(key) ?? null,
|
|
27
|
-
setItem: (key, value) => {
|
|
28
|
-
store.set(key, value);
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function mintResponse(overrides) {
|
|
33
|
-
return create(MintGuestTokenResponseSchema, {
|
|
34
|
-
accessToken: overrides?.accessToken ?? "guest-jwt-1",
|
|
35
|
-
tokenType: "Bearer",
|
|
36
|
-
expiresIn: overrides?.expiresIn ?? 900,
|
|
37
|
-
guestCookieId: overrides?.guestCookieId ?? "cookie-abc",
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
mintGuestToken.mockReset();
|
|
42
|
-
vi.useFakeTimers();
|
|
43
|
-
});
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
vi.useRealTimers();
|
|
46
|
-
});
|
|
47
|
-
describe("createGuestAuth", () => {
|
|
48
|
-
it("throws when baseUrl is missing", () => {
|
|
49
|
-
expect(() => createGuestAuth({ ...CONFIG, baseUrl: "" })).toThrow("baseUrl is required");
|
|
50
|
-
});
|
|
51
|
-
it("throws when org is missing", () => {
|
|
52
|
-
expect(() => createGuestAuth({ ...CONFIG, org: "" })).toThrow("org is required");
|
|
53
|
-
});
|
|
54
|
-
it("throws when slug is missing", () => {
|
|
55
|
-
expect(() => createGuestAuth({ ...CONFIG, slug: "" })).toThrow("slug is required");
|
|
56
|
-
});
|
|
57
|
-
it("returns a GuestAuth instance with valid config", () => {
|
|
58
|
-
expect(createGuestAuth(CONFIG)).toBeInstanceOf(GuestAuth);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
describe("GuestAuth.getAccessToken", () => {
|
|
62
|
-
it("mints on first call and sends an empty guest id", async () => {
|
|
63
|
-
mintGuestToken.mockResolvedValue(mintResponse());
|
|
64
|
-
const auth = createGuestAuth({ ...CONFIG, storage: createMemoryStorage() });
|
|
65
|
-
const token = await auth.getAccessToken();
|
|
66
|
-
expect(token).toBe("guest-jwt-1");
|
|
67
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(1);
|
|
68
|
-
expect(mintGuestToken.mock.calls[0][0]).toMatchObject({
|
|
69
|
-
org: "acme",
|
|
70
|
-
slug: "support-agent",
|
|
71
|
-
guestCookieId: "",
|
|
72
|
-
// No embedOrigin configured (the unframed hosted page): the field
|
|
73
|
-
// must stay empty so the server's absence-means-exempt rule applies.
|
|
74
|
-
embedOrigin: "",
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
it("passes the configured embedOrigin through to every mint", async () => {
|
|
78
|
-
mintGuestToken.mockResolvedValue(mintResponse());
|
|
79
|
-
const auth = createGuestAuth({
|
|
80
|
-
...CONFIG,
|
|
81
|
-
storage: createMemoryStorage(),
|
|
82
|
-
embedOrigin: "https://docs.example.com",
|
|
83
|
-
});
|
|
84
|
-
await auth.getAccessToken();
|
|
85
|
-
// Expire the cached token, forcing a re-mint — the origin must persist.
|
|
86
|
-
vi.advanceTimersByTime(900_000);
|
|
87
|
-
await auth.getAccessToken();
|
|
88
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(2);
|
|
89
|
-
for (const call of mintGuestToken.mock.calls) {
|
|
90
|
-
expect(call[0]).toMatchObject({ embedOrigin: "https://docs.example.com" });
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
it("passes the configured linkToken through to every mint", async () => {
|
|
94
|
-
mintGuestToken.mockResolvedValue(mintResponse());
|
|
95
|
-
const auth = createGuestAuth({
|
|
96
|
-
...CONFIG,
|
|
97
|
-
storage: createMemoryStorage(),
|
|
98
|
-
linkToken: "tok123",
|
|
99
|
-
});
|
|
100
|
-
await auth.getAccessToken();
|
|
101
|
-
// Expire the cached token, forcing a re-mint — the token must persist
|
|
102
|
-
// so a locked link keeps working across silent re-mints.
|
|
103
|
-
vi.advanceTimersByTime(900_000);
|
|
104
|
-
await auth.getAccessToken();
|
|
105
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(2);
|
|
106
|
-
for (const call of mintGuestToken.mock.calls) {
|
|
107
|
-
expect(call[0]).toMatchObject({ linkToken: "tok123" });
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
it("sends an empty linkToken when none is configured (plain link)", async () => {
|
|
111
|
-
mintGuestToken.mockResolvedValue(mintResponse());
|
|
112
|
-
const auth = createGuestAuth({ ...CONFIG, storage: createMemoryStorage() });
|
|
113
|
-
await auth.getAccessToken();
|
|
114
|
-
expect(mintGuestToken.mock.calls[0][0]).toMatchObject({ linkToken: "" });
|
|
115
|
-
});
|
|
116
|
-
it("rejects with permission-denied when the embed origin is refused", async () => {
|
|
117
|
-
mintGuestToken.mockRejectedValue(new ConnectError("This agent can\u2019t be embedded on this site.", Code.PermissionDenied));
|
|
118
|
-
const auth = createGuestAuth({
|
|
119
|
-
...CONFIG,
|
|
120
|
-
storage: createMemoryStorage(),
|
|
121
|
-
embedOrigin: "https://evil.example.com",
|
|
122
|
-
});
|
|
123
|
-
await expect(auth.getAccessToken()).rejects.toMatchObject({
|
|
124
|
-
code: "permission-denied",
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
it("persists the server-issued guest id and presents it on re-mint", async () => {
|
|
128
|
-
const storage = createMemoryStorage();
|
|
129
|
-
mintGuestToken.mockResolvedValue(mintResponse({ guestCookieId: "cookie-abc" }));
|
|
130
|
-
const auth = createGuestAuth({ ...CONFIG, storage });
|
|
131
|
-
await auth.getAccessToken();
|
|
132
|
-
expect(storage.store.get("stigmer:guest-id:acme")).toBe("cookie-abc");
|
|
133
|
-
expect(auth.guestCookieId).toBe("cookie-abc");
|
|
134
|
-
// Expire the cached token, forcing a second mint.
|
|
135
|
-
vi.advanceTimersByTime(900_000);
|
|
136
|
-
await auth.getAccessToken();
|
|
137
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(2);
|
|
138
|
-
expect(mintGuestToken.mock.calls[1][0]).toMatchObject({
|
|
139
|
-
guestCookieId: "cookie-abc",
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
it("restores a persisted guest id from a prior visit", async () => {
|
|
143
|
-
const storage = createMemoryStorage();
|
|
144
|
-
storage.setItem("stigmer:guest-id:acme", "cookie-from-last-visit");
|
|
145
|
-
mintGuestToken.mockResolvedValue(mintResponse());
|
|
146
|
-
const auth = createGuestAuth({ ...CONFIG, storage });
|
|
147
|
-
await auth.getAccessToken();
|
|
148
|
-
expect(mintGuestToken.mock.calls[0][0]).toMatchObject({
|
|
149
|
-
guestCookieId: "cookie-from-last-visit",
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
it("returns the cached token while it is fresh", async () => {
|
|
153
|
-
mintGuestToken.mockResolvedValue(mintResponse());
|
|
154
|
-
const auth = createGuestAuth({ ...CONFIG, storage: createMemoryStorage() });
|
|
155
|
-
await auth.getAccessToken();
|
|
156
|
-
// 13 minutes into a 15-minute token: still beyond the 60s skew.
|
|
157
|
-
vi.advanceTimersByTime(13 * 60_000);
|
|
158
|
-
const token = await auth.getAccessToken();
|
|
159
|
-
expect(token).toBe("guest-jwt-1");
|
|
160
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(1);
|
|
161
|
-
});
|
|
162
|
-
it("re-mints when the cached token is within the expiry skew", async () => {
|
|
163
|
-
mintGuestToken
|
|
164
|
-
.mockResolvedValueOnce(mintResponse({ accessToken: "guest-jwt-1" }))
|
|
165
|
-
.mockResolvedValueOnce(mintResponse({ accessToken: "guest-jwt-2" }));
|
|
166
|
-
const auth = createGuestAuth({ ...CONFIG, storage: createMemoryStorage() });
|
|
167
|
-
await auth.getAccessToken();
|
|
168
|
-
// 30 seconds of life left — inside the 60s skew window.
|
|
169
|
-
vi.advanceTimersByTime(900_000 - 30_000);
|
|
170
|
-
const token = await auth.getAccessToken();
|
|
171
|
-
expect(token).toBe("guest-jwt-2");
|
|
172
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(2);
|
|
173
|
-
});
|
|
174
|
-
it("collapses concurrent callers into a single mint", async () => {
|
|
175
|
-
let release;
|
|
176
|
-
mintGuestToken.mockImplementation(() => new Promise((resolve) => { release = resolve; }));
|
|
177
|
-
const auth = createGuestAuth({ ...CONFIG, storage: createMemoryStorage() });
|
|
178
|
-
const first = auth.getAccessToken();
|
|
179
|
-
const second = auth.getAccessToken();
|
|
180
|
-
release(mintResponse());
|
|
181
|
-
await expect(first).resolves.toBe("guest-jwt-1");
|
|
182
|
-
await expect(second).resolves.toBe("guest-jwt-1");
|
|
183
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(1);
|
|
184
|
-
});
|
|
185
|
-
it("rejects with a wrapped StigmerError when sharing is revoked", async () => {
|
|
186
|
-
mintGuestToken.mockRejectedValue(new ConnectError("agent not found", Code.NotFound));
|
|
187
|
-
const auth = createGuestAuth({ ...CONFIG, storage: createMemoryStorage() });
|
|
188
|
-
try {
|
|
189
|
-
await auth.getAccessToken();
|
|
190
|
-
expect.fail("should have thrown");
|
|
191
|
-
}
|
|
192
|
-
catch (e) {
|
|
193
|
-
expect(e).toHaveProperty("name", "StigmerError");
|
|
194
|
-
expect(e).toHaveProperty("code", "not-found");
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
it("recovers after a failed mint instead of caching the failure", async () => {
|
|
198
|
-
mintGuestToken
|
|
199
|
-
.mockRejectedValueOnce(new ConnectError("unavailable", Code.Unavailable))
|
|
200
|
-
.mockResolvedValueOnce(mintResponse());
|
|
201
|
-
const auth = createGuestAuth({ ...CONFIG, storage: createMemoryStorage() });
|
|
202
|
-
await expect(auth.getAccessToken()).rejects.toMatchObject({
|
|
203
|
-
code: "unavailable",
|
|
204
|
-
});
|
|
205
|
-
await expect(auth.getAccessToken()).resolves.toBe("guest-jwt-1");
|
|
206
|
-
expect(mintGuestToken).toHaveBeenCalledTimes(2);
|
|
207
|
-
});
|
|
208
|
-
it("still mints when storage throws", async () => {
|
|
209
|
-
const brokenStorage = {
|
|
210
|
-
getItem: () => {
|
|
211
|
-
throw new Error("storage disabled");
|
|
212
|
-
},
|
|
213
|
-
setItem: () => {
|
|
214
|
-
throw new Error("storage disabled");
|
|
215
|
-
},
|
|
216
|
-
};
|
|
217
|
-
mintGuestToken.mockResolvedValue(mintResponse());
|
|
218
|
-
const auth = createGuestAuth({ ...CONFIG, storage: brokenStorage });
|
|
219
|
-
await expect(auth.getAccessToken()).resolves.toBe("guest-jwt-1");
|
|
220
|
-
expect(auth.guestCookieId).toBeNull();
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
//# sourceMappingURL=guest-auth.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"guest-auth.test.js","sourceRoot":"","sources":["../../src/__tests__/guest-auth.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"iam-principal.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/iam-principal.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pins the grantee vocabulary (`iam-principal.ts`) and the team half of the
|
|
3
|
-
* authorization config (`authorization-config.ts`):
|
|
4
|
-
*
|
|
5
|
-
* - a team is always granted as `team:<id>#member` and a person always
|
|
6
|
-
* unqualified, because the server's revoke matches the qualifier
|
|
7
|
-
* exactly and a dropped `#member` revokes nothing while reporting
|
|
8
|
-
* success;
|
|
9
|
-
* - reading an access-list entry back is the inverse of building one,
|
|
10
|
-
* and anything else (a structural principal, another team qualifier)
|
|
11
|
-
* is refused rather than guessed at;
|
|
12
|
-
* - a team may only ever be offered a subset of a person's roles, never
|
|
13
|
-
* `owner`, and nothing on `organization` (the circular grant the
|
|
14
|
-
* model's membership bound forbids).
|
|
15
|
-
*/
|
|
16
|
-
import { describe, expect, it } from "vitest";
|
|
17
|
-
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
18
|
-
import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
19
|
-
import { getGrantableRoles, getTeamGrantableRoles, hasTeamGrantableRoles, isRoleTeamGrantable, } from "../authorization-config";
|
|
20
|
-
import { TEAM_GRANTABLE_ROLES } from "../gen/authorization-config";
|
|
21
|
-
import { granteeFromView, granteeRef, personGrantee, teamGrantee, } from "../iam-principal";
|
|
22
|
-
describe("granteeRef — the one spelling of a grantee on the wire", () => {
|
|
23
|
-
it("names a team as its members", () => {
|
|
24
|
-
const ref = granteeRef(teamGrantee("tm_sre"));
|
|
25
|
-
expect([ref.kind, ref.id, ref.relation]).toEqual(["team", "tm_sre", "member"]);
|
|
26
|
-
});
|
|
27
|
-
it("names a person with no relation qualifier", () => {
|
|
28
|
-
const ref = granteeRef(personGrantee("ida_alice"));
|
|
29
|
-
expect([ref.kind, ref.id, ref.relation]).toEqual(["identity_account", "ida_alice", ""]);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
describe("granteeFromView — reading an access-list entry back", () => {
|
|
33
|
-
it("round-trips both grantees through their wire reference", () => {
|
|
34
|
-
for (const grantee of [teamGrantee("tm_sre"), personGrantee("ida_alice")]) {
|
|
35
|
-
expect(granteeFromView(granteeRef(grantee))).toEqual(grantee);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
it("refuses what it would misname: a team without its members qualifier, a qualified person, a structural principal, an empty id", () => {
|
|
39
|
-
expect(granteeFromView({ kind: "team", id: "tm_sre", relation: "" })).toBeUndefined();
|
|
40
|
-
expect(granteeFromView({ kind: "team", id: "tm_sre", relation: "maintainer" })).toBeUndefined();
|
|
41
|
-
expect(granteeFromView({ kind: "identity_account", id: "ida_alice", relation: "member" })).toBeUndefined();
|
|
42
|
-
expect(granteeFromView({ kind: "organization", id: "acme", relation: "" })).toBeUndefined();
|
|
43
|
-
expect(granteeFromView({ kind: "identity_account", id: "", relation: "" })).toBeUndefined();
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe("team grantable roles", () => {
|
|
47
|
-
it("are, for every kind, a subset of the person's roles and never owner", () => {
|
|
48
|
-
for (const [kind, teamRoles] of TEAM_GRANTABLE_ROLES) {
|
|
49
|
-
const personRoles = getGrantableRoles(kind);
|
|
50
|
-
for (const role of teamRoles) {
|
|
51
|
-
expect(personRoles).toContain(role);
|
|
52
|
-
expect(role).not.toBe(IamRole.owner);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
it("list nothing on organization, so an organization is never shared with a team", () => {
|
|
57
|
-
expect(hasTeamGrantableRoles(ApiResourceKind.organization)).toBe(false);
|
|
58
|
-
expect(getTeamGrantableRoles(ApiResourceKind.organization)).toEqual([]);
|
|
59
|
-
});
|
|
60
|
-
it("answer per role on a kind a team may be shared", () => {
|
|
61
|
-
expect(isRoleTeamGrantable(ApiResourceKind.agent, IamRole.viewer)).toBe(true);
|
|
62
|
-
expect(isRoleTeamGrantable(ApiResourceKind.agent, IamRole.owner)).toBe(false);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
//# sourceMappingURL=iam-principal.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"iam-principal.test.js","sourceRoot":"","sources":["../../src/__tests__/iam-principal.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/manifest.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { clone, create, equals } from "@bufbuild/protobuf";
|
|
3
|
-
import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
4
|
-
import { EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
5
|
-
import { ScheduleSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
|
|
6
|
-
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
7
|
-
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
8
|
-
import { parse as parseYaml } from "yaml";
|
|
9
|
-
import { parseManifest } from "../manifest/parse";
|
|
10
|
-
import { serializeManifest } from "../manifest/serialize";
|
|
11
|
-
import { manifestDocumentForResource } from "../manifest/document";
|
|
12
|
-
import { manifestKinds, manifestHandlerForYamlKind } from "../manifest/registry";
|
|
13
|
-
/**
|
|
14
|
-
* Manifest engine contract tests.
|
|
15
|
-
*
|
|
16
|
-
* The engine's core promise is *round-trip fidelity against the generated
|
|
17
|
-
* proto schemas*: any resource the server returns serializes to YAML that
|
|
18
|
-
* parses back to the same proto (minus system-managed state), and any
|
|
19
|
-
* repo-authored manifest (snake_case fields, `apiVersion` spelling) parses
|
|
20
|
-
* to a proto the `apply` RPC accepts. Fixtures mirror the real manifests
|
|
21
|
-
* in the whatsapp-doctor-assistant dogfooding repo.
|
|
22
|
-
*/
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// Fixtures — shaped like the whatsapp-doctor-assistant repo manifests
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
const AGENT_YAML = `
|
|
27
|
-
apiVersion: agentic.stigmer.ai/v1
|
|
28
|
-
kind: Agent
|
|
29
|
-
metadata:
|
|
30
|
-
name: clinic-patient-assistant
|
|
31
|
-
org: rakeshreddi098
|
|
32
|
-
spec:
|
|
33
|
-
description: Patient-facing WhatsApp assistant for the clinic.
|
|
34
|
-
instructions: |
|
|
35
|
-
You are the appointment assistant for the clinic.
|
|
36
|
-
Short messages. One question at a time.
|
|
37
|
-
`;
|
|
38
|
-
const ENVIRONMENT_YAML = `
|
|
39
|
-
apiVersion: agentic.stigmer.ai/v1
|
|
40
|
-
kind: Environment
|
|
41
|
-
metadata:
|
|
42
|
-
name: clinic-patient-db
|
|
43
|
-
org: rakeshreddi098
|
|
44
|
-
spec:
|
|
45
|
-
description: "Clinic records access for the patient assistant"
|
|
46
|
-
data:
|
|
47
|
-
POSTGRES_CONNECTION_URL:
|
|
48
|
-
value: "postgresql://patient_role:secret@host:5432/postgres"
|
|
49
|
-
is_secret: true
|
|
50
|
-
description: "Supabase Postgres connection URL for patient_role"
|
|
51
|
-
`;
|
|
52
|
-
const AGENT_CHANNEL_YAML = `
|
|
53
|
-
apiVersion: agentic.stigmer.ai/v1
|
|
54
|
-
kind: AgentChannel
|
|
55
|
-
metadata:
|
|
56
|
-
name: clinic-patient-whatsapp
|
|
57
|
-
org: rakeshreddi098
|
|
58
|
-
spec:
|
|
59
|
-
agent_ref:
|
|
60
|
-
kind: agent
|
|
61
|
-
org: rakeshreddi098
|
|
62
|
-
slug: clinic-patient-assistant
|
|
63
|
-
enabled: true
|
|
64
|
-
whatsapp:
|
|
65
|
-
phone_number_id: "1234567890"
|
|
66
|
-
app_ref:
|
|
67
|
-
kind: channel_app
|
|
68
|
-
org: rakeshreddi098
|
|
69
|
-
slug: hosipital
|
|
70
|
-
environment_refs:
|
|
71
|
-
- kind: environment
|
|
72
|
-
org: rakeshreddi098
|
|
73
|
-
slug: clinic-patient-db
|
|
74
|
-
`;
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
// parseManifest
|
|
77
|
-
// ---------------------------------------------------------------------------
|
|
78
|
-
describe("parseManifest", () => {
|
|
79
|
-
it("parses a snake_case Agent manifest into a full Agent proto", () => {
|
|
80
|
-
const docs = parseManifest(AGENT_YAML);
|
|
81
|
-
expect(docs).toHaveLength(1);
|
|
82
|
-
const doc = docs[0];
|
|
83
|
-
expect(doc.handler.yamlKind).toBe("Agent");
|
|
84
|
-
expect(doc.name).toBe("clinic-patient-assistant");
|
|
85
|
-
expect(doc.org).toBe("rakeshreddi098");
|
|
86
|
-
const agent = doc.message;
|
|
87
|
-
expect(agent.spec?.description).toBe("Patient-facing WhatsApp assistant for the clinic.");
|
|
88
|
-
expect(agent.spec?.instructions).toContain("appointment assistant");
|
|
89
|
-
});
|
|
90
|
-
it("parses an AgentChannel manifest with enum-valued resource refs", () => {
|
|
91
|
-
const docs = parseManifest(AGENT_CHANNEL_YAML);
|
|
92
|
-
expect(docs).toHaveLength(1);
|
|
93
|
-
expect(docs[0].handler.yamlKind).toBe("AgentChannel");
|
|
94
|
-
expect(docs[0].slug).toBe("clinic-patient-whatsapp");
|
|
95
|
-
});
|
|
96
|
-
it("sorts multi-document manifests into dependency apply order", () => {
|
|
97
|
-
// Authored channel-first; the Environment must still apply first.
|
|
98
|
-
const docs = parseManifest(`${AGENT_CHANNEL_YAML}\n---\n${ENVIRONMENT_YAML}`);
|
|
99
|
-
expect(docs.map((d) => d.handler.yamlKind)).toEqual([
|
|
100
|
-
"Environment",
|
|
101
|
-
"AgentChannel",
|
|
102
|
-
]);
|
|
103
|
-
});
|
|
104
|
-
it("injects the target org when the document omits it", () => {
|
|
105
|
-
const yaml = AGENT_YAML.replace(" org: rakeshreddi098\n", "");
|
|
106
|
-
const docs = parseManifest(yaml, { org: "acme" });
|
|
107
|
-
expect(docs[0].org).toBe("acme");
|
|
108
|
-
expect(docs[0].warning).toBeUndefined();
|
|
109
|
-
});
|
|
110
|
-
it("honors the document org and warns when it differs from the target", () => {
|
|
111
|
-
const docs = parseManifest(AGENT_YAML, { org: "acme" });
|
|
112
|
-
expect(docs[0].org).toBe("rakeshreddi098");
|
|
113
|
-
expect(docs[0].warning).toContain('"rakeshreddi098"');
|
|
114
|
-
expect(docs[0].warning).toContain('"acme"');
|
|
115
|
-
});
|
|
116
|
-
it("rejects unknown fields loudly (strict schema contract)", () => {
|
|
117
|
-
const yaml = AGENT_YAML.replace("spec:", "spec:\n instrctions: typo");
|
|
118
|
-
expect(() => parseManifest(yaml)).toThrow(/Invalid Agent/);
|
|
119
|
-
});
|
|
120
|
-
it("rejects a document without a kind", () => {
|
|
121
|
-
expect(() => parseManifest("metadata:\n name: x\n")).toThrow(/'kind'/);
|
|
122
|
-
});
|
|
123
|
-
it("rejects unsupported kinds with the supported list", () => {
|
|
124
|
-
expect(() => parseManifest("kind: Skill\nmetadata:\n name: x\n")).toThrow(/Unsupported resource kind "Skill".*Agent/s);
|
|
125
|
-
});
|
|
126
|
-
it("rejects empty input with actionable guidance", () => {
|
|
127
|
-
expect(() => parseManifest(" \n")).toThrow(/empty/i);
|
|
128
|
-
});
|
|
129
|
-
it("rejects malformed YAML", () => {
|
|
130
|
-
expect(() => parseManifest("kind: Agent\n bad indent: [")).toThrow(/Invalid YAML/);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
|
-
// serializeManifest
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
describe("serializeManifest", () => {
|
|
137
|
-
const agent = create(AgentSchema, {
|
|
138
|
-
apiVersion: "agentic.stigmer.ai/v1",
|
|
139
|
-
kind: "Agent",
|
|
140
|
-
metadata: {
|
|
141
|
-
id: "agt_01example",
|
|
142
|
-
name: "clinic-patient-assistant",
|
|
143
|
-
slug: "clinic-patient-assistant",
|
|
144
|
-
org: "rakeshreddi098",
|
|
145
|
-
version: { id: "ver_01", message: "server-managed" },
|
|
146
|
-
},
|
|
147
|
-
spec: {
|
|
148
|
-
description: "Patient-facing WhatsApp assistant.",
|
|
149
|
-
instructions: "Short messages.\nOne question at a time.\n",
|
|
150
|
-
},
|
|
151
|
-
status: { defaultInstanceId: "agi_01example" },
|
|
152
|
-
});
|
|
153
|
-
it("emits the canonical envelope: apiVersion spelling, no status", () => {
|
|
154
|
-
const yaml = serializeManifest(agent);
|
|
155
|
-
const doc = parseYaml(yaml);
|
|
156
|
-
expect(Object.keys(doc)[0]).toBe("apiVersion");
|
|
157
|
-
expect(doc.apiVersion).toBe("agentic.stigmer.ai/v1");
|
|
158
|
-
expect(doc.kind).toBe("Agent");
|
|
159
|
-
expect(doc.status).toBeUndefined();
|
|
160
|
-
expect(yaml).not.toContain("api_version:");
|
|
161
|
-
});
|
|
162
|
-
it("keeps metadata.id but strips server-managed metadata.version", () => {
|
|
163
|
-
const doc = parseYaml(serializeManifest(agent));
|
|
164
|
-
expect(doc.metadata.id).toBe("agt_01example");
|
|
165
|
-
expect(doc.metadata.version).toBeUndefined();
|
|
166
|
-
});
|
|
167
|
-
it("fills apiVersion and kind from the registry when the proto omits them", () => {
|
|
168
|
-
const bare = create(AgentSchema, {
|
|
169
|
-
metadata: { name: "x", org: "acme" },
|
|
170
|
-
});
|
|
171
|
-
const doc = parseYaml(serializeManifest(bare));
|
|
172
|
-
expect(doc.apiVersion).toBe("agentic.stigmer.ai/v1");
|
|
173
|
-
expect(doc.kind).toBe("Agent");
|
|
174
|
-
});
|
|
175
|
-
it("round-trips through parseManifest to an equal proto", () => {
|
|
176
|
-
const docs = parseManifest(serializeManifest(agent));
|
|
177
|
-
expect(docs).toHaveLength(1);
|
|
178
|
-
// The round-tripped proto matches the original minus system-managed
|
|
179
|
-
// state (status, metadata.version) — exactly what apply consumes.
|
|
180
|
-
const expected = create(AgentSchema, {
|
|
181
|
-
...agent,
|
|
182
|
-
status: undefined,
|
|
183
|
-
metadata: { ...agent.metadata, version: undefined },
|
|
184
|
-
});
|
|
185
|
-
expect(equals(AgentSchema, docs[0].message, expected)).toBe(true);
|
|
186
|
-
});
|
|
187
|
-
it("round-trips Environment secret values byte-identically", () => {
|
|
188
|
-
const env = create(EnvironmentSchema, {
|
|
189
|
-
metadata: { name: "clinic-patient-db", org: "rakeshreddi098" },
|
|
190
|
-
spec: {
|
|
191
|
-
data: {
|
|
192
|
-
POSTGRES_CONNECTION_URL: {
|
|
193
|
-
value: "***REDACTED***",
|
|
194
|
-
isSecret: true,
|
|
195
|
-
description: "Supabase Postgres connection URL",
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
});
|
|
200
|
-
const docs = parseManifest(serializeManifest(env));
|
|
201
|
-
const roundTripped = docs[0].message;
|
|
202
|
-
expect(roundTripped.spec?.data.POSTGRES_CONNECTION_URL?.value).toBe("***REDACTED***");
|
|
203
|
-
expect(roundTripped.spec?.data.POSTGRES_CONNECTION_URL?.isSecret).toBe(true);
|
|
204
|
-
});
|
|
205
|
-
it("rejects messages of kinds outside the registry", () => {
|
|
206
|
-
// ApiResourceMetadata is a real proto message but not a manifest kind.
|
|
207
|
-
const notAResource = create(ApiResourceMetadataSchema, { name: "x" });
|
|
208
|
-
expect(() => serializeManifest(notAResource)).toThrow(/not.*registry/i);
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
// ---------------------------------------------------------------------------
|
|
212
|
-
// manifestDocumentForResource
|
|
213
|
-
// ---------------------------------------------------------------------------
|
|
214
|
-
describe("manifestDocumentForResource", () => {
|
|
215
|
-
// Shaped like a server-returned schedule: full metadata (including
|
|
216
|
-
// fields the curated ScheduleInput cannot express, like tags) and a
|
|
217
|
-
// populated status — the exact input of a lossless partial edit.
|
|
218
|
-
const schedule = create(ScheduleSchema, {
|
|
219
|
-
apiVersion: "agentic.stigmer.ai/v1",
|
|
220
|
-
kind: "Schedule",
|
|
221
|
-
metadata: {
|
|
222
|
-
id: "sch_01example",
|
|
223
|
-
name: "daily-fee-reminders",
|
|
224
|
-
slug: "daily-fee-reminders",
|
|
225
|
-
org: "isc",
|
|
226
|
-
tags: ["billing"],
|
|
227
|
-
labels: { team: "ops" },
|
|
228
|
-
},
|
|
229
|
-
spec: {
|
|
230
|
-
cron: "0 9 * * *",
|
|
231
|
-
timeZone: "Asia/Kolkata",
|
|
232
|
-
enabled: true,
|
|
233
|
-
target: {
|
|
234
|
-
case: "agent",
|
|
235
|
-
value: {
|
|
236
|
-
agentRef: { kind: ApiResourceKind.agent, org: "isc", slug: "fee-reminder" },
|
|
237
|
-
message: "Send today's fee reminders.",
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
status: { consecutiveFailures: 2, pausedReason: "" },
|
|
242
|
-
});
|
|
243
|
-
it("wraps a fetched proto untouched — the lossless edit contract", () => {
|
|
244
|
-
const flipped = clone(ScheduleSchema, schedule);
|
|
245
|
-
flipped.spec.enabled = false;
|
|
246
|
-
const doc = manifestDocumentForResource(flipped);
|
|
247
|
-
expect(doc.handler.yamlKind).toBe("Schedule");
|
|
248
|
-
expect(doc.name).toBe("daily-fee-reminders");
|
|
249
|
-
expect(doc.slug).toBe("daily-fee-reminders");
|
|
250
|
-
expect(doc.org).toBe("isc");
|
|
251
|
-
// Identity, not a copy: nothing is re-serialized or down-converted,
|
|
252
|
-
// so every field survives (the ScheduleInput path would drop tags).
|
|
253
|
-
expect(doc.message).toBe(flipped);
|
|
254
|
-
const expected = clone(ScheduleSchema, schedule);
|
|
255
|
-
expected.spec.enabled = false;
|
|
256
|
-
expect(equals(ScheduleSchema, doc.message, expected)).toBe(true);
|
|
257
|
-
});
|
|
258
|
-
it("falls back to name when the proto has no slug", () => {
|
|
259
|
-
const bare = create(AgentSchema, { metadata: { name: "x", org: "acme" } });
|
|
260
|
-
const doc = manifestDocumentForResource(bare);
|
|
261
|
-
expect(doc.slug).toBe("x");
|
|
262
|
-
});
|
|
263
|
-
it("rejects messages of kinds outside the registry", () => {
|
|
264
|
-
const notAResource = create(ApiResourceMetadataSchema, { name: "x" });
|
|
265
|
-
expect(() => manifestDocumentForResource(notAResource)).toThrow(/not.*registry/i);
|
|
266
|
-
});
|
|
267
|
-
it("rejects a resource without metadata.name", () => {
|
|
268
|
-
const nameless = create(ScheduleSchema, { metadata: { org: "acme" } });
|
|
269
|
-
expect(() => manifestDocumentForResource(nameless)).toThrow(/metadata\.name/);
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
// ---------------------------------------------------------------------------
|
|
273
|
-
// Registry invariants
|
|
274
|
-
// ---------------------------------------------------------------------------
|
|
275
|
-
describe("manifest registry", () => {
|
|
276
|
-
it("every handler resolves by its own YAML kind", () => {
|
|
277
|
-
for (const handler of manifestKinds()) {
|
|
278
|
-
expect(manifestHandlerForYamlKind(handler.yamlKind)).toBe(handler);
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
it("apply order is strictly increasing (no accidental ties)", () => {
|
|
282
|
-
const orders = manifestKinds().map((h) => h.applyOrder);
|
|
283
|
-
for (let i = 1; i < orders.length; i++) {
|
|
284
|
-
expect(orders[i]).toBeGreaterThan(orders[i - 1]);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
it("covers the kinds the console flows depend on", () => {
|
|
288
|
-
for (const kind of ["Agent", "McpServer", "Workflow", "Environment", "AgentChannel", "ChannelApp"]) {
|
|
289
|
-
expect(manifestHandlerForYamlKind(kind), `missing handler for ${kind}`).toBeDefined();
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
it("declares the updateVisibility binding on exactly the guarded-RPC kinds (oss#573)", () => {
|
|
293
|
-
// Visibility changes go through the updateVisibility RPC only (plain
|
|
294
|
-
// updates preserve stored visibility on both editions). The binding set
|
|
295
|
-
// mirrors the kinds whose proto VisibilityConfig grants non-private
|
|
296
|
-
// levels, minus Skill (push flow, not a manifest kind) — a kind added
|
|
297
|
-
// here without the RPC fails at compile time, one dropped from here
|
|
298
|
-
// silently strands manifest-declared visibility, which this pins.
|
|
299
|
-
const withBinding = manifestKinds()
|
|
300
|
-
.filter((h) => h.updateVisibility !== undefined)
|
|
301
|
-
.map((h) => h.yamlKind)
|
|
302
|
-
.sort();
|
|
303
|
-
expect(withBinding).toEqual(["Agent", "AgentInstance", "Environment", "McpServer", "Workflow"]);
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
//# sourceMappingURL=manifest.test.js.map
|