@stigmer/server 3.27.2 → 3.28.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/README.md +2 -0
- package/dist/authorization/authorizer.d.ts +3 -3
- package/dist/authorization/authorizer.js +3 -3
- package/dist/authorization/derived-tuples.js +6 -1
- package/dist/authorization/derived-tuples.js.map +1 -1
- package/dist/authorization/evaluator.d.ts +9 -10
- package/dist/authorization/evaluator.d.ts.map +1 -1
- 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 +29 -18
- package/dist/authorization/list-read-scope.js.map +1 -1
- package/dist/authorization/model/bindings.d.ts +41 -0
- package/dist/authorization/model/bindings.d.ts.map +1 -0
- package/dist/authorization/model/bindings.js +89 -0
- package/dist/authorization/model/bindings.js.map +1 -0
- package/dist/authorization/model/data/authorization-model.json +3114 -0
- package/dist/authorization/model/default-of.d.ts +2 -2
- package/dist/authorization/model/execution-viewer.d.ts +3 -0
- package/dist/authorization/model/execution-viewer.d.ts.map +1 -0
- package/dist/authorization/model/execution-viewer.js +50 -0
- package/dist/authorization/model/execution-viewer.js.map +1 -0
- package/dist/authorization/model/index.d.ts +33 -21
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +74 -52
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/openfga-json.d.ts +18 -0
- package/dist/authorization/model/openfga-json.d.ts.map +1 -0
- package/dist/authorization/model/openfga-json.js +266 -0
- package/dist/authorization/model/openfga-json.js.map +1 -0
- package/dist/authorization/model/rewrite.d.ts +39 -67
- package/dist/authorization/model/rewrite.d.ts.map +1 -1
- package/dist/authorization/model/rewrite.js +1 -117
- package/dist/authorization/model/rewrite.js.map +1 -1
- package/dist/authorization/strict-json.d.ts +20 -0
- package/dist/authorization/strict-json.d.ts.map +1 -0
- package/dist/authorization/strict-json.js +45 -0
- package/dist/authorization/strict-json.js.map +1 -0
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +9 -7
- package/dist/boot/compose.js.map +1 -1
- package/dist/domain/workflowexecution/list-index.d.ts +1 -1
- package/dist/extensions/list-read-scope.d.ts +18 -2
- package/dist/extensions/list-read-scope.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.js +20 -1
- package/dist/extensions/list-read-scope.js.map +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
- package/src/authorization/README.md +41 -34
- package/src/authorization/__tests__/authorizer.test.ts +5 -14
- package/src/authorization/__tests__/derived-tuples.test.ts +29 -27
- package/src/authorization/__tests__/evaluator.test.ts +53 -160
- package/src/authorization/__tests__/facts.test.ts +5 -11
- package/src/authorization/__tests__/list-read-scope.measure.test.ts +12 -20
- package/src/authorization/__tests__/list-read-scope.test.ts +15 -14
- package/src/authorization/__tests__/organization-directory.test.ts +2 -2
- package/src/authorization/__tests__/store-test-kit.ts +246 -0
- package/src/authorization/__tests__/store-tests.test.ts +91 -223
- package/src/authorization/__tests__/support.ts +30 -2
- package/src/authorization/__tests__/throwaway-model.ts +75 -0
- package/src/authorization/__tests__/wire-permissions.test.ts +141 -107
- package/src/authorization/authorizer.ts +3 -3
- package/src/authorization/derived-tuples.ts +7 -2
- package/src/authorization/evaluator.ts +8 -10
- package/src/authorization/list-read-scope.ts +37 -22
- package/src/authorization/model/__tests__/openfga-json.test.ts +353 -0
- package/src/authorization/model/__tests__/registry.test.ts +102 -276
- package/src/authorization/model/bindings.ts +131 -0
- package/src/authorization/model/data/authorization-model.json +3114 -0
- package/src/authorization/model/default-of.ts +2 -2
- package/src/authorization/model/execution-viewer.ts +56 -0
- package/src/authorization/model/index.ts +81 -72
- package/src/authorization/model/openfga-json.ts +310 -0
- package/src/authorization/model/rewrite.ts +39 -188
- package/src/authorization/strict-json.ts +52 -0
- package/src/boot/compose.ts +9 -7
- package/src/extensions/__tests__/built-in-authorization-composed.test.ts +3 -6
- package/src/extensions/list-read-scope.ts +30 -3
- package/src/index.ts +15 -44
- package/dist/authorization/model/agent.d.ts +0 -2
- package/dist/authorization/model/agent.d.ts.map +0 -1
- package/dist/authorization/model/agent.js +0 -43
- package/dist/authorization/model/agent.js.map +0 -1
- package/dist/authorization/model/agent_channel.d.ts +0 -2
- package/dist/authorization/model/agent_channel.d.ts.map +0 -1
- package/dist/authorization/model/agent_channel.js +0 -39
- package/dist/authorization/model/agent_channel.js.map +0 -1
- package/dist/authorization/model/agent_execution.d.ts +0 -2
- package/dist/authorization/model/agent_execution.d.ts.map +0 -1
- package/dist/authorization/model/agent_execution.js +0 -25
- package/dist/authorization/model/agent_execution.js.map +0 -1
- package/dist/authorization/model/agent_instance.d.ts +0 -2
- package/dist/authorization/model/agent_instance.d.ts.map +0 -1
- package/dist/authorization/model/agent_instance.js +0 -48
- package/dist/authorization/model/agent_instance.js.map +0 -1
- package/dist/authorization/model/agent_share.d.ts +0 -2
- package/dist/authorization/model/agent_share.d.ts.map +0 -1
- package/dist/authorization/model/agent_share.js +0 -29
- package/dist/authorization/model/agent_share.js.map +0 -1
- package/dist/authorization/model/api_key.d.ts +0 -2
- package/dist/authorization/model/api_key.d.ts.map +0 -1
- package/dist/authorization/model/api_key.js +0 -27
- package/dist/authorization/model/api_key.js.map +0 -1
- package/dist/authorization/model/artifact.d.ts +0 -2
- package/dist/authorization/model/artifact.d.ts.map +0 -1
- package/dist/authorization/model/artifact.js +0 -27
- package/dist/authorization/model/artifact.js.map +0 -1
- package/dist/authorization/model/channel_app.d.ts +0 -2
- package/dist/authorization/model/channel_app.d.ts.map +0 -1
- package/dist/authorization/model/channel_app.js +0 -28
- package/dist/authorization/model/channel_app.js.map +0 -1
- package/dist/authorization/model/environment.d.ts +0 -2
- package/dist/authorization/model/environment.d.ts.map +0 -1
- package/dist/authorization/model/environment.js +0 -33
- package/dist/authorization/model/environment.js.map +0 -1
- package/dist/authorization/model/execution_context.d.ts +0 -2
- package/dist/authorization/model/execution_context.d.ts.map +0 -1
- package/dist/authorization/model/execution_context.js +0 -19
- package/dist/authorization/model/execution_context.js.map +0 -1
- package/dist/authorization/model/iam_policy.d.ts +0 -2
- package/dist/authorization/model/iam_policy.d.ts.map +0 -1
- package/dist/authorization/model/iam_policy.js +0 -31
- package/dist/authorization/model/iam_policy.js.map +0 -1
- package/dist/authorization/model/identity_account.d.ts +0 -2
- package/dist/authorization/model/identity_account.d.ts.map +0 -1
- package/dist/authorization/model/identity_account.js +0 -25
- package/dist/authorization/model/identity_account.js.map +0 -1
- package/dist/authorization/model/mcp_server.d.ts +0 -2
- package/dist/authorization/model/mcp_server.d.ts.map +0 -1
- package/dist/authorization/model/mcp_server.js +0 -38
- package/dist/authorization/model/mcp_server.js.map +0 -1
- package/dist/authorization/model/memory.d.ts +0 -2
- package/dist/authorization/model/memory.d.ts.map +0 -1
- package/dist/authorization/model/memory.js +0 -26
- package/dist/authorization/model/memory.js.map +0 -1
- package/dist/authorization/model/oauth_app.d.ts +0 -2
- package/dist/authorization/model/oauth_app.d.ts.map +0 -1
- package/dist/authorization/model/oauth_app.js +0 -31
- package/dist/authorization/model/oauth_app.js.map +0 -1
- package/dist/authorization/model/organization.d.ts +0 -2
- package/dist/authorization/model/organization.d.ts.map +0 -1
- package/dist/authorization/model/organization.js +0 -58
- package/dist/authorization/model/organization.js.map +0 -1
- package/dist/authorization/model/platform_client.d.ts +0 -2
- package/dist/authorization/model/platform_client.d.ts.map +0 -1
- package/dist/authorization/model/platform_client.js +0 -31
- package/dist/authorization/model/platform_client.js.map +0 -1
- package/dist/authorization/model/plugin.d.ts +0 -2
- package/dist/authorization/model/plugin.d.ts.map +0 -1
- package/dist/authorization/model/plugin.js +0 -45
- package/dist/authorization/model/plugin.js.map +0 -1
- package/dist/authorization/model/schedule.d.ts +0 -2
- package/dist/authorization/model/schedule.d.ts.map +0 -1
- package/dist/authorization/model/schedule.js +0 -34
- package/dist/authorization/model/schedule.js.map +0 -1
- package/dist/authorization/model/session.d.ts +0 -2
- package/dist/authorization/model/session.d.ts.map +0 -1
- package/dist/authorization/model/session.js +0 -38
- package/dist/authorization/model/session.js.map +0 -1
- package/dist/authorization/model/skill.d.ts +0 -2
- package/dist/authorization/model/skill.d.ts.map +0 -1
- package/dist/authorization/model/skill.js +0 -39
- package/dist/authorization/model/skill.js.map +0 -1
- package/dist/authorization/model/workflow.d.ts +0 -2
- package/dist/authorization/model/workflow.d.ts.map +0 -1
- package/dist/authorization/model/workflow.js +0 -39
- package/dist/authorization/model/workflow.js.map +0 -1
- package/dist/authorization/model/workflow_execution.d.ts +0 -2
- package/dist/authorization/model/workflow_execution.d.ts.map +0 -1
- package/dist/authorization/model/workflow_execution.js +0 -33
- package/dist/authorization/model/workflow_execution.js.map +0 -1
- package/dist/authorization/model/workflow_instance.d.ts +0 -2
- package/dist/authorization/model/workflow_instance.d.ts.map +0 -1
- package/dist/authorization/model/workflow_instance.js +0 -96
- package/dist/authorization/model/workflow_instance.js.map +0 -1
- package/dist/authorization/store-test-kit.d.ts +0 -62
- package/dist/authorization/store-test-kit.d.ts.map +0 -1
- package/dist/authorization/store-test-kit.js +0 -265
- package/dist/authorization/store-test-kit.js.map +0 -1
- package/src/authorization/__tests__/enterprise-model.ts +0 -59
- package/src/authorization/__tests__/fixtures/fga/agent-channel-owner.fga.yaml +0 -112
- package/src/authorization/__tests__/fixtures/fga/agent-instance-creation.fga.yaml +0 -177
- package/src/authorization/__tests__/fixtures/fga/agent-share-owner.fga.yaml +0 -109
- package/src/authorization/__tests__/fixtures/fga/artifact-org-and-owner.fga.yaml +0 -128
- package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +0 -318
- package/src/authorization/__tests__/fixtures/fga/channel-app-owner.fga.yaml +0 -125
- package/src/authorization/__tests__/fixtures/fga/channel-participation.fga.yaml +0 -201
- package/src/authorization/__tests__/fixtures/fga/channel-session-visibility.fga.yaml +0 -187
- package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +0 -214
- package/src/authorization/__tests__/fixtures/fga/mcp-server-authoring.fga.yaml +0 -129
- package/src/authorization/__tests__/fixtures/fga/memory-subject-only.fga.yaml +0 -72
- package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +0 -308
- package/src/authorization/__tests__/fixtures/fga/org-shared-environment.fga.yaml +0 -144
- package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +0 -199
- package/src/authorization/__tests__/fixtures/fga/provider-standing-viewer.fga.yaml +0 -40
- package/src/authorization/__tests__/fixtures/fga/reserved-label-writer.fga.yaml +0 -41
- package/src/authorization/__tests__/fixtures/fga/schedule-owner.fga.yaml +0 -113
- package/src/authorization/__tests__/fixtures/fga/schedule-session-visibility.fga.yaml +0 -214
- package/src/authorization/__tests__/fixtures/fga/session-personal-resource.fga.yaml +0 -117
- package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +0 -190
- package/src/authorization/model/agent.ts +0 -64
- package/src/authorization/model/agent_channel.ts +0 -57
- package/src/authorization/model/agent_execution.ts +0 -33
- package/src/authorization/model/agent_instance.ts +0 -66
- package/src/authorization/model/agent_share.ts +0 -40
- package/src/authorization/model/api_key.ts +0 -28
- package/src/authorization/model/artifact.ts +0 -38
- package/src/authorization/model/channel_app.ts +0 -39
- package/src/authorization/model/environment.ts +0 -48
- package/src/authorization/model/execution_context.ts +0 -20
- package/src/authorization/model/iam_policy.ts +0 -42
- package/src/authorization/model/identity_account.ts +0 -26
- package/src/authorization/model/mcp_server.ts +0 -59
- package/src/authorization/model/memory.ts +0 -27
- package/src/authorization/model/oauth_app.ts +0 -43
- package/src/authorization/model/organization.ts +0 -59
- package/src/authorization/model/platform_client.ts +0 -43
- package/src/authorization/model/plugin.ts +0 -66
- package/src/authorization/model/schedule.ts +0 -49
- package/src/authorization/model/session.ts +0 -50
- package/src/authorization/model/skill.ts +0 -60
- package/src/authorization/model/workflow.ts +0 -60
- package/src/authorization/model/workflow_execution.ts +0 -46
- package/src/authorization/model/workflow_instance.ts +0 -125
- package/src/authorization/store-test-kit.ts +0 -395
|
@@ -1,33 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pins the built-in model
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
2
|
+
* Pins the built-in model against its sources and the contract:
|
|
3
|
+
* - its types are the files `fga.mod` lists, in that order, one type per
|
|
4
|
+
* file named by the file, and every one is bound (bindings.ts);
|
|
5
|
+
* - every binding's schema is the message `kind_meta` spells for the
|
|
6
|
+
* kind (`ai.stigmer.<group>.<name>.<version>.<Name>`), `platform`
|
|
7
|
+
* excepted by name as the one rowless type, so the explicit table
|
|
8
|
+
* cannot bind a kind to the wrong message;
|
|
9
|
+
* - every declaration names a `.fga` file that exists under fga/model;
|
|
10
|
+
* - the model declares every open-source-tier kind, and outside the tier
|
|
11
|
+
* exactly the four kinds the wider editions serve, so a kind the
|
|
12
|
+
* contract moves between tiers is a visible diff here;
|
|
13
|
+
* - a kind is reached by enum and by FGA type name alike;
|
|
14
|
+
* - the relations whose direct list admits a team (`team#member`) are
|
|
15
|
+
* exactly the roles the kind's `team_grantable_roles` names, a subset
|
|
16
|
+
* of what a person can be granted and never ownership, so the grant
|
|
17
|
+
* step and the model cannot disagree about where a team may be
|
|
18
|
+
* granted;
|
|
19
|
+
* - the derived rules are exactly the three relations `kind_meta` cannot
|
|
20
|
+
* derive.
|
|
13
21
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* set-equal to the `kind_meta.tier` open-source members (a kind the
|
|
17
|
-
* contract moves into or out of the tier is a visible diff here before
|
|
18
|
-
* it is a silent gap in enforcement).
|
|
22
|
+
* Whether the model defines what the wire asks is the whole contract's
|
|
23
|
+
* question, pinned in __tests__/wire-permissions.test.ts.
|
|
19
24
|
*/
|
|
25
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
26
|
+
import { fileURLToPath } from "node:url";
|
|
27
|
+
|
|
20
28
|
import { describe, expect, it } from "vitest";
|
|
21
29
|
|
|
30
|
+
import { ApiResourceGroup } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_group_pb";
|
|
22
31
|
import {
|
|
23
32
|
ApiResourceKind,
|
|
24
33
|
ApiResourceKindSchema,
|
|
34
|
+
ApiResourceVersion,
|
|
25
35
|
ResourceTier,
|
|
26
36
|
} from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
27
|
-
import {
|
|
28
|
-
IamPermissionSchema,
|
|
29
|
-
IamRole,
|
|
30
|
-
} from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
37
|
+
import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
31
38
|
|
|
32
39
|
import {
|
|
33
40
|
getKindMeta,
|
|
@@ -35,221 +42,40 @@ import {
|
|
|
35
42
|
kindEnumName,
|
|
36
43
|
teamGrantableRolesFor,
|
|
37
44
|
} from "../../../pipeline/apiresource-meta.js";
|
|
45
|
+
import { KIND_BINDINGS, ROWLESS } from "../bindings.js";
|
|
38
46
|
import { builtInModel, declarationFor } from "../index.js";
|
|
39
47
|
import type { Rewrite, SubjectType } from "../rewrite.js";
|
|
40
48
|
|
|
41
|
-
/** The
|
|
42
|
-
const
|
|
43
|
-
ApiResourceKind.identity_account,
|
|
44
|
-
ApiResourceKind.iam_policy,
|
|
45
|
-
ApiResourceKind.api_key,
|
|
46
|
-
ApiResourceKind.oauth_app,
|
|
47
|
-
ApiResourceKind.platform_client,
|
|
48
|
-
ApiResourceKind.organization,
|
|
49
|
-
ApiResourceKind.agent,
|
|
50
|
-
ApiResourceKind.agent_channel,
|
|
51
|
-
ApiResourceKind.agent_share,
|
|
52
|
-
ApiResourceKind.channel_app,
|
|
53
|
-
ApiResourceKind.agent_instance,
|
|
54
|
-
ApiResourceKind.agent_execution,
|
|
55
|
-
ApiResourceKind.artifact,
|
|
56
|
-
ApiResourceKind.environment,
|
|
57
|
-
ApiResourceKind.execution_context,
|
|
58
|
-
ApiResourceKind.mcp_server,
|
|
59
|
-
ApiResourceKind.memory,
|
|
60
|
-
ApiResourceKind.schedule,
|
|
61
|
-
ApiResourceKind.session,
|
|
62
|
-
ApiResourceKind.skill,
|
|
63
|
-
ApiResourceKind.workflow,
|
|
64
|
-
ApiResourceKind.workflow_instance,
|
|
65
|
-
ApiResourceKind.workflow_execution,
|
|
66
|
-
ApiResourceKind.plugin,
|
|
67
|
-
] as const;
|
|
49
|
+
/** The server package root, where fga/model lives. */
|
|
50
|
+
const PACKAGE_ROOT = new URL("../../../../", import.meta.url);
|
|
68
51
|
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
]
|
|
94
|
-
|
|
95
|
-
"can_view",
|
|
96
|
-
"can_edit",
|
|
97
|
-
"can_delete",
|
|
98
|
-
"can_grant_access",
|
|
99
|
-
"can_view_access",
|
|
100
|
-
],
|
|
101
|
-
oauth_app: [
|
|
102
|
-
"can_view",
|
|
103
|
-
"can_edit",
|
|
104
|
-
"can_delete",
|
|
105
|
-
"can_grant_access",
|
|
106
|
-
"can_view_access",
|
|
107
|
-
],
|
|
108
|
-
platform_client: [
|
|
109
|
-
"can_view",
|
|
110
|
-
"can_edit",
|
|
111
|
-
"can_delete",
|
|
112
|
-
"can_grant_access",
|
|
113
|
-
"can_view_access",
|
|
114
|
-
],
|
|
115
|
-
organization: [
|
|
116
|
-
"can_view",
|
|
117
|
-
"can_edit",
|
|
118
|
-
"can_delete",
|
|
119
|
-
"can_create_agent",
|
|
120
|
-
"can_create_workflow",
|
|
121
|
-
"can_create_session",
|
|
122
|
-
"can_create_environment",
|
|
123
|
-
"can_create_skill",
|
|
124
|
-
"can_create_plugin",
|
|
125
|
-
"can_create_mcp_server",
|
|
126
|
-
"can_create_idp",
|
|
127
|
-
"can_create_identity_account",
|
|
128
|
-
"can_create_oauth_app",
|
|
129
|
-
"can_create_platform_client",
|
|
130
|
-
"can_create_channel_app",
|
|
131
|
-
"can_create_execution_in",
|
|
132
|
-
"can_create_agent_share",
|
|
133
|
-
"can_create_agent_instance",
|
|
134
|
-
"can_create_team",
|
|
135
|
-
"can_grant_access",
|
|
136
|
-
"can_view_access",
|
|
137
|
-
"can_view_billing",
|
|
138
|
-
"can_manage_billing",
|
|
139
|
-
],
|
|
140
|
-
agent: [
|
|
141
|
-
"can_view",
|
|
142
|
-
"can_edit",
|
|
143
|
-
"can_delete",
|
|
144
|
-
"can_execute",
|
|
145
|
-
"can_create_instance",
|
|
146
|
-
"can_grant_access",
|
|
147
|
-
"can_view_access",
|
|
148
|
-
],
|
|
149
|
-
agent_channel: [
|
|
150
|
-
"can_view",
|
|
151
|
-
"can_edit",
|
|
152
|
-
"can_delete",
|
|
153
|
-
"can_participate",
|
|
154
|
-
"can_grant_access",
|
|
155
|
-
"can_view_access",
|
|
156
|
-
],
|
|
157
|
-
agent_share: [
|
|
158
|
-
"can_view",
|
|
159
|
-
"can_edit",
|
|
160
|
-
"can_delete",
|
|
161
|
-
"can_grant_access",
|
|
162
|
-
"can_view_access",
|
|
163
|
-
],
|
|
164
|
-
channel_app: [
|
|
165
|
-
"can_view",
|
|
166
|
-
"can_edit",
|
|
167
|
-
"can_delete",
|
|
168
|
-
"can_grant_access",
|
|
169
|
-
"can_view_access",
|
|
170
|
-
],
|
|
171
|
-
agent_instance: [
|
|
172
|
-
"can_view",
|
|
173
|
-
"can_execute",
|
|
174
|
-
"can_edit",
|
|
175
|
-
"can_delete",
|
|
176
|
-
"can_grant_access",
|
|
177
|
-
"can_view_access",
|
|
178
|
-
],
|
|
179
|
-
agent_execution: ["can_view", "can_edit"],
|
|
180
|
-
artifact: ["can_view", "can_edit"],
|
|
181
|
-
environment: [
|
|
182
|
-
"can_view",
|
|
183
|
-
"can_edit",
|
|
184
|
-
"can_delete",
|
|
185
|
-
"can_read_secrets",
|
|
186
|
-
"can_grant_access",
|
|
187
|
-
"can_view_access",
|
|
188
|
-
],
|
|
189
|
-
execution_context: ["can_view", "can_edit"],
|
|
190
|
-
mcp_server: [
|
|
191
|
-
"can_view",
|
|
192
|
-
"can_edit",
|
|
193
|
-
"can_delete",
|
|
194
|
-
"can_connect",
|
|
195
|
-
"can_grant_access",
|
|
196
|
-
"can_view_access",
|
|
197
|
-
],
|
|
198
|
-
memory: ["can_view", "can_edit", "can_delete"],
|
|
199
|
-
schedule: [
|
|
200
|
-
"can_view",
|
|
201
|
-
"can_edit",
|
|
202
|
-
"can_delete",
|
|
203
|
-
"can_grant_access",
|
|
204
|
-
"can_view_access",
|
|
205
|
-
],
|
|
206
|
-
session: [
|
|
207
|
-
"can_view",
|
|
208
|
-
"can_edit",
|
|
209
|
-
"can_delete",
|
|
210
|
-
"can_create_execution_in",
|
|
211
|
-
"can_grant_access",
|
|
212
|
-
"can_view_access",
|
|
213
|
-
],
|
|
214
|
-
skill: [
|
|
215
|
-
"can_view",
|
|
216
|
-
"can_edit",
|
|
217
|
-
"can_delete",
|
|
218
|
-
"can_grant_access",
|
|
219
|
-
"can_view_access",
|
|
220
|
-
],
|
|
221
|
-
workflow: [
|
|
222
|
-
"can_view",
|
|
223
|
-
"can_edit",
|
|
224
|
-
"can_delete",
|
|
225
|
-
"can_execute",
|
|
226
|
-
"can_grant_access",
|
|
227
|
-
"can_view_access",
|
|
228
|
-
],
|
|
229
|
-
plugin: [
|
|
230
|
-
"can_view",
|
|
231
|
-
"can_edit",
|
|
232
|
-
"can_delete",
|
|
233
|
-
"can_grant_access",
|
|
234
|
-
"can_view_access",
|
|
235
|
-
],
|
|
236
|
-
workflow_instance: [
|
|
237
|
-
"can_view",
|
|
238
|
-
"can_execute",
|
|
239
|
-
"can_edit",
|
|
240
|
-
"can_delete",
|
|
241
|
-
"can_grant_access",
|
|
242
|
-
"can_view_access",
|
|
243
|
-
],
|
|
244
|
-
workflow_execution: [
|
|
245
|
-
"can_view",
|
|
246
|
-
"can_edit",
|
|
247
|
-
"can_grant_access",
|
|
248
|
-
"can_view_access",
|
|
249
|
-
],
|
|
250
|
-
};
|
|
52
|
+
/** The kinds the model defines outside the open-source tier: the ones the wider editions serve. */
|
|
53
|
+
const WIDER_EDITION_KINDS: ReadonlyArray<ApiResourceKind> = [
|
|
54
|
+
ApiResourceKind.platform,
|
|
55
|
+
ApiResourceKind.identity_provider,
|
|
56
|
+
ApiResourceKind.invitation,
|
|
57
|
+
ApiResourceKind.team,
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
/** The files `fga.mod` lists, in its order. */
|
|
61
|
+
function modFiles(): ReadonlyArray<string> {
|
|
62
|
+
const text = readFileSync(fileURLToPath(new URL("fga/model/fga.mod", PACKAGE_ROOT)), "utf8");
|
|
63
|
+
return [...text.matchAll(/^\s*-\s*(\S+\.fga)\s*$/gm)].map((match) => match[1] ?? "");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The message `kind_meta` spells for a kind. */
|
|
67
|
+
function kindMetaMessageName(kind: ApiResourceKind): string {
|
|
68
|
+
const meta = getKindMeta(kind);
|
|
69
|
+
return [
|
|
70
|
+
"ai",
|
|
71
|
+
"stigmer",
|
|
72
|
+
ApiResourceGroup[meta.group],
|
|
73
|
+
meta.name.toLowerCase(),
|
|
74
|
+
ApiResourceVersion[meta.version],
|
|
75
|
+
meta.name,
|
|
76
|
+
].join(".");
|
|
77
|
+
}
|
|
251
78
|
|
|
252
|
-
/** The subject types a relation's direct lists name, wherever they sit in its rewrite. */
|
|
253
79
|
function directSubjects(rewrite: Rewrite): ReadonlyArray<SubjectType> {
|
|
254
80
|
switch (rewrite.node) {
|
|
255
81
|
case "this":
|
|
@@ -268,14 +94,10 @@ function directSubjects(rewrite: Rewrite): ReadonlyArray<SubjectType> {
|
|
|
268
94
|
}
|
|
269
95
|
|
|
270
96
|
function isTeamMembers(subject: SubjectType): boolean {
|
|
271
|
-
return
|
|
272
|
-
subject.form === "userset" &&
|
|
273
|
-
subject.type === "team" &&
|
|
274
|
-
subject.relation === "member"
|
|
275
|
-
);
|
|
97
|
+
return subject.form === "userset" && subject.type === "team" && subject.relation === "member";
|
|
276
98
|
}
|
|
277
99
|
|
|
278
|
-
/** Every kind whose `kind_meta.tier` is the open-source tier
|
|
100
|
+
/** Every kind whose `kind_meta.tier` is the open-source tier. */
|
|
279
101
|
function openSourceTierKinds(): ReadonlySet<ApiResourceKind> {
|
|
280
102
|
const kinds = new Set<ApiResourceKind>();
|
|
281
103
|
for (const value of ApiResourceKindSchema.values) {
|
|
@@ -290,59 +112,63 @@ function openSourceTierKinds(): ReadonlySet<ApiResourceKind> {
|
|
|
290
112
|
return kinds;
|
|
291
113
|
}
|
|
292
114
|
|
|
293
|
-
describe("the built-in model
|
|
294
|
-
it("
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
115
|
+
describe("the built-in model", () => {
|
|
116
|
+
it("defines one type per file fga.mod lists, named by the file, in fga.mod order, every one bound", () => {
|
|
117
|
+
const files = modFiles();
|
|
118
|
+
expect(files.length).toBeGreaterThan(0);
|
|
119
|
+
expect(builtInModel.declarations.map((d) => d.type)).toEqual(
|
|
120
|
+
files.map((file) => file.replace(/^.*\//, "").replace(/\.fga$/, "")),
|
|
121
|
+
);
|
|
122
|
+
expect(builtInModel.declarations.map((d) => d.source)).toEqual(
|
|
123
|
+
files.map((file) => `fga/model/${file}`),
|
|
124
|
+
);
|
|
125
|
+
expect([...KIND_BINDINGS.keys()].map(kindEnumName)).toEqual(
|
|
126
|
+
builtInModel.declarations.map((d) => d.type),
|
|
127
|
+
);
|
|
299
128
|
});
|
|
300
129
|
|
|
301
|
-
it("
|
|
302
|
-
for (const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
ApiResourceKind.invitation,
|
|
311
|
-
ApiResourceKind.team,
|
|
312
|
-
]) {
|
|
313
|
-
expect(declarationFor(unserved), kindEnumName(unserved)).toBeUndefined();
|
|
130
|
+
it("binds every kind to the message kind_meta spells, and platform alone to ROWLESS", () => {
|
|
131
|
+
for (const declaration of builtInModel.declarations) {
|
|
132
|
+
if (declaration.kind === ApiResourceKind.platform) {
|
|
133
|
+
expect(declaration.schema).toBe(ROWLESS);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
expect(declaration.schema?.typeName, declaration.type).toBe(
|
|
137
|
+
kindMetaMessageName(declaration.kind),
|
|
138
|
+
);
|
|
314
139
|
}
|
|
315
|
-
expect(builtInModel.byType("")).toBeUndefined();
|
|
316
140
|
});
|
|
317
141
|
|
|
318
|
-
it("names
|
|
142
|
+
it("names a .fga source that exists", () => {
|
|
319
143
|
for (const declaration of builtInModel.declarations) {
|
|
320
|
-
expect(
|
|
321
|
-
new
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
);
|
|
144
|
+
expect(
|
|
145
|
+
existsSync(fileURLToPath(new URL(declaration.source, PACKAGE_ROOT))),
|
|
146
|
+
declaration.source,
|
|
147
|
+
).toBe(true);
|
|
325
148
|
}
|
|
326
149
|
});
|
|
327
150
|
|
|
328
|
-
it("
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
151
|
+
it("defines every open-source-tier kind, and outside the tier exactly the kinds the wider editions serve", () => {
|
|
152
|
+
const declared = new Set(builtInModel.declarations.map((d) => d.kind));
|
|
153
|
+
const tier = openSourceTierKinds();
|
|
154
|
+
for (const kind of tier) {
|
|
155
|
+
expect(declared.has(kind), kindEnumName(kind)).toBe(true);
|
|
156
|
+
}
|
|
157
|
+
expect(
|
|
158
|
+
[...declared].filter((kind) => !tier.has(kind)).map(kindEnumName).sort(),
|
|
159
|
+
).toEqual(WIDER_EDITION_KINDS.map(kindEnumName).sort());
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("reaches a declaration by kind and by FGA type name", () => {
|
|
335
163
|
for (const declaration of builtInModel.declarations) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
);
|
|
339
|
-
expect(declaredWirePermissions, declaration.type).toEqual(
|
|
340
|
-
WIRE_PERMISSIONS_BY_TYPE[declaration.type],
|
|
341
|
-
);
|
|
164
|
+
expect(declarationFor(declaration.kind)).toBe(declaration);
|
|
165
|
+
expect(builtInModel.byType(kindEnumName(declaration.kind))).toBe(declaration);
|
|
342
166
|
}
|
|
167
|
+
expect(declarationFor(ApiResourceKind.api_resource_kind_unknown)).toBeUndefined();
|
|
168
|
+
expect(builtInModel.byType("")).toBeUndefined();
|
|
343
169
|
});
|
|
344
170
|
|
|
345
|
-
it("admits a team exactly on the roles each kind's team_grantable_roles lists — the
|
|
171
|
+
it("admits a team exactly on the roles each kind's team_grantable_roles lists — the model and the contract say one thing", () => {
|
|
346
172
|
for (const declaration of builtInModel.declarations) {
|
|
347
173
|
const admitsTeam = [...declaration.relations]
|
|
348
174
|
.filter(([, rewrite]) => directSubjects(rewrite).some(isTeamMembers))
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the compiled model cannot say about a type, and the evaluator needs:
|
|
3
|
+
* the message schema a stored row of the kind decodes with, and the
|
|
4
|
+
* relations `kind_meta.authorization` cannot derive from the row alone.
|
|
5
|
+
* One row per type of the model, in `fga.mod` order; model/index.ts joins
|
|
6
|
+
* this table with the compiled JSON and refuses, at load, a type with no
|
|
7
|
+
* binding, a binding with no type, and a derived rule for a relation the
|
|
8
|
+
* type does not define.
|
|
9
|
+
*
|
|
10
|
+
* The table is explicit rather than computed from `kind_meta`'s naming
|
|
11
|
+
* convention (`ai.stigmer.<group>.<name>.<version>.<Name>`): a lookup by
|
|
12
|
+
* name would need a registry holding every message and would hide a
|
|
13
|
+
* mistake behind a rule, and an explicit import is what the tree-shaken
|
|
14
|
+
* slim bundle wants. The convention holds for every row but `platform`,
|
|
15
|
+
* and model/__tests__/registry.test.ts pins the table against it.
|
|
16
|
+
*
|
|
17
|
+
* `platform` has no stored resource: it is the singleton the platform's
|
|
18
|
+
* own permissions hang off (`platform:stigmer`), and a check on it
|
|
19
|
+
* resolves over tuples alone. Its row is ROWLESS, so the table says so
|
|
20
|
+
* rather than leaving a hole; the tuple source never loads a row for it
|
|
21
|
+
* and the list scope never lists it.
|
|
22
|
+
*
|
|
23
|
+
* The three derived rules: `default_of` on both instance kinds, which the
|
|
24
|
+
* blueprint's default-instance pointer decides (default-of.ts), and a
|
|
25
|
+
* workflow instance's `execution_viewer`, which its execution visibility
|
|
26
|
+
* decides (execution-viewer.ts).
|
|
27
|
+
*/
|
|
28
|
+
import type { DescMessage } from "@bufbuild/protobuf";
|
|
29
|
+
|
|
30
|
+
import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
31
|
+
import { AgentChannelSchema } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/api_pb";
|
|
32
|
+
import { AgentExecutionSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
33
|
+
import { AgentInstanceSchema } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/api_pb";
|
|
34
|
+
import { AgentShareSchema } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/api_pb";
|
|
35
|
+
import { ArtifactSchema } from "@stigmer/protos/ai/stigmer/agentic/artifact/v1/api_pb";
|
|
36
|
+
import { ChannelAppSchema } from "@stigmer/protos/ai/stigmer/agentic/channelapp/v1/api_pb";
|
|
37
|
+
import { EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
|
|
38
|
+
import { ExecutionContextSchema } from "@stigmer/protos/ai/stigmer/agentic/executioncontext/v1/api_pb";
|
|
39
|
+
import { McpServerSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
40
|
+
import { MemorySchema } from "@stigmer/protos/ai/stigmer/agentic/memory/v1/api_pb";
|
|
41
|
+
import { PluginSchema } from "@stigmer/protos/ai/stigmer/agentic/plugin/v1/api_pb";
|
|
42
|
+
import { ScheduleSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
|
|
43
|
+
import { SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
44
|
+
import { SkillSchema } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
|
|
45
|
+
import { WorkflowSchema } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/api_pb";
|
|
46
|
+
import { WorkflowExecutionSchema } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/api_pb";
|
|
47
|
+
import { WorkflowInstanceSchema } from "@stigmer/protos/ai/stigmer/agentic/workflowinstance/v1/api_pb";
|
|
48
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
49
|
+
import { ApiKeySchema } from "@stigmer/protos/ai/stigmer/iam/apikey/v1/api_pb";
|
|
50
|
+
import { IamPolicySchema } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/api_pb";
|
|
51
|
+
import { IdentityAccountSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
52
|
+
import { IdentityProviderSchema } from "@stigmer/protos/ai/stigmer/iam/identityprovider/v1/api_pb";
|
|
53
|
+
import { InvitationSchema } from "@stigmer/protos/ai/stigmer/iam/invitation/v1/api_pb";
|
|
54
|
+
import { OAuthAppSchema } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/api_pb";
|
|
55
|
+
import { PlatformClientSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
56
|
+
import { TeamSchema } from "@stigmer/protos/ai/stigmer/iam/team/v1/api_pb";
|
|
57
|
+
import { OrganizationSchema } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/api_pb";
|
|
58
|
+
|
|
59
|
+
import { defaultOfBlueprint } from "./default-of.js";
|
|
60
|
+
import { executionViewer } from "./execution-viewer.js";
|
|
61
|
+
import type { DerivedRelation } from "./rewrite.js";
|
|
62
|
+
|
|
63
|
+
/** A type with no stored resource: it resolves over tuples alone (the module header). */
|
|
64
|
+
export const ROWLESS = undefined;
|
|
65
|
+
|
|
66
|
+
export interface KindBinding {
|
|
67
|
+
/** What a stored row decodes with, or ROWLESS. */
|
|
68
|
+
readonly schema: DescMessage | typeof ROWLESS;
|
|
69
|
+
/** The relations `kind_meta` cannot derive, by relation name. */
|
|
70
|
+
readonly derived?: Readonly<Record<string, DerivedRelation>>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Every type of the model, bound, in `fga.mod` order. */
|
|
74
|
+
export const KIND_BINDINGS: ReadonlyMap<ApiResourceKind, KindBinding> = new Map<
|
|
75
|
+
ApiResourceKind,
|
|
76
|
+
KindBinding
|
|
77
|
+
>([
|
|
78
|
+
[ApiResourceKind.platform, { schema: ROWLESS }],
|
|
79
|
+
[ApiResourceKind.identity_account, { schema: IdentityAccountSchema }],
|
|
80
|
+
[ApiResourceKind.identity_provider, { schema: IdentityProviderSchema }],
|
|
81
|
+
[ApiResourceKind.iam_policy, { schema: IamPolicySchema }],
|
|
82
|
+
[ApiResourceKind.api_key, { schema: ApiKeySchema }],
|
|
83
|
+
[ApiResourceKind.oauth_app, { schema: OAuthAppSchema }],
|
|
84
|
+
[ApiResourceKind.platform_client, { schema: PlatformClientSchema }],
|
|
85
|
+
[ApiResourceKind.invitation, { schema: InvitationSchema }],
|
|
86
|
+
[ApiResourceKind.team, { schema: TeamSchema }],
|
|
87
|
+
[ApiResourceKind.organization, { schema: OrganizationSchema }],
|
|
88
|
+
[ApiResourceKind.agent, { schema: AgentSchema }],
|
|
89
|
+
[ApiResourceKind.agent_channel, { schema: AgentChannelSchema }],
|
|
90
|
+
[ApiResourceKind.agent_share, { schema: AgentShareSchema }],
|
|
91
|
+
[ApiResourceKind.channel_app, { schema: ChannelAppSchema }],
|
|
92
|
+
[
|
|
93
|
+
ApiResourceKind.agent_instance,
|
|
94
|
+
{
|
|
95
|
+
schema: AgentInstanceSchema,
|
|
96
|
+
derived: {
|
|
97
|
+
default_of: defaultOfBlueprint({
|
|
98
|
+
kind: ApiResourceKind.agent,
|
|
99
|
+
schema: AgentSchema,
|
|
100
|
+
defaultInstanceIdOf: (agent) => agent.status?.defaultInstanceId ?? "",
|
|
101
|
+
}),
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
[ApiResourceKind.agent_execution, { schema: AgentExecutionSchema }],
|
|
106
|
+
[ApiResourceKind.artifact, { schema: ArtifactSchema }],
|
|
107
|
+
[ApiResourceKind.environment, { schema: EnvironmentSchema }],
|
|
108
|
+
[ApiResourceKind.execution_context, { schema: ExecutionContextSchema }],
|
|
109
|
+
[ApiResourceKind.mcp_server, { schema: McpServerSchema }],
|
|
110
|
+
[ApiResourceKind.memory, { schema: MemorySchema }],
|
|
111
|
+
[ApiResourceKind.plugin, { schema: PluginSchema }],
|
|
112
|
+
[ApiResourceKind.schedule, { schema: ScheduleSchema }],
|
|
113
|
+
[ApiResourceKind.session, { schema: SessionSchema }],
|
|
114
|
+
[ApiResourceKind.skill, { schema: SkillSchema }],
|
|
115
|
+
[ApiResourceKind.workflow, { schema: WorkflowSchema }],
|
|
116
|
+
[
|
|
117
|
+
ApiResourceKind.workflow_instance,
|
|
118
|
+
{
|
|
119
|
+
schema: WorkflowInstanceSchema,
|
|
120
|
+
derived: {
|
|
121
|
+
default_of: defaultOfBlueprint({
|
|
122
|
+
kind: ApiResourceKind.workflow,
|
|
123
|
+
schema: WorkflowSchema,
|
|
124
|
+
defaultInstanceIdOf: (workflow) => workflow.status?.defaultInstanceId ?? "",
|
|
125
|
+
}),
|
|
126
|
+
execution_viewer: executionViewer,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
[ApiResourceKind.workflow_execution, { schema: WorkflowExecutionSchema }],
|
|
131
|
+
]);
|