@stigmer/server 3.22.1-dev.20260922095755 → 3.22.1
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 +8 -4
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +9 -5
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/derived-tuples.d.ts.map +1 -1
- package/dist/authorization/derived-tuples.js +25 -10
- package/dist/authorization/derived-tuples.js.map +1 -1
- package/dist/authorization/evaluator.d.ts +8 -7
- package/dist/authorization/evaluator.d.ts.map +1 -1
- package/dist/authorization/evaluator.js +20 -4
- 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 +9 -5
- 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 +5 -4
- 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 +4 -3
- package/dist/authorization/model/plugin.js.map +1 -1
- package/dist/authorization/model/rewrite.d.ts +10 -8
- package/dist/authorization/model/rewrite.d.ts.map +1 -1
- package/dist/authorization/model/rewrite.js +3 -0
- 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 +3 -2
- package/dist/authorization/organization-directory.js.map +1 -1
- package/dist/authorization/store-test-kit.d.ts +6 -0
- package/dist/authorization/store-test-kit.d.ts.map +1 -1
- package/dist/authorization/store-test-kit.js +62 -16
- package/dist/authorization/store-test-kit.js.map +1 -1
- package/dist/authorization/tuples.d.ts +32 -13
- package/dist/authorization/tuples.d.ts.map +1 -1
- package/dist/authorization/tuples.js +11 -3
- 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 +1 -3
- 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 +1 -3
- 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 +4 -3
- package/dist/domain/agentinstance/controller.js.map +1 -1
- package/dist/domain/agentshare/constants.d.ts +11 -6
- package/dist/domain/agentshare/constants.d.ts.map +1 -1
- package/dist/domain/agentshare/constants.js +16 -8
- 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 +1 -3
- package/dist/domain/agentshare/controller.js.map +1 -1
- package/dist/domain/agentshare/steps.d.ts +25 -18
- package/dist/domain/agentshare/steps.d.ts.map +1 -1
- package/dist/domain/agentshare/steps.js +142 -41
- 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 +3 -2
- 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 +1 -2
- 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 +4 -3
- 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 +3 -1
- package/dist/domain/plugin/controller.js.map +1 -1
- package/dist/domain/plugin/push.d.ts +5 -7
- package/dist/domain/plugin/push.d.ts.map +1 -1
- package/dist/domain/plugin/push.js +14 -8
- 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 +1 -3
- 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 +2 -3
- 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 +2 -0
- package/dist/domain/skill/controller.js.map +1 -1
- package/dist/domain/workflow/controller.d.ts.map +1 -1
- package/dist/domain/workflow/controller.js +6 -14
- package/dist/domain/workflow/controller.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -1
- package/dist/domain/workflow/validation/task-config-constraints.d.ts +1 -10
- package/dist/domain/workflow/validation/task-config-constraints.d.ts.map +1 -1
- package/dist/domain/workflow/validation/task-config-constraints.js +2 -3
- 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 +2 -4
- 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 +4 -3
- package/dist/domain/workflowinstance/controller.js.map +1 -1
- package/dist/extensions/authorization-queries.d.ts +5 -6
- 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 +2 -3
- package/dist/extensions/resource-authorization.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/apiresource-meta.d.ts +3 -12
- package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
- package/dist/pipeline/apiresource-meta.js +10 -21
- package/dist/pipeline/apiresource-meta.js.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.d.ts +3 -9
- package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.js +11 -9
- package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
- package/dist/pipeline/steps/references.d.ts +20 -178
- package/dist/pipeline/steps/references.d.ts.map +1 -1
- package/dist/pipeline/steps/references.js +43 -344
- package/dist/pipeline/steps/references.js.map +1 -1
- package/dist/pipeline/steps/visibility-gates.d.ts +27 -0
- package/dist/pipeline/steps/visibility-gates.d.ts.map +1 -0
- package/dist/pipeline/steps/visibility-gates.js +139 -0
- package/dist/pipeline/steps/visibility-gates.js.map +1 -0
- package/dist/query/search/controller.js +1 -0
- package/dist/query/search/controller.js.map +1 -1
- package/dist/query/search/criteria.d.ts +5 -1
- package/dist/query/search/criteria.d.ts.map +1 -1
- package/dist/query/search/criteria.js +13 -3
- package/dist/query/search/criteria.js.map +1 -1
- package/dist/query/search/handler.d.ts +4 -5
- package/dist/query/search/handler.d.ts.map +1 -1
- package/dist/query/search/handler.js +6 -7
- 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 +2 -0
- package/dist/query/search/query-store.js.map +1 -1
- package/dist/store/interface.d.ts +6 -3
- package/dist/store/interface.d.ts.map +1 -1
- package/dist/store/interface.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +1 -3
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +1 -35
- 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 +9 -4
- package/dist/store/postgres/store.js.map +1 -1
- package/dist/store/sqlite/migrations.d.ts +1 -3
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +1 -36
- 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 +8 -4
- package/dist/store/sqlite/store.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/README.md +26 -24
- package/src/authorization/__tests__/authorizer.test.ts +9 -10
- package/src/authorization/__tests__/derived-tuples.test.ts +11 -4
- package/src/authorization/__tests__/evaluator.test.ts +73 -14
- package/src/authorization/__tests__/facts.test.ts +2 -2
- package/src/authorization/__tests__/fixtures/fga/agent-instance-creation.fga.yaml +185 -0
- package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +98 -6
- package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +98 -0
- package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +61 -4
- package/src/authorization/__tests__/fixtures/fga/mcp-server-authoring.fga.yaml +143 -0
- package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +21 -1
- package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +25 -1
- package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +52 -0
- package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +3 -1
- package/src/authorization/__tests__/list-read-scope.test.ts +17 -18
- package/src/authorization/__tests__/store-tests.test.ts +8 -1
- package/src/authorization/__tests__/tuples.test.ts +11 -12
- package/src/authorization/authorizer.ts +9 -4
- package/src/authorization/derived-tuples.ts +31 -14
- package/src/authorization/evaluator.ts +44 -8
- package/src/authorization/list-read-scope.ts +11 -5
- package/src/authorization/model/agent.ts +5 -2
- package/src/authorization/model/agent_instance.ts +2 -0
- package/src/authorization/model/mcp_server.ts +2 -0
- package/src/authorization/model/plugin.ts +4 -1
- package/src/authorization/model/rewrite.ts +13 -8
- package/src/authorization/model/skill.ts +2 -0
- package/src/authorization/model/workflow.ts +2 -0
- package/src/authorization/model/workflow_instance.ts +2 -0
- package/src/authorization/organization-directory.ts +3 -1
- package/src/authorization/store-test-kit.ts +75 -16
- package/src/authorization/tuples.ts +39 -16
- package/src/domain/agent/__tests__/agent.test.ts +4 -11
- package/src/domain/agent/controller.ts +7 -7
- package/src/domain/agentchannel/__tests__/agentchannel.test.ts +48 -223
- package/src/domain/agentchannel/controller.ts +1 -6
- package/src/domain/agentexecution/controller.ts +1 -6
- package/src/domain/agentinstance/controller.ts +12 -6
- package/src/domain/agentshare/__tests__/agentshare.test.ts +172 -196
- package/src/domain/agentshare/__tests__/create-authorization.test.ts +31 -16
- package/src/domain/agentshare/constants.ts +26 -14
- package/src/domain/agentshare/controller.ts +1 -6
- package/src/domain/agentshare/steps.ts +194 -41
- package/src/domain/environment/controller.ts +8 -5
- package/src/domain/executioncontext/controller.ts +1 -5
- package/src/domain/mcpserver/__tests__/mcpserver.test.ts +28 -115
- package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +18 -53
- package/src/domain/mcpserver/controller.ts +12 -6
- package/src/domain/plugin/controller.ts +8 -1
- package/src/domain/plugin/push.ts +16 -8
- package/src/domain/schedule/controller.ts +1 -6
- package/src/domain/session/controller.ts +4 -12
- package/src/domain/skill/controller.ts +7 -0
- package/src/domain/workflow/controller.ts +10 -28
- package/src/domain/workflow/registry/data/task-kind-registry.json +1 -1
- package/src/domain/workflow/validation/task-config-constraints.ts +3 -7
- package/src/domain/workflowexecution/controller.ts +2 -7
- package/src/domain/workflowinstance/controller.ts +12 -6
- package/src/extensions/__tests__/built-in-authorization-composed.test.ts +19 -32
- package/src/extensions/__tests__/extension-composition.test.ts +4 -4
- package/src/extensions/__tests__/list-read-scope-composed.test.ts +6 -9
- package/src/extensions/authorization-queries.ts +5 -6
- package/src/extensions/list-read-scope.ts +1 -1
- package/src/extensions/resource-authorization.ts +5 -3
- package/src/index.ts +14 -0
- package/src/pipeline/apiresource-meta.ts +10 -21
- package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +31 -18
- package/src/pipeline/steps/__tests__/visibility-gates.test.ts +187 -0
- package/src/pipeline/steps/authorization-tuples.ts +11 -9
- package/src/pipeline/steps/references.ts +70 -578
- package/src/pipeline/steps/visibility-gates.ts +174 -0
- package/src/query/search/__tests__/criteria.test.ts +4 -0
- package/src/query/search/__tests__/query-store.test.ts +40 -11
- package/src/query/search/controller.ts +1 -0
- package/src/query/search/criteria.ts +14 -0
- package/src/query/search/handler.ts +7 -6
- package/src/query/search/query-store.ts +2 -0
- package/src/store/__tests__/store-contract.ts +51 -6
- package/src/store/interface.ts +6 -3
- package/src/store/postgres/__tests__/migrations.test.ts +6 -187
- package/src/store/postgres/__tests__/store-contract.test.ts +2 -0
- package/src/store/postgres/migrations.ts +1 -48
- package/src/store/postgres/store.ts +11 -4
- package/src/store/sqlite/__tests__/migrations.test.ts +5 -191
- package/src/store/sqlite/migrations.ts +1 -45
- package/src/store/sqlite/store.ts +10 -4
- package/dist/domain/workflow/agent-call-references.d.ts +0 -54
- package/dist/domain/workflow/agent-call-references.d.ts.map +0 -1
- package/dist/domain/workflow/agent-call-references.js +0 -97
- package/dist/domain/workflow/agent-call-references.js.map +0 -1
- package/dist/store/public-visibility-retired.d.ts +0 -67
- package/dist/store/public-visibility-retired.d.ts.map +0 -1
- package/dist/store/public-visibility-retired.js +0 -55
- package/dist/store/public-visibility-retired.js.map +0 -1
- package/src/domain/workflow/__tests__/agent-call-references.test.ts +0 -222
- package/src/domain/workflow/agent-call-references.ts +0 -157
- package/src/pipeline/__tests__/supports-visibility.test.ts +0 -112
- package/src/pipeline/steps/__tests__/references.test.ts +0 -703
- package/src/store/__tests__/public-visibility-retired.test.ts +0 -127
- package/src/store/public-visibility-retired.ts +0 -119
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* built-in authorizer: which tuples a stored row stands for, in exactly
|
|
4
4
|
* the shapes the cloud's tuple driver writes (stigmer-cloud
|
|
5
5
|
* iam/tuple-lifecycle.ts: `organization:<org>#viewer` for the org level,
|
|
6
|
-
* the
|
|
6
|
+
* the conditional `identity_account:*` for public, the owner by the
|
|
7
|
+
* kind's attribution, the parent links by `kind_meta`). Two facts are the
|
|
7
8
|
* OSS edition's own and are pinned here by name: the organization's owner
|
|
8
9
|
* is a ROW (2b's role lifecycle), never derived from its creator stamp,
|
|
9
10
|
* or a revoked founder would stay owner; and a stamp that names no person
|
|
@@ -95,7 +96,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
95
96
|
]);
|
|
96
97
|
});
|
|
97
98
|
|
|
98
|
-
it("a
|
|
99
|
+
it("a public blueprint adds the conditional wildcard AND keeps the org floor", () => {
|
|
99
100
|
expect(
|
|
100
101
|
derivedFor("skill", {
|
|
101
102
|
visibility: ApiResourceVisibility.visibility_public,
|
|
@@ -103,6 +104,8 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
103
104
|
).toEqual([
|
|
104
105
|
"skill:skill-1#organization@organization:acme",
|
|
105
106
|
"skill:skill-1#owner@identity_account:ida_carol",
|
|
107
|
+
"skill:skill-1#viewer@identity_account:* with allow_public",
|
|
108
|
+
"skill:skill-1#viewer@organization:acme#viewer",
|
|
106
109
|
]);
|
|
107
110
|
});
|
|
108
111
|
|
|
@@ -163,7 +166,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
163
166
|
).toEqual(["memory:memory-1#organization@organization:acme"]);
|
|
164
167
|
});
|
|
165
168
|
|
|
166
|
-
it("an environment carries its creator tuple
|
|
169
|
+
it("an environment carries its creator tuple, an org-viewer at org level, and NO public wildcard (the kind's ceiling)", () => {
|
|
167
170
|
expect(
|
|
168
171
|
derivedFor("environment", {
|
|
169
172
|
visibility: ApiResourceVisibility.visibility_org,
|
|
@@ -176,7 +179,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
176
179
|
]);
|
|
177
180
|
expect(
|
|
178
181
|
derivedFor("environment", {
|
|
179
|
-
visibility: ApiResourceVisibility.
|
|
182
|
+
visibility: ApiResourceVisibility.visibility_public,
|
|
180
183
|
}),
|
|
181
184
|
).toEqual([
|
|
182
185
|
"environment:environment-1#organization@organization:acme",
|
|
@@ -506,6 +509,9 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
506
509
|
object,
|
|
507
510
|
"can_view",
|
|
508
511
|
DAVE,
|
|
512
|
+
{
|
|
513
|
+
allow: false,
|
|
514
|
+
},
|
|
509
515
|
),
|
|
510
516
|
).toBe(true);
|
|
511
517
|
expect(rowReads).toBe(1);
|
|
@@ -701,6 +707,7 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
701
707
|
parseObjectRef(object),
|
|
702
708
|
relation,
|
|
703
709
|
person,
|
|
710
|
+
{ allow: true },
|
|
704
711
|
);
|
|
705
712
|
}
|
|
706
713
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pins the evaluator's semantics the store tests cannot express (the
|
|
3
3
|
* cloud's `.fga.yaml` documents prove the model's answers; this file
|
|
4
|
-
* proves the machinery under them): how a person matches a tuple,
|
|
5
|
-
* direct tuple outside the line's
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* proves the machinery under them): how a person matches a tuple, what
|
|
5
|
+
* the `allow_public` context does, that a direct tuple outside the line's
|
|
6
|
+
* type restriction is ignored (model drift fails closed), how far a
|
|
7
|
+
* resolution may walk, and that a declaration cycle or an undeclared
|
|
8
|
+
* target is a thrown fault and never a silent deny.
|
|
8
9
|
*
|
|
9
10
|
* The fixture source is the in-memory one the store-test kit uses, so the
|
|
10
11
|
* two proofs share one tuple vocabulary. Where a case needs a shape the
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
direct,
|
|
30
31
|
from,
|
|
31
32
|
objectOf,
|
|
33
|
+
publicWith,
|
|
32
34
|
union,
|
|
33
35
|
usersetOf,
|
|
34
36
|
} from "../model/rewrite.js";
|
|
@@ -54,17 +56,22 @@ function person(accountId: string, ...aliases: string[]): Person {
|
|
|
54
56
|
return { accountId, aliases: new Set([accountId, ...aliases]) };
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
const RESOLVE = { allow: true };
|
|
60
|
+
const LIST = { allow: false };
|
|
61
|
+
|
|
57
62
|
async function allowed(
|
|
58
63
|
source: TupleSource,
|
|
59
64
|
object: string,
|
|
60
65
|
relation: string,
|
|
61
66
|
who: Person,
|
|
67
|
+
context = RESOLVE,
|
|
62
68
|
): Promise<boolean> {
|
|
63
69
|
return checkRelation(
|
|
64
70
|
{ model: builtInModel, source },
|
|
65
71
|
parseObjectRef(object),
|
|
66
72
|
relation,
|
|
67
73
|
who,
|
|
74
|
+
context,
|
|
68
75
|
);
|
|
69
76
|
}
|
|
70
77
|
|
|
@@ -93,17 +100,67 @@ describe("a person against a direct tuple", () => {
|
|
|
93
100
|
});
|
|
94
101
|
});
|
|
95
102
|
|
|
96
|
-
describe("
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
describe("the public wildcard and its condition", () => {
|
|
104
|
+
const publicViewer = (object: string): Tuple => ({
|
|
105
|
+
object: parseObjectRef(object),
|
|
106
|
+
relation: "viewer",
|
|
107
|
+
subject: {
|
|
108
|
+
form: "wildcard",
|
|
109
|
+
type: "identity_account",
|
|
110
|
+
condition: "allow_public",
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
const source = newInMemoryTupleSource([
|
|
114
|
+
tuple("agent:open#organization@organization:acme"),
|
|
115
|
+
publicViewer("agent:open"),
|
|
116
|
+
]);
|
|
117
|
+
const stranger = person("ida_mallory");
|
|
118
|
+
|
|
119
|
+
it("reads for anyone on a point check (the cloud's `allow: true`) and for nobody in a listing (`allow: false`)", async () => {
|
|
104
120
|
expect(await allowed(source, "agent:open", "can_view", stranger)).toBe(
|
|
105
|
-
|
|
121
|
+
true,
|
|
106
122
|
);
|
|
123
|
+
expect(
|
|
124
|
+
await allowed(source, "agent:open", "can_view", stranger, LIST),
|
|
125
|
+
).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("ignores a wildcard tuple that carries no condition where the line demands one — a tuple the cloud could never have written", async () => {
|
|
129
|
+
const bare = newInMemoryTupleSource([
|
|
130
|
+
tuple("agent:open#viewer@identity_account:*"),
|
|
131
|
+
]);
|
|
132
|
+
expect(await allowed(bare, "agent:open", "can_view", stranger)).toBe(false);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("is a thrown fault under a condition the transcript names but the evaluator does not know — a model that grew a condition", async () => {
|
|
136
|
+
const grown = declareKind({
|
|
137
|
+
kind: ApiResourceKind.agent,
|
|
138
|
+
schema: AgentSchema,
|
|
139
|
+
source: "test/grown.fga",
|
|
140
|
+
relations: [
|
|
141
|
+
["viewer", direct(publicWith("identity_account", "after_hours"))],
|
|
142
|
+
],
|
|
143
|
+
});
|
|
144
|
+
const afterHours = newInMemoryTupleSource([
|
|
145
|
+
{
|
|
146
|
+
object: parseObjectRef("agent:open"),
|
|
147
|
+
relation: "viewer",
|
|
148
|
+
subject: {
|
|
149
|
+
form: "wildcard",
|
|
150
|
+
type: "identity_account",
|
|
151
|
+
condition: "after_hours",
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
]);
|
|
155
|
+
await expect(
|
|
156
|
+
checkRelation(
|
|
157
|
+
{ model: newModel([grown]), source: afterHours },
|
|
158
|
+
parseObjectRef("agent:open"),
|
|
159
|
+
"viewer",
|
|
160
|
+
stranger,
|
|
161
|
+
RESOLVE,
|
|
162
|
+
),
|
|
163
|
+
).rejects.toMatchObject({ reason: "unknown-condition" });
|
|
107
164
|
});
|
|
108
165
|
});
|
|
109
166
|
|
|
@@ -220,6 +277,7 @@ describe("the walk itself", () => {
|
|
|
220
277
|
parseObjectRef("agent:n0"),
|
|
221
278
|
"next",
|
|
222
279
|
person("ida_nobody"),
|
|
280
|
+
RESOLVE,
|
|
223
281
|
),
|
|
224
282
|
).rejects.toMatchObject({ reason: "resolution-depth-exceeded" });
|
|
225
283
|
});
|
|
@@ -240,6 +298,7 @@ describe("the walk itself", () => {
|
|
|
240
298
|
parseObjectRef("agent:x"),
|
|
241
299
|
"a",
|
|
242
300
|
person("ida_nobody"),
|
|
301
|
+
RESOLVE,
|
|
243
302
|
),
|
|
244
303
|
).rejects.toBeInstanceOf(AuthorizationEvaluationError);
|
|
245
304
|
});
|
|
@@ -273,7 +332,7 @@ describe("declareKind validates a transcript at load", () => {
|
|
|
273
332
|
source: "test/bad.fga",
|
|
274
333
|
relations: [
|
|
275
334
|
["viewer", direct(objectOf("identity_account"))],
|
|
276
|
-
["viewer", direct(
|
|
335
|
+
["viewer", direct(publicWith("identity_account", "allow_public"))],
|
|
277
336
|
],
|
|
278
337
|
}),
|
|
279
338
|
).toThrow("declared twice");
|
|
@@ -50,7 +50,7 @@ describe("rowFactsOf against the tuple lifecycle's own resolution", () => {
|
|
|
50
50
|
for (const visibility of [
|
|
51
51
|
ApiResourceVisibility.visibility_private,
|
|
52
52
|
ApiResourceVisibility.visibility_org,
|
|
53
|
-
ApiResourceVisibility.
|
|
53
|
+
ApiResourceVisibility.visibility_public,
|
|
54
54
|
]) {
|
|
55
55
|
it(`${declaration.type} at ${ApiResourceVisibility[visibility]}: the same parent links and visibility shapes`, () => {
|
|
56
56
|
const row = fixtureRow(declaration, {
|
|
@@ -133,7 +133,7 @@ describe("a list candidate against the loaded row — the facts' two producers",
|
|
|
133
133
|
for (const visibility of [
|
|
134
134
|
ApiResourceVisibility.visibility_private,
|
|
135
135
|
ApiResourceVisibility.visibility_org,
|
|
136
|
-
ApiResourceVisibility.
|
|
136
|
+
ApiResourceVisibility.visibility_public,
|
|
137
137
|
]) {
|
|
138
138
|
it(`${declaration.type} at ${ApiResourceVisibility[visibility]}: the candidate the helper builds carries the facts the driver derives from`, async () => {
|
|
139
139
|
const row = fixtureRow(declaration, {
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Pinned copy of stigmer-cloud backend/services/stigmer-server/fga/tests/agent-instance-creation.fga.yaml
|
|
2
|
+
# at commit 4c03c38d2 (the OpenFGA store test the cloud runs against its live model).
|
|
3
|
+
# The body below is byte-identical to the source; the cloud re-runs the LIVE
|
|
4
|
+
# file against this evaluator at the re-pin, so a stale copy is caught there.
|
|
5
|
+
# Store tests for agent-instance creation: two halves, asked together by
|
|
6
|
+
# the create since stigmer#1209 (v3.22.0). The agent half is the agent's
|
|
7
|
+
# can_create_instance (can_execute, so the viewer set: whoever may run the
|
|
8
|
+
# agent may instantiate it). The organization half is
|
|
9
|
+
# can_create_agent_instance: member on the organization the instance is
|
|
10
|
+
# created IN, which is the caller's own, not the agent's: a personal
|
|
11
|
+
# instance of another organization's public agent lives in the caller's
|
|
12
|
+
# organization (the marketplace case), so the agent's permission alone
|
|
13
|
+
# would let a row be planted in any organization named on the request.
|
|
14
|
+
#
|
|
15
|
+
# What these pin: owners, admins and members hold the organization half;
|
|
16
|
+
# a viewer-role account may run an org-visible agent (the agent half) and
|
|
17
|
+
# still lacks the organization half; a guest holds neither; an outsider
|
|
18
|
+
# holds neither; and the marketplace case passes on the caller's own
|
|
19
|
+
# organization while the agent half comes from the public wildcard.
|
|
20
|
+
#
|
|
21
|
+
# Run: fga model test --tests agent-instance-creation.fga.yaml
|
|
22
|
+
|
|
23
|
+
name: agent-instance-creation
|
|
24
|
+
model_file: ../model/fga.mod
|
|
25
|
+
|
|
26
|
+
tuples:
|
|
27
|
+
# Org acme: olivia owns it, oscar administers, dave is a plain member,
|
|
28
|
+
# vera a read-only viewer, greta the share-link guest account.
|
|
29
|
+
- user: identity_account:olivia
|
|
30
|
+
relation: owner
|
|
31
|
+
object: organization:acme
|
|
32
|
+
- user: identity_account:oscar
|
|
33
|
+
relation: admin
|
|
34
|
+
object: organization:acme
|
|
35
|
+
- user: identity_account:dave
|
|
36
|
+
relation: member
|
|
37
|
+
object: organization:acme
|
|
38
|
+
- user: identity_account:vera
|
|
39
|
+
relation: viewer
|
|
40
|
+
object: organization:acme
|
|
41
|
+
- user: identity_account:greta
|
|
42
|
+
relation: guest
|
|
43
|
+
object: organization:acme
|
|
44
|
+
|
|
45
|
+
# Org consumer: mia is a plain member there and holds no role in acme.
|
|
46
|
+
- user: identity_account:mia
|
|
47
|
+
relation: member
|
|
48
|
+
object: organization:consumer
|
|
49
|
+
|
|
50
|
+
# An ORG-visible agent in acme, authored by oscar.
|
|
51
|
+
- user: organization:acme
|
|
52
|
+
relation: organization
|
|
53
|
+
object: agent:team-bot
|
|
54
|
+
- user: identity_account:oscar
|
|
55
|
+
relation: owner
|
|
56
|
+
object: agent:team-bot
|
|
57
|
+
- user: organization:acme#viewer
|
|
58
|
+
relation: viewer
|
|
59
|
+
object: agent:team-bot
|
|
60
|
+
|
|
61
|
+
# A PRIVATE agent in acme, authored by oscar (no visibility tuple).
|
|
62
|
+
- user: organization:acme
|
|
63
|
+
relation: organization
|
|
64
|
+
object: agent:secret-bot
|
|
65
|
+
- user: identity_account:oscar
|
|
66
|
+
relation: owner
|
|
67
|
+
object: agent:secret-bot
|
|
68
|
+
|
|
69
|
+
# A PUBLIC marketplace agent in acme (the conditional wildcard plus the
|
|
70
|
+
# org floor tuple the visibility writer emits).
|
|
71
|
+
- user: organization:acme
|
|
72
|
+
relation: organization
|
|
73
|
+
object: agent:open-bot
|
|
74
|
+
- user: identity_account:oscar
|
|
75
|
+
relation: owner
|
|
76
|
+
object: agent:open-bot
|
|
77
|
+
- user: identity_account:*
|
|
78
|
+
relation: viewer
|
|
79
|
+
object: agent:open-bot
|
|
80
|
+
condition:
|
|
81
|
+
name: allow_public
|
|
82
|
+
context: {}
|
|
83
|
+
- user: organization:acme#viewer
|
|
84
|
+
relation: viewer
|
|
85
|
+
object: agent:open-bot
|
|
86
|
+
|
|
87
|
+
tests:
|
|
88
|
+
- name: owners, admins and members hold the organization half
|
|
89
|
+
check:
|
|
90
|
+
- user: identity_account:olivia
|
|
91
|
+
object: organization:acme
|
|
92
|
+
assertions:
|
|
93
|
+
can_create_agent_instance: true
|
|
94
|
+
- user: identity_account:oscar
|
|
95
|
+
object: organization:acme
|
|
96
|
+
assertions:
|
|
97
|
+
can_create_agent_instance: true
|
|
98
|
+
- user: identity_account:dave
|
|
99
|
+
object: organization:acme
|
|
100
|
+
assertions:
|
|
101
|
+
can_create_agent_instance: true
|
|
102
|
+
|
|
103
|
+
- name: a viewer, a guest and an outsider do not
|
|
104
|
+
check:
|
|
105
|
+
- user: identity_account:vera
|
|
106
|
+
object: organization:acme
|
|
107
|
+
assertions:
|
|
108
|
+
can_create_agent_instance: false
|
|
109
|
+
can_create_session: false
|
|
110
|
+
- user: identity_account:greta
|
|
111
|
+
object: organization:acme
|
|
112
|
+
assertions:
|
|
113
|
+
can_create_agent_instance: false
|
|
114
|
+
can_create_session: true
|
|
115
|
+
- user: identity_account:mia
|
|
116
|
+
object: organization:acme
|
|
117
|
+
assertions:
|
|
118
|
+
can_create_agent_instance: false
|
|
119
|
+
|
|
120
|
+
- name: a member instantiates an org-visible agent, both halves held
|
|
121
|
+
check:
|
|
122
|
+
- user: identity_account:dave
|
|
123
|
+
object: agent:team-bot
|
|
124
|
+
context:
|
|
125
|
+
allow: false
|
|
126
|
+
assertions:
|
|
127
|
+
can_create_instance: true
|
|
128
|
+
can_execute: true
|
|
129
|
+
|
|
130
|
+
- name: a viewer may run the org-visible agent and still cannot instantiate it here
|
|
131
|
+
check:
|
|
132
|
+
- user: identity_account:vera
|
|
133
|
+
object: agent:team-bot
|
|
134
|
+
context:
|
|
135
|
+
allow: false
|
|
136
|
+
assertions:
|
|
137
|
+
can_create_instance: true
|
|
138
|
+
- user: identity_account:vera
|
|
139
|
+
object: organization:acme
|
|
140
|
+
assertions:
|
|
141
|
+
can_create_agent_instance: false
|
|
142
|
+
|
|
143
|
+
- name: a private agent gives the agent half to its author and the admins only
|
|
144
|
+
check:
|
|
145
|
+
- user: identity_account:oscar
|
|
146
|
+
object: agent:secret-bot
|
|
147
|
+
context:
|
|
148
|
+
allow: false
|
|
149
|
+
assertions:
|
|
150
|
+
can_create_instance: true
|
|
151
|
+
- user: identity_account:olivia
|
|
152
|
+
object: agent:secret-bot
|
|
153
|
+
context:
|
|
154
|
+
allow: false
|
|
155
|
+
assertions:
|
|
156
|
+
can_create_instance: true
|
|
157
|
+
- user: identity_account:dave
|
|
158
|
+
object: agent:secret-bot
|
|
159
|
+
context:
|
|
160
|
+
allow: false
|
|
161
|
+
assertions:
|
|
162
|
+
can_create_instance: false
|
|
163
|
+
- user: identity_account:mia
|
|
164
|
+
object: agent:secret-bot
|
|
165
|
+
context:
|
|
166
|
+
allow: false
|
|
167
|
+
assertions:
|
|
168
|
+
can_create_instance: false
|
|
169
|
+
|
|
170
|
+
- name: the marketplace case, the agent half from the wildcard and the organization half at home
|
|
171
|
+
check:
|
|
172
|
+
- user: identity_account:mia
|
|
173
|
+
object: agent:open-bot
|
|
174
|
+
context:
|
|
175
|
+
allow: true
|
|
176
|
+
assertions:
|
|
177
|
+
can_create_instance: true
|
|
178
|
+
- user: identity_account:mia
|
|
179
|
+
object: organization:consumer
|
|
180
|
+
assertions:
|
|
181
|
+
can_create_agent_instance: true
|
|
182
|
+
- user: identity_account:mia
|
|
183
|
+
object: organization:acme
|
|
184
|
+
assertions:
|
|
185
|
+
can_create_agent_instance: false
|