@stigmer/server 3.23.0 → 3.24.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/dist/authorization/authorizer.d.ts +4 -8
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +5 -9
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/derived-tuples.d.ts.map +1 -1
- package/dist/authorization/derived-tuples.js +10 -25
- package/dist/authorization/derived-tuples.js.map +1 -1
- package/dist/authorization/evaluator.d.ts +7 -8
- package/dist/authorization/evaluator.d.ts.map +1 -1
- package/dist/authorization/evaluator.js +4 -20
- package/dist/authorization/evaluator.js.map +1 -1
- package/dist/authorization/list-read-scope.d.ts.map +1 -1
- package/dist/authorization/list-read-scope.js +5 -9
- package/dist/authorization/list-read-scope.js.map +1 -1
- package/dist/authorization/model/agent.d.ts.map +1 -1
- package/dist/authorization/model/agent.js +4 -5
- package/dist/authorization/model/agent.js.map +1 -1
- package/dist/authorization/model/agent_instance.d.ts.map +1 -1
- package/dist/authorization/model/agent_instance.js +2 -2
- package/dist/authorization/model/agent_instance.js.map +1 -1
- package/dist/authorization/model/mcp_server.d.ts.map +1 -1
- package/dist/authorization/model/mcp_server.js +2 -2
- package/dist/authorization/model/mcp_server.js.map +1 -1
- package/dist/authorization/model/plugin.d.ts.map +1 -1
- package/dist/authorization/model/plugin.js +3 -4
- package/dist/authorization/model/plugin.js.map +1 -1
- package/dist/authorization/model/rewrite.d.ts +8 -10
- package/dist/authorization/model/rewrite.d.ts.map +1 -1
- package/dist/authorization/model/rewrite.js +0 -3
- package/dist/authorization/model/rewrite.js.map +1 -1
- package/dist/authorization/model/skill.d.ts.map +1 -1
- package/dist/authorization/model/skill.js +2 -2
- package/dist/authorization/model/skill.js.map +1 -1
- package/dist/authorization/model/workflow.d.ts.map +1 -1
- package/dist/authorization/model/workflow.js +2 -2
- package/dist/authorization/model/workflow.js.map +1 -1
- package/dist/authorization/model/workflow_instance.d.ts.map +1 -1
- package/dist/authorization/model/workflow_instance.js +2 -2
- package/dist/authorization/model/workflow_instance.js.map +1 -1
- package/dist/authorization/organization-directory.d.ts.map +1 -1
- package/dist/authorization/organization-directory.js +2 -3
- package/dist/authorization/organization-directory.js.map +1 -1
- package/dist/authorization/store-test-kit.d.ts +0 -6
- package/dist/authorization/store-test-kit.d.ts.map +1 -1
- package/dist/authorization/store-test-kit.js +16 -62
- package/dist/authorization/store-test-kit.js.map +1 -1
- package/dist/authorization/tuples.d.ts +13 -32
- package/dist/authorization/tuples.d.ts.map +1 -1
- package/dist/authorization/tuples.js +3 -11
- package/dist/authorization/tuples.js.map +1 -1
- package/dist/domain/agent/controller.d.ts.map +1 -1
- package/dist/domain/agent/controller.js +4 -4
- package/dist/domain/agent/controller.js.map +1 -1
- package/dist/domain/agentchannel/controller.d.ts.map +1 -1
- package/dist/domain/agentchannel/controller.js +3 -1
- package/dist/domain/agentchannel/controller.js.map +1 -1
- package/dist/domain/agentexecution/controller.d.ts.map +1 -1
- package/dist/domain/agentexecution/controller.js +3 -1
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentinstance/controller.d.ts.map +1 -1
- package/dist/domain/agentinstance/controller.js +3 -4
- package/dist/domain/agentinstance/controller.js.map +1 -1
- package/dist/domain/agentshare/constants.d.ts +6 -11
- package/dist/domain/agentshare/constants.d.ts.map +1 -1
- package/dist/domain/agentshare/constants.js +8 -16
- package/dist/domain/agentshare/constants.js.map +1 -1
- package/dist/domain/agentshare/controller.d.ts.map +1 -1
- package/dist/domain/agentshare/controller.js +3 -1
- package/dist/domain/agentshare/controller.js.map +1 -1
- package/dist/domain/agentshare/steps.d.ts +18 -25
- package/dist/domain/agentshare/steps.d.ts.map +1 -1
- package/dist/domain/agentshare/steps.js +41 -142
- package/dist/domain/agentshare/steps.js.map +1 -1
- package/dist/domain/environment/controller.d.ts.map +1 -1
- package/dist/domain/environment/controller.js +2 -3
- package/dist/domain/environment/controller.js.map +1 -1
- package/dist/domain/executioncontext/controller.d.ts.map +1 -1
- package/dist/domain/executioncontext/controller.js +2 -1
- package/dist/domain/executioncontext/controller.js.map +1 -1
- package/dist/domain/mcpserver/controller.d.ts.map +1 -1
- package/dist/domain/mcpserver/controller.js +3 -4
- package/dist/domain/mcpserver/controller.js.map +1 -1
- package/dist/domain/plugin/controller.d.ts.map +1 -1
- package/dist/domain/plugin/controller.js +1 -3
- package/dist/domain/plugin/controller.js.map +1 -1
- package/dist/domain/plugin/push.d.ts +7 -5
- package/dist/domain/plugin/push.d.ts.map +1 -1
- package/dist/domain/plugin/push.js +8 -14
- package/dist/domain/plugin/push.js.map +1 -1
- package/dist/domain/schedule/controller.d.ts.map +1 -1
- package/dist/domain/schedule/controller.js +3 -1
- package/dist/domain/schedule/controller.js.map +1 -1
- package/dist/domain/session/controller.d.ts.map +1 -1
- package/dist/domain/session/controller.js +3 -2
- package/dist/domain/session/controller.js.map +1 -1
- package/dist/domain/skill/controller.d.ts.map +1 -1
- package/dist/domain/skill/controller.js +0 -2
- package/dist/domain/skill/controller.js.map +1 -1
- package/dist/domain/workflow/agent-call-references.d.ts +81 -0
- package/dist/domain/workflow/agent-call-references.d.ts.map +1 -0
- package/dist/domain/workflow/agent-call-references.js +117 -0
- package/dist/domain/workflow/agent-call-references.js.map +1 -0
- package/dist/domain/workflow/controller.d.ts.map +1 -1
- package/dist/domain/workflow/controller.js +14 -6
- package/dist/domain/workflow/controller.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +3 -3
- package/dist/domain/workflow/validation/task-config-constraints.d.ts +10 -1
- package/dist/domain/workflow/validation/task-config-constraints.d.ts.map +1 -1
- package/dist/domain/workflow/validation/task-config-constraints.js +3 -2
- package/dist/domain/workflow/validation/task-config-constraints.js.map +1 -1
- package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
- package/dist/domain/workflowexecution/controller.js +4 -2
- package/dist/domain/workflowexecution/controller.js.map +1 -1
- package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
- package/dist/domain/workflowinstance/controller.js +3 -4
- package/dist/domain/workflowinstance/controller.js.map +1 -1
- package/dist/extensions/authorization-queries.d.ts +6 -5
- package/dist/extensions/authorization-queries.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.d.ts +1 -1
- package/dist/extensions/resource-authorization.d.ts +3 -2
- package/dist/extensions/resource-authorization.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline/apiresource-labels.d.ts +10 -9
- package/dist/pipeline/apiresource-labels.d.ts.map +1 -1
- package/dist/pipeline/apiresource-labels.js +10 -9
- package/dist/pipeline/apiresource-labels.js.map +1 -1
- package/dist/pipeline/apiresource-meta.d.ts +12 -3
- package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
- package/dist/pipeline/apiresource-meta.js +21 -10
- package/dist/pipeline/apiresource-meta.js.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.d.ts +9 -3
- package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.js +9 -11
- package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
- package/dist/pipeline/steps/references.d.ts +204 -20
- package/dist/pipeline/steps/references.d.ts.map +1 -1
- package/dist/pipeline/steps/references.js +356 -43
- package/dist/pipeline/steps/references.js.map +1 -1
- package/dist/query/search/controller.js +0 -1
- package/dist/query/search/controller.js.map +1 -1
- package/dist/query/search/criteria.d.ts +1 -5
- package/dist/query/search/criteria.d.ts.map +1 -1
- package/dist/query/search/criteria.js +3 -13
- package/dist/query/search/criteria.js.map +1 -1
- package/dist/query/search/handler.d.ts +5 -4
- package/dist/query/search/handler.d.ts.map +1 -1
- package/dist/query/search/handler.js +7 -6
- package/dist/query/search/handler.js.map +1 -1
- package/dist/query/search/query-store.d.ts.map +1 -1
- package/dist/query/search/query-store.js +0 -2
- package/dist/query/search/query-store.js.map +1 -1
- package/dist/store/interface.d.ts +3 -6
- package/dist/store/interface.d.ts.map +1 -1
- package/dist/store/interface.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +3 -1
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +35 -1
- package/dist/store/postgres/migrations.js.map +1 -1
- package/dist/store/postgres/store.d.ts.map +1 -1
- package/dist/store/postgres/store.js +4 -9
- package/dist/store/postgres/store.js.map +1 -1
- package/dist/store/public-visibility-retired.d.ts +67 -0
- package/dist/store/public-visibility-retired.d.ts.map +1 -0
- package/dist/store/public-visibility-retired.js +55 -0
- package/dist/store/public-visibility-retired.js.map +1 -0
- package/dist/store/sqlite/migrations.d.ts +3 -1
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +36 -1
- package/dist/store/sqlite/migrations.js.map +1 -1
- package/dist/store/sqlite/store.d.ts.map +1 -1
- package/dist/store/sqlite/store.js +4 -8
- package/dist/store/sqlite/store.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/README.md +24 -26
- package/src/authorization/__tests__/authorizer.test.ts +10 -9
- package/src/authorization/__tests__/derived-tuples.test.ts +4 -11
- package/src/authorization/__tests__/evaluator.test.ts +14 -73
- package/src/authorization/__tests__/facts.test.ts +2 -2
- package/src/authorization/__tests__/fixtures/fga/agent-instance-creation.fga.yaml +19 -27
- package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +6 -98
- package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +4 -61
- package/src/authorization/__tests__/fixtures/fga/mcp-server-authoring.fga.yaml +1 -15
- package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +1 -21
- package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +1 -25
- package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +1 -3
- package/src/authorization/__tests__/list-read-scope.test.ts +18 -17
- package/src/authorization/__tests__/store-tests.test.ts +2 -6
- package/src/authorization/__tests__/tuples.test.ts +12 -11
- package/src/authorization/authorizer.ts +4 -9
- package/src/authorization/derived-tuples.ts +14 -31
- package/src/authorization/evaluator.ts +8 -44
- package/src/authorization/list-read-scope.ts +5 -11
- package/src/authorization/model/agent.ts +2 -5
- package/src/authorization/model/agent_instance.ts +0 -2
- package/src/authorization/model/mcp_server.ts +0 -2
- package/src/authorization/model/plugin.ts +1 -4
- package/src/authorization/model/rewrite.ts +8 -13
- package/src/authorization/model/skill.ts +0 -2
- package/src/authorization/model/workflow.ts +0 -2
- package/src/authorization/model/workflow_instance.ts +0 -2
- package/src/authorization/organization-directory.ts +1 -3
- package/src/authorization/store-test-kit.ts +16 -75
- package/src/authorization/tuples.ts +16 -39
- package/src/domain/agent/__tests__/agent.test.ts +11 -4
- package/src/domain/agent/controller.ts +7 -7
- package/src/domain/agentchannel/__tests__/agentchannel.test.ts +223 -48
- package/src/domain/agentchannel/controller.ts +6 -1
- package/src/domain/agentexecution/controller.ts +6 -1
- package/src/domain/agentinstance/controller.ts +6 -12
- package/src/domain/agentshare/__tests__/agentshare.test.ts +196 -172
- package/src/domain/agentshare/__tests__/create-authorization.test.ts +16 -31
- package/src/domain/agentshare/constants.ts +14 -26
- package/src/domain/agentshare/controller.ts +6 -1
- package/src/domain/agentshare/steps.ts +41 -194
- package/src/domain/environment/controller.ts +5 -8
- package/src/domain/executioncontext/controller.ts +5 -1
- package/src/domain/mcpserver/__tests__/mcpserver.test.ts +115 -28
- package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +53 -18
- package/src/domain/mcpserver/controller.ts +6 -12
- package/src/domain/plugin/controller.ts +1 -8
- package/src/domain/plugin/push.ts +8 -16
- package/src/domain/schedule/controller.ts +6 -1
- package/src/domain/session/controller.ts +12 -4
- package/src/domain/skill/controller.ts +0 -7
- package/src/domain/workflow/__tests__/agent-call-references.test.ts +373 -0
- package/src/domain/workflow/agent-call-references.ts +204 -0
- package/src/domain/workflow/controller.ts +28 -10
- package/src/domain/workflow/registry/data/task-kind-registry.json +3 -3
- package/src/domain/workflow/validation/task-config-constraints.ts +7 -3
- package/src/domain/workflowexecution/controller.ts +7 -2
- package/src/domain/workflowinstance/controller.ts +6 -12
- package/src/extensions/__tests__/built-in-authorization-composed.test.ts +32 -19
- package/src/extensions/__tests__/extension-composition.test.ts +4 -4
- package/src/extensions/__tests__/list-read-scope-composed.test.ts +9 -6
- package/src/extensions/authorization-queries.ts +6 -5
- package/src/extensions/list-read-scope.ts +1 -1
- package/src/extensions/resource-authorization.ts +3 -5
- package/src/index.ts +0 -1
- package/src/pipeline/__tests__/supports-visibility.test.ts +112 -0
- package/src/pipeline/apiresource-labels.ts +10 -9
- package/src/pipeline/apiresource-meta.ts +21 -10
- package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +18 -31
- package/src/pipeline/steps/__tests__/references.test.ts +737 -0
- package/src/pipeline/steps/authorization-tuples.ts +9 -11
- package/src/pipeline/steps/references.ts +622 -70
- package/src/query/search/__tests__/criteria.test.ts +0 -4
- package/src/query/search/__tests__/query-store.test.ts +11 -40
- package/src/query/search/controller.ts +0 -1
- package/src/query/search/criteria.ts +0 -14
- package/src/query/search/handler.ts +6 -7
- package/src/query/search/query-store.ts +0 -2
- package/src/store/__tests__/public-visibility-retired.test.ts +127 -0
- package/src/store/__tests__/store-contract.ts +6 -51
- package/src/store/interface.ts +3 -6
- package/src/store/postgres/__tests__/migrations.test.ts +187 -6
- package/src/store/postgres/__tests__/store-contract.test.ts +0 -2
- package/src/store/postgres/migrations.ts +48 -1
- package/src/store/postgres/store.ts +4 -11
- package/src/store/public-visibility-retired.ts +119 -0
- package/src/store/sqlite/__tests__/migrations.test.ts +191 -5
- package/src/store/sqlite/migrations.ts +45 -1
- package/src/store/sqlite/store.ts +4 -10
- package/dist/pipeline/steps/visibility-gates.d.ts +0 -27
- package/dist/pipeline/steps/visibility-gates.d.ts.map +0 -1
- package/dist/pipeline/steps/visibility-gates.js +0 -139
- package/dist/pipeline/steps/visibility-gates.js.map +0 -1
- package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +0 -98
- package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +0 -52
- package/src/pipeline/steps/__tests__/visibility-gates.test.ts +0 -187
- package/src/pipeline/steps/visibility-gates.ts +0 -174
|
@@ -33,8 +33,10 @@ import { AgentCommandController } from "@stigmer/protos/ai/stigmer/agentic/agent
|
|
|
33
33
|
import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
34
34
|
import { AgentShareCommandController } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/command_pb";
|
|
35
35
|
import { AgentShareQueryController } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/query_pb";
|
|
36
|
+
import { AgentShareSchema } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/api_pb";
|
|
36
37
|
import type { AgentShare } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/api_pb";
|
|
37
38
|
import { AgentShareAudience } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/spec_pb";
|
|
39
|
+
import { EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
38
40
|
import { SkillSchema } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
|
|
39
41
|
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
40
42
|
import { ApiResourceReferenceSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
|
|
@@ -47,11 +49,15 @@ import { createLogger } from "../../../boot/logger.js";
|
|
|
47
49
|
import type { Store } from "../../../store/interface.js";
|
|
48
50
|
import {
|
|
49
51
|
ORG_REQUIRED_FOR_LOOKUP_MESSAGE,
|
|
50
|
-
|
|
52
|
+
sameOrgInvariantMessage,
|
|
51
53
|
} from "../constants.js";
|
|
52
54
|
import { findShareByOrgAndSlug, sharingLinkTokenAllowed } from "../steps.js";
|
|
53
55
|
|
|
54
|
-
const silentLogger = createLogger({
|
|
56
|
+
const silentLogger = createLogger({
|
|
57
|
+
level: "error",
|
|
58
|
+
pretty: false,
|
|
59
|
+
write: () => {},
|
|
60
|
+
});
|
|
55
61
|
|
|
56
62
|
const API_VERSION = "agentic.stigmer.ai/v1";
|
|
57
63
|
|
|
@@ -68,7 +74,10 @@ let dir: string;
|
|
|
68
74
|
beforeAll(async () => {
|
|
69
75
|
dir = mkdtempSync(path.join(tmpdir(), "agentshare-domain-test-"));
|
|
70
76
|
vi.stubEnv("STIGMER_ENCRYPTION_KEY", Buffer.alloc(32, 7).toString("base64"));
|
|
71
|
-
vi.stubEnv(
|
|
77
|
+
vi.stubEnv(
|
|
78
|
+
"STIGMER_RUNNER_TOKEN_KEY",
|
|
79
|
+
Buffer.alloc(32, 8).toString("base64"),
|
|
80
|
+
);
|
|
72
81
|
server = await composeServer({
|
|
73
82
|
config: loadConfig({
|
|
74
83
|
STIGMER_MODEL_REGISTRY_REFRESH: "off",
|
|
@@ -118,13 +127,6 @@ async function createTestAgent(name: string, org: string): Promise<Agent> {
|
|
|
118
127
|
}
|
|
119
128
|
|
|
120
129
|
/** Flips the agent marketplace-public through the real pipeline (D1). */
|
|
121
|
-
async function makeAgentPublic(agent: Agent): Promise<void> {
|
|
122
|
-
await agents.updateVisibility({
|
|
123
|
-
resourceId: agent.metadata!.id,
|
|
124
|
-
visibility: ApiResourceVisibility.visibility_public,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
130
|
/**
|
|
129
131
|
* Writes a skill fixture directly to the store — the established
|
|
130
132
|
* cross-domain fixture pattern (the skill domain is not ported yet, and
|
|
@@ -142,7 +144,12 @@ async function saveSkill(
|
|
|
142
144
|
kind: "Skill",
|
|
143
145
|
metadata: { id, name: slug, slug, org, visibility },
|
|
144
146
|
});
|
|
145
|
-
await server.store.saveResource(
|
|
147
|
+
await server.store.saveResource(
|
|
148
|
+
ApiResourceKind.skill,
|
|
149
|
+
id,
|
|
150
|
+
SkillSchema,
|
|
151
|
+
skill,
|
|
152
|
+
);
|
|
146
153
|
}
|
|
147
154
|
|
|
148
155
|
/** Minimal canonical share: no slug, no name — both default from the agent. */
|
|
@@ -178,7 +185,10 @@ describe("agentshare create", () => {
|
|
|
178
185
|
const ORG = "create-test-org";
|
|
179
186
|
|
|
180
187
|
it("canonical share defaults slug and name from the agent; ash_ id; ref normalized", async () => {
|
|
181
|
-
const agent = await createTestAgent(
|
|
188
|
+
const agent = await createTestAgent(
|
|
189
|
+
uniqueName("Canonical Default Agent"),
|
|
190
|
+
ORG,
|
|
191
|
+
);
|
|
182
192
|
const share = await shares.create(shareFor(agent, true));
|
|
183
193
|
|
|
184
194
|
expect(share.metadata?.slug).toBe(agent.metadata!.slug);
|
|
@@ -202,13 +212,20 @@ describe("agentshare create", () => {
|
|
|
202
212
|
expect(err.rawMessage).toBe("Agent not found: no-such-agent");
|
|
203
213
|
});
|
|
204
214
|
|
|
205
|
-
it("
|
|
206
|
-
const agent = await createTestAgent(
|
|
215
|
+
it("an agent_ref naming another organization is FAILED_PRECONDITION with the same-organization copy, before any lookup", async () => {
|
|
216
|
+
const agent = await createTestAgent(
|
|
217
|
+
uniqueName("Cross Org Ghost Agent"),
|
|
218
|
+
ORG,
|
|
219
|
+
);
|
|
207
220
|
const share = shareFor(agent, true);
|
|
208
|
-
share.spec.agentRef = {
|
|
221
|
+
share.spec.agentRef = {
|
|
222
|
+
...share.spec.agentRef,
|
|
223
|
+
org: "some-other-org",
|
|
224
|
+
} as never;
|
|
209
225
|
|
|
210
226
|
const err = await grpcError(() => shares.create(share));
|
|
211
|
-
expect(err.code).toBe(Code.
|
|
227
|
+
expect(err.code).toBe(Code.FailedPrecondition);
|
|
228
|
+
expect(err.rawMessage).toBe(sameOrgInvariantMessage("some-other-org"));
|
|
212
229
|
});
|
|
213
230
|
|
|
214
231
|
it("stamps the agent-id pin on the created share", async () => {
|
|
@@ -236,7 +253,10 @@ describe("agentshare create", () => {
|
|
|
236
253
|
});
|
|
237
254
|
|
|
238
255
|
it("second canonical share for the same agent is ALREADY_EXISTS", async () => {
|
|
239
|
-
const agent = await createTestAgent(
|
|
256
|
+
const agent = await createTestAgent(
|
|
257
|
+
uniqueName("Duplicate Share Agent"),
|
|
258
|
+
ORG,
|
|
259
|
+
);
|
|
240
260
|
await shares.create(shareFor(agent, true));
|
|
241
261
|
|
|
242
262
|
const err = await grpcError(() => shares.create(shareFor(agent, true)));
|
|
@@ -248,7 +268,8 @@ describe("agentshare create", () => {
|
|
|
248
268
|
await shares.create(shareFor(agent, true));
|
|
249
269
|
|
|
250
270
|
const named = shareFor(agent, true);
|
|
251
|
-
(named.metadata as Record<string, string>).name =
|
|
271
|
+
(named.metadata as Record<string, string>).name =
|
|
272
|
+
uniqueName("Docs Site Channel");
|
|
252
273
|
const second = await shares.create(named);
|
|
253
274
|
expect(second.metadata?.slug).not.toBe(agent.metadata!.slug);
|
|
254
275
|
});
|
|
@@ -264,7 +285,10 @@ describe("launch-gate config", () => {
|
|
|
264
285
|
const ORG = "launchgate-test-org";
|
|
265
286
|
|
|
266
287
|
it("allowed_origins and messages persist and round-trip", async () => {
|
|
267
|
-
const agent = await createTestAgent(
|
|
288
|
+
const agent = await createTestAgent(
|
|
289
|
+
uniqueName("Launch Gate Config Agent"),
|
|
290
|
+
ORG,
|
|
291
|
+
);
|
|
268
292
|
const created = await shares.create({
|
|
269
293
|
...shareFor(agent, true),
|
|
270
294
|
spec: {
|
|
@@ -289,7 +313,10 @@ describe("launch-gate config", () => {
|
|
|
289
313
|
});
|
|
290
314
|
|
|
291
315
|
it("malformed origins are INVALID_ARGUMENT", async () => {
|
|
292
|
-
const agent = await createTestAgent(
|
|
316
|
+
const agent = await createTestAgent(
|
|
317
|
+
uniqueName("Origin Validation Agent"),
|
|
318
|
+
ORG,
|
|
319
|
+
);
|
|
293
320
|
for (const origin of [
|
|
294
321
|
"docs.example.com", // missing scheme
|
|
295
322
|
"https://example.com/path", // path not allowed
|
|
@@ -308,7 +335,10 @@ describe("launch-gate config", () => {
|
|
|
308
335
|
});
|
|
309
336
|
|
|
310
337
|
it("overlong custom message is INVALID_ARGUMENT", async () => {
|
|
311
|
-
const agent = await createTestAgent(
|
|
338
|
+
const agent = await createTestAgent(
|
|
339
|
+
uniqueName("Message Length Agent"),
|
|
340
|
+
ORG,
|
|
341
|
+
);
|
|
312
342
|
const err = await grpcError(() =>
|
|
313
343
|
shares.create({
|
|
314
344
|
...shareFor(agent, true),
|
|
@@ -322,7 +352,27 @@ describe("launch-gate config", () => {
|
|
|
322
352
|
});
|
|
323
353
|
|
|
324
354
|
it("environment_refs on an org-audience share is INVALID_ARGUMENT; public persists", async () => {
|
|
325
|
-
const agent = await createTestAgent(
|
|
355
|
+
const agent = await createTestAgent(
|
|
356
|
+
uniqueName("Env Refs Audience Agent"),
|
|
357
|
+
ORG,
|
|
358
|
+
);
|
|
359
|
+
// The environment must exist when the share is written (the reference rule).
|
|
360
|
+
await server.store.saveResource(
|
|
361
|
+
ApiResourceKind.environment,
|
|
362
|
+
"env_shared_credentials",
|
|
363
|
+
EnvironmentSchema,
|
|
364
|
+
create(EnvironmentSchema, {
|
|
365
|
+
apiVersion: "agentic.stigmer.ai/v1",
|
|
366
|
+
kind: "Environment",
|
|
367
|
+
metadata: {
|
|
368
|
+
id: "env_shared_credentials",
|
|
369
|
+
name: "shared-credentials",
|
|
370
|
+
slug: "shared-credentials",
|
|
371
|
+
org: ORG,
|
|
372
|
+
visibility: ApiResourceVisibility.visibility_org,
|
|
373
|
+
},
|
|
374
|
+
}),
|
|
375
|
+
);
|
|
326
376
|
const envRef = {
|
|
327
377
|
kind: ApiResourceKind.environment,
|
|
328
378
|
org: ORG,
|
|
@@ -378,8 +428,14 @@ describe("agentshare update", () => {
|
|
|
378
428
|
});
|
|
379
429
|
|
|
380
430
|
it("agent_ref is immutable — FAILED_PRECONDITION with the pinned copy", async () => {
|
|
381
|
-
const agentA = await createTestAgent(
|
|
382
|
-
|
|
431
|
+
const agentA = await createTestAgent(
|
|
432
|
+
uniqueName("Immutable Ref Agent A"),
|
|
433
|
+
ORG,
|
|
434
|
+
);
|
|
435
|
+
const agentB = await createTestAgent(
|
|
436
|
+
uniqueName("Immutable Ref Agent B"),
|
|
437
|
+
ORG,
|
|
438
|
+
);
|
|
383
439
|
const created = await shares.create(shareFor(agentA, true));
|
|
384
440
|
|
|
385
441
|
created.spec!.agentRef = create(ApiResourceReferenceSchema, {
|
|
@@ -397,146 +453,83 @@ describe("agentshare update", () => {
|
|
|
397
453
|
// Cross-org contract (Go TestAgentShareController_CrossOrg, decision 013).
|
|
398
454
|
// ---------------------------------------------------------------------------
|
|
399
455
|
|
|
400
|
-
describe("
|
|
456
|
+
describe("the same-organization invariant", () => {
|
|
401
457
|
const PROVIDER = "provider-org";
|
|
402
458
|
const CONSUMER = "consumer-org";
|
|
403
459
|
|
|
404
|
-
function
|
|
460
|
+
function shareInAnotherOrg(agent: Agent, enabled: boolean) {
|
|
405
461
|
const share = shareFor(agent, enabled);
|
|
406
462
|
share.metadata.org = CONSUMER;
|
|
407
|
-
share.spec.agentRef = {
|
|
463
|
+
share.spec.agentRef = {
|
|
464
|
+
...share.spec.agentRef,
|
|
465
|
+
org: agent.metadata!.org,
|
|
466
|
+
} as never;
|
|
408
467
|
return share;
|
|
409
468
|
}
|
|
410
469
|
|
|
411
|
-
it("
|
|
412
|
-
const
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
expect(
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
it("non-public agent is NOT_FOUND, indistinguishable from absence", async () => {
|
|
430
|
-
const agent = await createTestAgent(uniqueName("Private Provider Agent"), PROVIDER);
|
|
431
|
-
|
|
432
|
-
const err = await grpcError(() => shares.create(crossOrgShare(agent, true)));
|
|
433
|
-
expect(err.code).toBe(Code.NotFound);
|
|
434
|
-
|
|
435
|
-
// The refusal must match a genuinely missing agent — no existence
|
|
436
|
-
// probe for private slugs (the T09 indistinguishability contract).
|
|
437
|
-
const ghost = crossOrgShare(agent, true);
|
|
438
|
-
ghost.spec.agentRef = { ...ghost.spec.agentRef, org: "empty-provider-org" } as never;
|
|
470
|
+
it("another organization's agent cannot be shared — the same sentence whether the agent exists or not, at any level", async () => {
|
|
471
|
+
const existing = await createTestAgent(
|
|
472
|
+
uniqueName("Provider Agent"),
|
|
473
|
+
PROVIDER,
|
|
474
|
+
);
|
|
475
|
+
const err = await grpcError(() =>
|
|
476
|
+
shares.create(shareInAnotherOrg(existing, true)),
|
|
477
|
+
);
|
|
478
|
+
expect(err.code).toBe(Code.FailedPrecondition);
|
|
479
|
+
expect(err.rawMessage).toBe(sameOrgInvariantMessage(PROVIDER));
|
|
480
|
+
|
|
481
|
+
const ghost = shareFor(existing, true);
|
|
482
|
+
ghost.metadata.org = CONSUMER;
|
|
483
|
+
ghost.spec.agentRef = {
|
|
484
|
+
...ghost.spec.agentRef,
|
|
485
|
+
org: PROVIDER,
|
|
486
|
+
slug: "no-such-agent",
|
|
487
|
+
} as never;
|
|
439
488
|
const ghostErr = await grpcError(() => shares.create(ghost));
|
|
440
|
-
expect(
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
it("org audience is refused cross-org, on create and on update", async () => {
|
|
444
|
-
const agent = await createTestAgent(uniqueName("Audience Rule Agent"), PROVIDER);
|
|
445
|
-
await makeAgentPublic(agent);
|
|
446
|
-
|
|
447
|
-
const orgAudience = crossOrgShare(agent, true);
|
|
448
|
-
(orgAudience.spec as Record<string, unknown>).audience = AgentShareAudience.org;
|
|
449
|
-
const createErr = await grpcError(() => shares.create(orgAudience));
|
|
450
|
-
expect(createErr.code).toBe(Code.FailedPrecondition);
|
|
451
|
-
expect(createErr.rawMessage).toBe(crossOrgAudienceMessage(PROVIDER));
|
|
452
|
-
|
|
453
|
-
const created = await shares.create(crossOrgShare(agent, true));
|
|
454
|
-
created.spec!.audience = AgentShareAudience.org;
|
|
455
|
-
const updateErr = await grpcError(() => shares.update(created));
|
|
456
|
-
expect(updateErr.code).toBe(Code.FailedPrecondition);
|
|
457
|
-
expect(updateErr.rawMessage).toBe(crossOrgAudienceMessage(PROVIDER));
|
|
489
|
+
expect(ghostErr.code).toBe(Code.FailedPrecondition);
|
|
490
|
+
expect(ghostErr.rawMessage).toBe(sameOrgInvariantMessage(PROVIDER));
|
|
458
491
|
});
|
|
459
492
|
|
|
460
|
-
it("
|
|
461
|
-
await
|
|
462
|
-
"
|
|
463
|
-
PROVIDER,
|
|
464
|
-
"private-skill",
|
|
465
|
-
ApiResourceVisibility.visibility_private,
|
|
466
|
-
);
|
|
467
|
-
await saveSkill(
|
|
468
|
-
"skl_public_dep",
|
|
493
|
+
it("a stored share whose agent is in another organization fails the profile closed, like a dangling reference", async () => {
|
|
494
|
+
const agent = await createTestAgent(
|
|
495
|
+
uniqueName("Legacy Provider Agent"),
|
|
469
496
|
PROVIDER,
|
|
470
|
-
"public-skill",
|
|
471
|
-
ApiResourceVisibility.visibility_public,
|
|
472
497
|
);
|
|
473
|
-
|
|
474
|
-
const
|
|
498
|
+
// A row from before the invariant, written straight to the store.
|
|
499
|
+
const legacy = create(AgentShareSchema, {
|
|
475
500
|
apiVersion: API_VERSION,
|
|
476
|
-
kind: "
|
|
477
|
-
metadata: {
|
|
501
|
+
kind: "AgentShare",
|
|
502
|
+
metadata: {
|
|
503
|
+
id: "ash_legacy_cross_org",
|
|
504
|
+
name: "legacy-cross-org",
|
|
505
|
+
slug: "legacy-cross-org",
|
|
506
|
+
org: CONSUMER,
|
|
507
|
+
},
|
|
478
508
|
spec: {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
509
|
+
agentRef: {
|
|
510
|
+
kind: ApiResourceKind.agent,
|
|
511
|
+
org: PROVIDER,
|
|
512
|
+
slug: agent.metadata!.slug,
|
|
513
|
+
},
|
|
514
|
+
enabled: true,
|
|
515
|
+
audience: AgentShareAudience.public,
|
|
484
516
|
},
|
|
517
|
+
status: { agentId: agent.metadata!.id },
|
|
485
518
|
});
|
|
486
|
-
await
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
// Same-org sharing of the same agent stays unaffected — the sweep is
|
|
494
|
-
// a cross-org rule only.
|
|
495
|
-
await shares.create(shareFor(agent, true));
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
it("visibility flip fails the profile closed", async () => {
|
|
499
|
-
const agent = await createTestAgent(uniqueName("Revocable Agent"), PROVIDER);
|
|
500
|
-
await makeAgentPublic(agent);
|
|
501
|
-
const created = await shares.create(crossOrgShare(agent, true));
|
|
502
|
-
|
|
503
|
-
const ref = { org: CONSUMER, slug: created.metadata!.slug };
|
|
504
|
-
await query.getSharedProfile(ref);
|
|
505
|
-
|
|
506
|
-
await agents.updateVisibility({
|
|
507
|
-
resourceId: agent.metadata!.id,
|
|
508
|
-
visibility: ApiResourceVisibility.visibility_private,
|
|
509
|
-
});
|
|
519
|
+
await server.store.saveResource(
|
|
520
|
+
ApiResourceKind.agent_share,
|
|
521
|
+
legacy.metadata!.id,
|
|
522
|
+
AgentShareSchema,
|
|
523
|
+
legacy,
|
|
524
|
+
);
|
|
510
525
|
|
|
511
|
-
const err = await grpcError(() =>
|
|
526
|
+
const err = await grpcError(() =>
|
|
527
|
+
query.getSharedProfile({ org: CONSUMER, slug: "legacy-cross-org" }),
|
|
528
|
+
);
|
|
512
529
|
expect(err.code).toBe(Code.NotFound);
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
const name = uniqueName("Ephemeral Provider Agent");
|
|
517
|
-
const agent = await createTestAgent(name, PROVIDER);
|
|
518
|
-
await makeAgentPublic(agent);
|
|
519
|
-
const created = await shares.create(crossOrgShare(agent, true));
|
|
520
|
-
const ref = { org: CONSUMER, slug: created.metadata!.slug };
|
|
521
|
-
|
|
522
|
-
await agents.delete({ value: agent.metadata!.id });
|
|
523
|
-
|
|
524
|
-
// The consumer org's share survives the provider's delete (cross-org
|
|
525
|
-
// shares are NOT cascaded — not the provider's resource to destroy)
|
|
526
|
-
// but fails closed.
|
|
527
|
-
const survived = await query.get({ value: created.metadata!.id });
|
|
528
|
-
expect(survived.status?.agentId).toBe(agent.metadata!.id);
|
|
529
|
-
const danglingErr = await grpcError(() => query.getSharedProfile(ref));
|
|
530
|
-
expect(danglingErr.code).toBe(Code.NotFound);
|
|
531
|
-
|
|
532
|
-
// A DIFFERENT public agent later claims the same org/slug: the pin
|
|
533
|
-
// must keep the old share dark.
|
|
534
|
-
const recreated = await createTestAgent(name, PROVIDER);
|
|
535
|
-
await makeAgentPublic(recreated);
|
|
536
|
-
expect(recreated.metadata!.slug).toBe(agent.metadata!.slug);
|
|
537
|
-
|
|
538
|
-
const rebindErr = await grpcError(() => query.getSharedProfile(ref));
|
|
539
|
-
expect(rebindErr.code).toBe(Code.NotFound);
|
|
530
|
+
// The row itself is still readable by id — nothing is deleted.
|
|
531
|
+
const row = await query.get({ value: legacy.metadata!.id });
|
|
532
|
+
expect(row.status?.agentId).toBe(agent.metadata!.id);
|
|
540
533
|
});
|
|
541
534
|
});
|
|
542
535
|
|
|
@@ -548,13 +541,18 @@ describe("getSharedProfile (anonymous lane)", () => {
|
|
|
548
541
|
const ORG = "profile-test-org";
|
|
549
542
|
|
|
550
543
|
it("uniform NotFound across no-share / disabled / deleted; enabled resolves trimmed", async () => {
|
|
551
|
-
const agent = await createTestAgent(
|
|
544
|
+
const agent = await createTestAgent(
|
|
545
|
+
uniqueName("Shared Profile Agent"),
|
|
546
|
+
ORG,
|
|
547
|
+
);
|
|
552
548
|
const ref = { org: ORG, slug: agent.metadata!.slug };
|
|
553
549
|
|
|
554
550
|
// No share yet.
|
|
555
551
|
const noShareErr = await grpcError(() => query.getSharedProfile(ref));
|
|
556
552
|
expect(noShareErr.code).toBe(Code.NotFound);
|
|
557
|
-
expect(noShareErr.rawMessage).toBe(
|
|
553
|
+
expect(noShareErr.rawMessage).toBe(
|
|
554
|
+
`Agent not found: ${agent.metadata!.slug}`,
|
|
555
|
+
);
|
|
558
556
|
|
|
559
557
|
// Enabled share resolves to the trimmed profile — display fields from
|
|
560
558
|
// the AGENT, URL identity from the SHARE, never the full Agent.
|
|
@@ -609,7 +607,10 @@ describe("audience and the member resolution lane", () => {
|
|
|
609
607
|
const ORG = "audience-test-org";
|
|
610
608
|
|
|
611
609
|
it("audience persists and round-trips", async () => {
|
|
612
|
-
const agent = await createTestAgent(
|
|
610
|
+
const agent = await createTestAgent(
|
|
611
|
+
uniqueName("Audience Round Trip Agent"),
|
|
612
|
+
ORG,
|
|
613
|
+
);
|
|
613
614
|
const created = await shares.create({
|
|
614
615
|
...shareFor(agent, true),
|
|
615
616
|
spec: { ...shareFor(agent, true).spec, audience: AgentShareAudience.org },
|
|
@@ -621,10 +622,15 @@ describe("audience and the member resolution lane", () => {
|
|
|
621
622
|
});
|
|
622
623
|
|
|
623
624
|
it("member path resolves shares in either audience (OSS: membership always holds)", async () => {
|
|
624
|
-
const agent = await createTestAgent(
|
|
625
|
+
const agent = await createTestAgent(
|
|
626
|
+
uniqueName("Member Resolution Agent"),
|
|
627
|
+
ORG,
|
|
628
|
+
);
|
|
625
629
|
const ref = { org: ORG, slug: agent.metadata!.slug };
|
|
626
630
|
|
|
627
|
-
const noShareErr = await grpcError(() =>
|
|
631
|
+
const noShareErr = await grpcError(() =>
|
|
632
|
+
query.getSharedProfileForMember(ref),
|
|
633
|
+
);
|
|
628
634
|
expect(noShareErr.code).toBe(Code.NotFound);
|
|
629
635
|
|
|
630
636
|
await shares.create({
|
|
@@ -637,7 +643,10 @@ describe("audience and the member resolution lane", () => {
|
|
|
637
643
|
});
|
|
638
644
|
|
|
639
645
|
it("the ANONYMOUS path collapses an org-audience share to the uniform NotFound (C2 close-out — the proto's audience contract)", async () => {
|
|
640
|
-
const agent = await createTestAgent(
|
|
646
|
+
const agent = await createTestAgent(
|
|
647
|
+
uniqueName("Org Audience Anon Agent"),
|
|
648
|
+
ORG,
|
|
649
|
+
);
|
|
641
650
|
await shares.create({
|
|
642
651
|
...shareFor(agent, true),
|
|
643
652
|
spec: { ...shareFor(agent, true).spec, audience: AgentShareAudience.org },
|
|
@@ -706,7 +715,9 @@ describe("rotateShareLink", () => {
|
|
|
706
715
|
|
|
707
716
|
// Capture the no-share NOT_FOUND before creating — the locked-link
|
|
708
717
|
// refusal must be byte-identical to it.
|
|
709
|
-
const noShareErr = await grpcError(() =>
|
|
718
|
+
const noShareErr = await grpcError(() =>
|
|
719
|
+
query.getSharedProfile(request("")),
|
|
720
|
+
);
|
|
710
721
|
|
|
711
722
|
const share = await shares.create(shareFor(agent, true));
|
|
712
723
|
|
|
@@ -714,23 +725,31 @@ describe("rotateShareLink", () => {
|
|
|
714
725
|
await query.getSharedProfile(request("stray-token"));
|
|
715
726
|
|
|
716
727
|
// Rotation locks the link: 27 url-safe chars, status-resident.
|
|
717
|
-
const rotated = await shares.rotateShareLink({
|
|
728
|
+
const rotated = await shares.rotateShareLink({
|
|
729
|
+
resourceId: share.metadata!.id,
|
|
730
|
+
});
|
|
718
731
|
const firstToken = rotated.status?.shareLinkToken ?? "";
|
|
719
732
|
expect(firstToken).toHaveLength(27);
|
|
720
733
|
expect(firstToken).toMatch(/^[A-Za-z0-9_-]+$/);
|
|
721
734
|
|
|
722
|
-
const lockedErr = await grpcError(() =>
|
|
735
|
+
const lockedErr = await grpcError(() =>
|
|
736
|
+
query.getSharedProfile(request("")),
|
|
737
|
+
);
|
|
723
738
|
expect(lockedErr.code).toBe(Code.NotFound);
|
|
724
739
|
expect(lockedErr.rawMessage).toBe(noShareErr.rawMessage);
|
|
725
740
|
|
|
726
741
|
await query.getSharedProfile(request(firstToken));
|
|
727
742
|
|
|
728
743
|
// Re-rotation kills the previous token.
|
|
729
|
-
const reRotated = await shares.rotateShareLink({
|
|
744
|
+
const reRotated = await shares.rotateShareLink({
|
|
745
|
+
resourceId: share.metadata!.id,
|
|
746
|
+
});
|
|
730
747
|
const secondToken = reRotated.status?.shareLinkToken ?? "";
|
|
731
748
|
expect(secondToken).not.toBe(firstToken);
|
|
732
749
|
|
|
733
|
-
const deadErr = await grpcError(() =>
|
|
750
|
+
const deadErr = await grpcError(() =>
|
|
751
|
+
query.getSharedProfile(request(firstToken)),
|
|
752
|
+
);
|
|
734
753
|
expect(deadErr.code).toBe(Code.NotFound);
|
|
735
754
|
await query.getSharedProfile(request(secondToken));
|
|
736
755
|
|
|
@@ -757,7 +776,10 @@ describe("rotateShareLink", () => {
|
|
|
757
776
|
});
|
|
758
777
|
|
|
759
778
|
it("member path stays open for org-audience shares even when a token exists", async () => {
|
|
760
|
-
const agent = await createTestAgent(
|
|
779
|
+
const agent = await createTestAgent(
|
|
780
|
+
uniqueName("Org Audience Rotate Agent"),
|
|
781
|
+
ORG,
|
|
782
|
+
);
|
|
761
783
|
const created = await shares.create({
|
|
762
784
|
...shareFor(agent, true),
|
|
763
785
|
spec: { ...shareFor(agent, true).spec, audience: AgentShareAudience.org },
|
|
@@ -778,11 +800,15 @@ describe("rotateShareLink", () => {
|
|
|
778
800
|
|
|
779
801
|
describe("getByAgent", () => {
|
|
780
802
|
it("finds the canonical share and a renamed share", async () => {
|
|
781
|
-
const agent = await createTestAgent(
|
|
803
|
+
const agent = await createTestAgent(
|
|
804
|
+
uniqueName("Get By Agent Agent"),
|
|
805
|
+
"gba-org",
|
|
806
|
+
);
|
|
782
807
|
const canonical = await shares.create(shareFor(agent, true));
|
|
783
808
|
|
|
784
809
|
const renamed = shareFor(agent, true);
|
|
785
|
-
(renamed.metadata as Record<string, string>).name =
|
|
810
|
+
(renamed.metadata as Record<string, string>).name =
|
|
811
|
+
uniqueName("Renamed Channel");
|
|
786
812
|
const second = await shares.create(renamed);
|
|
787
813
|
|
|
788
814
|
const list = await query.getByAgent({ agentId: agent.metadata!.id });
|
|
@@ -802,25 +828,21 @@ describe("getByAgent", () => {
|
|
|
802
828
|
uniqueName("Org Scoped List Agent"),
|
|
803
829
|
"gba-provider-org",
|
|
804
830
|
);
|
|
805
|
-
await makeAgentPublic(agent);
|
|
806
831
|
await shares.create(shareFor(agent, true));
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
crossOrg.spec.agentRef = {
|
|
811
|
-
...crossOrg.spec.agentRef,
|
|
812
|
-
org: agent.metadata!.org,
|
|
813
|
-
} as never;
|
|
814
|
-
await shares.create(crossOrg);
|
|
832
|
+
const named = shareFor(agent, true);
|
|
833
|
+
named.metadata = { ...named.metadata, name: "second link" } as never;
|
|
834
|
+
await shares.create(named);
|
|
815
835
|
|
|
816
836
|
const cases: Array<{ org: string; want: number; wantOrg: string }> = [
|
|
817
837
|
{ org: "", want: 2, wantOrg: "" },
|
|
818
|
-
{ org: "gba-provider-org", want:
|
|
819
|
-
{ org: "gba-consumer-org", want: 1, wantOrg: "gba-consumer-org" },
|
|
838
|
+
{ org: "gba-provider-org", want: 2, wantOrg: "gba-provider-org" },
|
|
820
839
|
{ org: "gba-bystander-org", want: 0, wantOrg: "" },
|
|
821
840
|
];
|
|
822
841
|
for (const tt of cases) {
|
|
823
|
-
const list = await query.getByAgent({
|
|
842
|
+
const list = await query.getByAgent({
|
|
843
|
+
agentId: agent.metadata!.id,
|
|
844
|
+
org: tt.org,
|
|
845
|
+
});
|
|
824
846
|
expect(list.totalCount, `org ${tt.org}`).toBe(tt.want);
|
|
825
847
|
for (const item of list.items) {
|
|
826
848
|
if (tt.wantOrg !== "") {
|
|
@@ -848,7 +870,9 @@ describe("apply semantics", () => {
|
|
|
848
870
|
expect(created.metadata?.id).not.toBe("");
|
|
849
871
|
|
|
850
872
|
const again = shareFor(agent, true);
|
|
851
|
-
(again.spec as Record<string, unknown>).allowedOrigins = [
|
|
873
|
+
(again.spec as Record<string, unknown>).allowedOrigins = [
|
|
874
|
+
"https://docs.example.com",
|
|
875
|
+
];
|
|
852
876
|
const updated = await shares.apply(again);
|
|
853
877
|
expect(updated.metadata?.id).toBe(created.metadata!.id);
|
|
854
878
|
expect(updated.spec?.allowedOrigins).toHaveLength(1);
|