@stigmer/server 3.27.2 → 3.29.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 +3141 -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 +20 -3
- 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 +92 -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 +345 -277
- package/src/authorization/model/bindings.ts +131 -0
- package/src/authorization/model/data/authorization-model.json +3141 -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 +32 -4
- 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,265 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The OpenFGA store-test kit — runs a `.fga.yaml` store test (the format
|
|
3
|
-
* `fga model test` reads: fixture tuples, then named tests with `check`
|
|
4
|
-
* and `list_objects` assertions) against the built-in evaluator, so the
|
|
5
|
-
* cloud's own model tests — written by the model's authors and run
|
|
6
|
-
* against real OpenFGA in the cloud's CI — are the proof that this
|
|
7
|
-
* evaluator answers the same model the same way. Open source runs the
|
|
8
|
-
* kit over pinned copies of those documents (authorization/__tests__/
|
|
9
|
-
* fixtures/fga/); the cloud runs it over the LIVE documents at the
|
|
10
|
-
* re-pin, which is what makes the copies safe to hold.
|
|
11
|
-
*
|
|
12
|
-
* Shape: the port-contract kits' (store/port-contract.ts) — vitest-free,
|
|
13
|
-
* node:assert, cases the consumer's framework iterates — because a
|
|
14
|
-
* composition consumes it through the published barrel and vitest is a
|
|
15
|
-
* devDependency that must not enter the barrel's runtime graph.
|
|
16
|
-
*
|
|
17
|
-
* What is run and what is reported. One case per named test; a case
|
|
18
|
-
* asserts every `check` in the test whose object's kind the model
|
|
19
|
-
* declares, relation by relation, and FAILS on the first disagreement
|
|
20
|
-
* (the message names the check in the document's own words). Assertions
|
|
21
|
-
* the kit does not run are returned as `skipped`, each with its reason,
|
|
22
|
-
* so a consumer pins the list and a document that gains a scenario, or a
|
|
23
|
-
* declaration that lands, is a visible diff and never a quietly smaller
|
|
24
|
-
* proof. Three reasons: a check whose TARGET kind the model does not
|
|
25
|
-
* declare (`undeclared-kind`) and every `list_objects` assertion
|
|
26
|
-
* (`list-objects`, the list scope's proof) are known when the kit is
|
|
27
|
-
* built; the third is known only from the walk. A document may grant
|
|
28
|
-
* through a type the model does not declare — the cloud's platform
|
|
29
|
-
* tenancy reaches people through `identity_provider:<idp>#platform_user`,
|
|
30
|
-
* a kind this edition does not serve — and OpenFGA answers `true` where
|
|
31
|
-
* a model without that type resolves the userset to nobody. The kit runs
|
|
32
|
-
* every assertion over a recording view of the document's tuples, and an
|
|
33
|
-
* assertion whose walk READ a tuple naming an undeclared type is
|
|
34
|
-
* reported as `undeclared-subject-type` (the types named) instead of
|
|
35
|
-
* being asserted, whatever it would have answered: decided from the
|
|
36
|
-
* model and the data, per assertion, so the sibling arms of the same
|
|
37
|
-
* check block still run and a union that is settled before it reaches
|
|
38
|
-
* such a tuple runs too. Over a model that declares every type in the
|
|
39
|
-
* file (the cloud's drift test, built from the live model) nothing is
|
|
40
|
-
* recorded and everything runs — the same kit, no edition branch.
|
|
41
|
-
* `skipped` is therefore complete once every case has run; a consumer
|
|
42
|
-
* pins it after the cases, which is the order a test file declares them.
|
|
43
|
-
*
|
|
44
|
-
* The parser is strict on purpose: an unknown key anywhere is a thrown
|
|
45
|
-
* fault, so a change to the format upstream is loud here rather than
|
|
46
|
-
* half-run. The model declares no condition, so the format's `condition`
|
|
47
|
-
* on a tuple and `context` on a check are among the keys refused: a
|
|
48
|
-
* document that still carries them is written against a model this
|
|
49
|
-
* evaluator does not answer, and saying so beats running it half-blind.
|
|
50
|
-
*/
|
|
51
|
-
import assert from "node:assert/strict";
|
|
52
|
-
import { checkRelation } from "./evaluator.js";
|
|
53
|
-
import { ACCOUNT_TYPE, newInMemoryTupleSource, parseObjectRef, parseSubject, } from "./tuples.js";
|
|
54
|
-
/**
|
|
55
|
-
* Parses a loaded YAML value into a document, refusing anything the
|
|
56
|
-
* format the cloud's files use does not carry (`sourceName` names the
|
|
57
|
-
* file in every message).
|
|
58
|
-
*/
|
|
59
|
-
export function parseStoreTestDocument(value, sourceName) {
|
|
60
|
-
const root = record(value, sourceName, [
|
|
61
|
-
"name",
|
|
62
|
-
"model_file",
|
|
63
|
-
"tuples",
|
|
64
|
-
"tests",
|
|
65
|
-
]);
|
|
66
|
-
return {
|
|
67
|
-
name: text(root["name"], `${sourceName}: name`),
|
|
68
|
-
tuples: list(root["tuples"], `${sourceName}: tuples`).map((entry, index) => parseTuple(entry, `${sourceName}: tuples[${index}]`)),
|
|
69
|
-
tests: list(root["tests"], `${sourceName}: tests`).map((entry, index) => parseTest(entry, `${sourceName}: tests[${index}]`)),
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function parseTuple(value, where) {
|
|
73
|
-
const entry = record(value, where, ["user", "relation", "object"]);
|
|
74
|
-
return {
|
|
75
|
-
user: text(entry["user"], `${where}.user`),
|
|
76
|
-
relation: text(entry["relation"], `${where}.relation`),
|
|
77
|
-
object: text(entry["object"], `${where}.object`),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function parseTest(value, where) {
|
|
81
|
-
const entry = record(value, where, ["name", "check", "list_objects"]);
|
|
82
|
-
return {
|
|
83
|
-
name: text(entry["name"], `${where}.name`),
|
|
84
|
-
check: optionalList(entry["check"], `${where}.check`).map((item, index) => parseCheck(item, `${where}.check[${index}]`)),
|
|
85
|
-
list_objects: optionalList(entry["list_objects"], `${where}.list_objects`).map((item, index) => parseListObjects(item, `${where}.list_objects[${index}]`)),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function parseCheck(value, where) {
|
|
89
|
-
const entry = record(value, where, ["user", "object", "assertions"]);
|
|
90
|
-
const assertions = record(entry["assertions"], `${where}.assertions`);
|
|
91
|
-
const parsed = {};
|
|
92
|
-
for (const [relation, expected] of Object.entries(assertions)) {
|
|
93
|
-
if (typeof expected !== "boolean") {
|
|
94
|
-
throw new Error(`${where}.assertions.${relation}: expected a boolean`);
|
|
95
|
-
}
|
|
96
|
-
parsed[relation] = expected;
|
|
97
|
-
}
|
|
98
|
-
return {
|
|
99
|
-
user: text(entry["user"], `${where}.user`),
|
|
100
|
-
object: text(entry["object"], `${where}.object`),
|
|
101
|
-
assertions: parsed,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function parseListObjects(value, where) {
|
|
105
|
-
const entry = record(value, where, ["user", "type", "assertions"]);
|
|
106
|
-
const assertions = record(entry["assertions"], `${where}.assertions`);
|
|
107
|
-
const parsed = {};
|
|
108
|
-
for (const [relation, expected] of Object.entries(assertions)) {
|
|
109
|
-
parsed[relation] = list(expected, `${where}.assertions.${relation}`).map((item, index) => text(item, `${where}.assertions.${relation}[${index}]`));
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
user: text(entry["user"], `${where}.user`),
|
|
113
|
-
type: text(entry["type"], `${where}.type`),
|
|
114
|
-
assertions: parsed,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
function record(value, where, allowedKeys) {
|
|
118
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
119
|
-
throw new Error(`${where}: expected a mapping`);
|
|
120
|
-
}
|
|
121
|
-
const entry = value;
|
|
122
|
-
if (allowedKeys !== undefined) {
|
|
123
|
-
for (const key of Object.keys(entry)) {
|
|
124
|
-
if (!allowedKeys.includes(key)) {
|
|
125
|
-
throw new Error(`${where}: unknown key '${key}'`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return entry;
|
|
130
|
-
}
|
|
131
|
-
function list(value, where) {
|
|
132
|
-
if (!Array.isArray(value)) {
|
|
133
|
-
throw new Error(`${where}: expected a list`);
|
|
134
|
-
}
|
|
135
|
-
return value;
|
|
136
|
-
}
|
|
137
|
-
function optionalList(value, where) {
|
|
138
|
-
return value === undefined ? [] : list(value, where);
|
|
139
|
-
}
|
|
140
|
-
function text(value, where) {
|
|
141
|
-
if (typeof value !== "string") {
|
|
142
|
-
throw new Error(`${where}: expected a string`);
|
|
143
|
-
}
|
|
144
|
-
return value;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* The document's tests as runnable cases over `model`, plus every
|
|
148
|
-
* assertion group the kit does not run.
|
|
149
|
-
*/
|
|
150
|
-
export function storeTestCases(document, model) {
|
|
151
|
-
const source = newInMemoryTupleSource(document.tuples.map(tupleOf));
|
|
152
|
-
const skipped = [];
|
|
153
|
-
const cases = [];
|
|
154
|
-
for (const test of document.tests) {
|
|
155
|
-
const runnable = [];
|
|
156
|
-
for (const item of test.check) {
|
|
157
|
-
const object = parseObjectRef(item.object);
|
|
158
|
-
if (model.byType(object.type) === undefined) {
|
|
159
|
-
skipped.push({
|
|
160
|
-
document: document.name,
|
|
161
|
-
test: test.name,
|
|
162
|
-
subject: item.user,
|
|
163
|
-
object: item.object,
|
|
164
|
-
reason: "undeclared-kind",
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
runnable.push(item);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
for (const item of test.list_objects) {
|
|
172
|
-
skipped.push({
|
|
173
|
-
document: document.name,
|
|
174
|
-
test: test.name,
|
|
175
|
-
subject: item.user,
|
|
176
|
-
object: `<${item.type}>`,
|
|
177
|
-
reason: "list-objects",
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
if (runnable.length === 0) {
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
cases.push({
|
|
184
|
-
name: `${document.name} :: ${test.name}`,
|
|
185
|
-
async run() {
|
|
186
|
-
for (const item of runnable) {
|
|
187
|
-
const object = parseObjectRef(item.object);
|
|
188
|
-
const person = personOf(item.user);
|
|
189
|
-
for (const [relation, expected] of Object.entries(item.assertions)) {
|
|
190
|
-
const recording = recordUndeclaredTypes(source, model);
|
|
191
|
-
const actual = await checkRelation({ model, source: recording }, object, relation, person);
|
|
192
|
-
if (recording.reached.size > 0) {
|
|
193
|
-
skipped.push({
|
|
194
|
-
document: document.name,
|
|
195
|
-
test: test.name,
|
|
196
|
-
subject: item.user,
|
|
197
|
-
object: item.object,
|
|
198
|
-
relation,
|
|
199
|
-
reason: "undeclared-subject-type",
|
|
200
|
-
types: [...recording.reached].sort(),
|
|
201
|
-
});
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
assert.equal(actual, expected, `${document.name} :: ${test.name}: ${item.user} ${relation} ${item.object} expected ${String(expected)}, got ${String(actual)}`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return { cases, skipped };
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* A view of `inner` that records, for one walk, every subject type the
|
|
214
|
-
* evaluator read that `model` does not declare. A person
|
|
215
|
-
* (`identity_account:<id>`) is a subject the evaluator compares, never a
|
|
216
|
-
* type it resolves, so it is not a "reach" whatever the model declares; a
|
|
217
|
-
* userset or a parent object of an undeclared type is.
|
|
218
|
-
*/
|
|
219
|
-
function recordUndeclaredTypes(inner, model) {
|
|
220
|
-
const reached = new Set();
|
|
221
|
-
return {
|
|
222
|
-
reached,
|
|
223
|
-
async tuplesOf(object, relation) {
|
|
224
|
-
const tuples = await inner.tuplesOf(object, relation);
|
|
225
|
-
for (const tuple of tuples) {
|
|
226
|
-
const type = resolvedTypeOf(tuple.subject);
|
|
227
|
-
if (type !== undefined && model.byType(type) === undefined) {
|
|
228
|
-
reached.add(type);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return tuples;
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
/** The type the evaluator would resolve a subject on, or undefined for a person. */
|
|
236
|
-
function resolvedTypeOf(subject) {
|
|
237
|
-
switch (subject.form) {
|
|
238
|
-
case "object":
|
|
239
|
-
return subject.object.type === ACCOUNT_TYPE
|
|
240
|
-
? undefined
|
|
241
|
-
: subject.object.type;
|
|
242
|
-
case "userset":
|
|
243
|
-
return subject.object.type;
|
|
244
|
-
default: {
|
|
245
|
-
const exhaustive = subject;
|
|
246
|
-
throw new Error(`unknown subject form: ${JSON.stringify(exhaustive)}`);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
function tupleOf(entry) {
|
|
251
|
-
return {
|
|
252
|
-
object: parseObjectRef(entry.object),
|
|
253
|
-
relation: entry.relation,
|
|
254
|
-
subject: parseSubject(entry.user),
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
/** The document's users are plain accounts; a user of another type is a format the kit does not run. */
|
|
258
|
-
function personOf(user) {
|
|
259
|
-
const object = parseObjectRef(user);
|
|
260
|
-
if (object.type !== ACCOUNT_TYPE || object.id === "*") {
|
|
261
|
-
throw new Error(`store test users are accounts; got '${user}'`);
|
|
262
|
-
}
|
|
263
|
-
return { accountId: object.id, aliases: new Set([object.id]) };
|
|
264
|
-
}
|
|
265
|
-
//# sourceMappingURL=store-test-kit.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store-test-kit.js","sourceRoot":"","sources":["../../src/authorization/store-test-kit.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Enterprise team type as the tests evaluate it: a transcript of
|
|
3
|
-
* fga/model/iam/team.fga in the shape of every open-source transcript
|
|
4
|
-
* (`../model/*.ts`), and a model that is the built-in one plus that
|
|
5
|
-
* declaration. Open source serves no team — the kind's tier is
|
|
6
|
-
* enterprise, so `builtInModel` declares none — yet its transcripts
|
|
7
|
-
* already name the team grant (`agent`'s `viewer` accepts
|
|
8
|
-
* `team#member`), and the derived tuple source reads the grants made to
|
|
9
|
-
* a person's teams. These fixtures let the source's tests and the list
|
|
10
|
-
* scope's cost measurement evaluate that path over real rows without
|
|
11
|
-
* declaring the kind in the edition that does not serve it.
|
|
12
|
-
*
|
|
13
|
-
* The membership line is the model's one intersection: a member is a
|
|
14
|
-
* person granted the role AND still one of the organization's viewers, so
|
|
15
|
-
* leaving the organization ends every team-derived grant with no cleanup.
|
|
16
|
-
* Guests hold `organization#guest`, never viewer, so a guest is never a
|
|
17
|
-
* member.
|
|
18
|
-
*/
|
|
19
|
-
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
20
|
-
import { TeamSchema } from "@stigmer/protos/ai/stigmer/iam/team/v1/api_pb";
|
|
21
|
-
|
|
22
|
-
import type { Model } from "../model/index.js";
|
|
23
|
-
import { builtInModel, newModel } from "../model/index.js";
|
|
24
|
-
import {
|
|
25
|
-
computed,
|
|
26
|
-
declareKind,
|
|
27
|
-
direct,
|
|
28
|
-
from,
|
|
29
|
-
intersection,
|
|
30
|
-
objectOf,
|
|
31
|
-
} from "../model/rewrite.js";
|
|
32
|
-
|
|
33
|
-
export const teamDeclaration = declareKind({
|
|
34
|
-
kind: ApiResourceKind.team,
|
|
35
|
-
schema: TeamSchema,
|
|
36
|
-
source: "fga/model/iam/team.fga",
|
|
37
|
-
relations: [
|
|
38
|
-
["organization", direct(objectOf("organization"))],
|
|
39
|
-
[
|
|
40
|
-
"member",
|
|
41
|
-
intersection(
|
|
42
|
-
direct(objectOf("identity_account")),
|
|
43
|
-
from("viewer", "organization"),
|
|
44
|
-
),
|
|
45
|
-
],
|
|
46
|
-
["viewer", from("viewer", "organization")],
|
|
47
|
-
["can_view", computed("viewer")],
|
|
48
|
-
["can_edit", from("admin", "organization")],
|
|
49
|
-
["can_delete", from("admin", "organization")],
|
|
50
|
-
["can_grant_access", from("admin", "organization")],
|
|
51
|
-
["can_view_access", computed("viewer")],
|
|
52
|
-
],
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
/** The built-in declarations and the team type; the evaluator reaches them by kind and type, so their order carries nothing. */
|
|
56
|
-
export const enterpriseModel: Model = newModel([
|
|
57
|
-
...builtInModel.declarations,
|
|
58
|
-
teamDeclaration,
|
|
59
|
-
]);
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# Pinned copy of stigmer-cloud backend/services/stigmer-server/fga/tests/agent-channel-owner.fga.yaml
|
|
2
|
-
# at commit b87dd1170 (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
|
-
# Agent channels are owner-scoped connection config (channel-integrations
|
|
6
|
-
# decision 001, cloned from the agent_share model): the creator owns the
|
|
7
|
-
# channel; view/edit/delete/install require ownership or an explicit grant.
|
|
8
|
-
# Plain org members get NO implicit access, and — critically — no
|
|
9
|
-
# workspace-visitor tuples exist at all: workspace-user admission to the
|
|
10
|
-
# channel runtime is app-level (webhook signature + channel caller identity
|
|
11
|
-
# + per-turn gates), never FGA.
|
|
12
|
-
#
|
|
13
|
-
# Org ADMINS inherit owner (T08, consistent with agents and shares — an
|
|
14
|
-
# admin who can edit the agent can manage its distribution channels). The
|
|
15
|
-
# narrowness these tests pin: owner + admins have control, granted viewers
|
|
16
|
-
# read, plain members have nothing.
|
|
17
|
-
#
|
|
18
|
-
# Run: fga model test --tests agent-channel-owner.fga.yaml
|
|
19
|
-
|
|
20
|
-
name: agent-channel-owner
|
|
21
|
-
model_file: ../model/fga.mod
|
|
22
|
-
|
|
23
|
-
tuples:
|
|
24
|
-
# Org membership for both accounts — proving membership grants nothing.
|
|
25
|
-
- user: identity_account:alice
|
|
26
|
-
relation: member
|
|
27
|
-
object: organization:acme
|
|
28
|
-
- user: identity_account:mallory
|
|
29
|
-
relation: member
|
|
30
|
-
object: organization:acme
|
|
31
|
-
|
|
32
|
-
# Org admin — proving T08 inheritance reaches channels.
|
|
33
|
-
- user: identity_account:ana
|
|
34
|
-
relation: admin
|
|
35
|
-
object: organization:acme
|
|
36
|
-
|
|
37
|
-
# The channel, created by alice (the config-driven create tuples).
|
|
38
|
-
- user: organization:acme
|
|
39
|
-
relation: organization
|
|
40
|
-
object: agent_channel:support-bot-slack
|
|
41
|
-
- user: identity_account:alice
|
|
42
|
-
relation: owner
|
|
43
|
-
object: agent_channel:support-bot-slack
|
|
44
|
-
|
|
45
|
-
# An explicit viewer grant to carol (not even an org member).
|
|
46
|
-
- user: identity_account:carol
|
|
47
|
-
relation: viewer
|
|
48
|
-
object: agent_channel:support-bot-slack
|
|
49
|
-
|
|
50
|
-
tests:
|
|
51
|
-
- name: owner has full control including grant management
|
|
52
|
-
check:
|
|
53
|
-
- user: identity_account:alice
|
|
54
|
-
object: agent_channel:support-bot-slack
|
|
55
|
-
assertions:
|
|
56
|
-
can_view: true
|
|
57
|
-
can_edit: true
|
|
58
|
-
can_delete: true
|
|
59
|
-
can_grant_access: true
|
|
60
|
-
can_view_access: true
|
|
61
|
-
|
|
62
|
-
- name: explicitly granted viewer can read but not mutate
|
|
63
|
-
check:
|
|
64
|
-
- user: identity_account:carol
|
|
65
|
-
object: agent_channel:support-bot-slack
|
|
66
|
-
assertions:
|
|
67
|
-
can_view: true
|
|
68
|
-
can_edit: false
|
|
69
|
-
can_delete: false
|
|
70
|
-
can_grant_access: false
|
|
71
|
-
can_view_access: true
|
|
72
|
-
|
|
73
|
-
- name: fellow org member has no implicit access
|
|
74
|
-
check:
|
|
75
|
-
- user: identity_account:mallory
|
|
76
|
-
object: agent_channel:support-bot-slack
|
|
77
|
-
assertions:
|
|
78
|
-
can_view: false
|
|
79
|
-
can_edit: false
|
|
80
|
-
can_delete: false
|
|
81
|
-
can_grant_access: false
|
|
82
|
-
can_view_access: false
|
|
83
|
-
|
|
84
|
-
- name: org admin inherits channel management (T08)
|
|
85
|
-
check:
|
|
86
|
-
- user: identity_account:ana
|
|
87
|
-
object: agent_channel:support-bot-slack
|
|
88
|
-
assertions:
|
|
89
|
-
can_view: true
|
|
90
|
-
can_edit: true
|
|
91
|
-
can_delete: true
|
|
92
|
-
can_grant_access: true
|
|
93
|
-
|
|
94
|
-
- name: listing channels reflects ownership and grants, not membership
|
|
95
|
-
list_objects:
|
|
96
|
-
- user: identity_account:alice
|
|
97
|
-
type: agent_channel
|
|
98
|
-
assertions:
|
|
99
|
-
can_view:
|
|
100
|
-
- agent_channel:support-bot-slack
|
|
101
|
-
can_edit:
|
|
102
|
-
- agent_channel:support-bot-slack
|
|
103
|
-
- user: identity_account:carol
|
|
104
|
-
type: agent_channel
|
|
105
|
-
assertions:
|
|
106
|
-
can_view:
|
|
107
|
-
- agent_channel:support-bot-slack
|
|
108
|
-
can_edit: []
|
|
109
|
-
- user: identity_account:mallory
|
|
110
|
-
type: agent_channel
|
|
111
|
-
assertions:
|
|
112
|
-
can_view: []
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
# Pinned copy of stigmer-cloud backend/services/stigmer-server/fga/tests/agent-instance-creation.fga.yaml
|
|
2
|
-
# as changed by stigmer-cloud#765 (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 platform-visible agent lives in the
|
|
12
|
-
# caller's organization (the tenant-family case), so the agent's permission
|
|
13
|
-
# alone 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 tenant-family case passes on the caller's own
|
|
19
|
-
# organization while the agent half comes from the platform_viewer grant.
|
|
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
|
-
# acme owns identity_provider:idp1, which manages consumer: the two are
|
|
51
|
-
# one tenant family, the audience a platform-visible agent reaches.
|
|
52
|
-
- user: organization:acme
|
|
53
|
-
relation: organization
|
|
54
|
-
object: identity_provider:idp1
|
|
55
|
-
- user: organization:consumer
|
|
56
|
-
relation: managed_org
|
|
57
|
-
object: identity_provider:idp1
|
|
58
|
-
|
|
59
|
-
# An ORG-visible agent in acme, authored by oscar.
|
|
60
|
-
- user: organization:acme
|
|
61
|
-
relation: organization
|
|
62
|
-
object: agent:team-bot
|
|
63
|
-
- user: identity_account:oscar
|
|
64
|
-
relation: owner
|
|
65
|
-
object: agent:team-bot
|
|
66
|
-
- user: organization:acme#viewer
|
|
67
|
-
relation: viewer
|
|
68
|
-
object: agent:team-bot
|
|
69
|
-
|
|
70
|
-
# A PRIVATE agent in acme, authored by oscar (no visibility tuple).
|
|
71
|
-
- user: organization:acme
|
|
72
|
-
relation: organization
|
|
73
|
-
object: agent:secret-bot
|
|
74
|
-
- user: identity_account:oscar
|
|
75
|
-
relation: owner
|
|
76
|
-
object: agent:secret-bot
|
|
77
|
-
|
|
78
|
-
# A PLATFORM-visible agent in acme (the platform_viewer grant plus the
|
|
79
|
-
# org floor tuple the visibility writer emits).
|
|
80
|
-
- user: organization:acme
|
|
81
|
-
relation: organization
|
|
82
|
-
object: agent:open-bot
|
|
83
|
-
- user: identity_account:oscar
|
|
84
|
-
relation: owner
|
|
85
|
-
object: agent:open-bot
|
|
86
|
-
- user: identity_provider:idp1#platform_user
|
|
87
|
-
relation: platform_viewer
|
|
88
|
-
object: agent:open-bot
|
|
89
|
-
- user: organization:acme#viewer
|
|
90
|
-
relation: viewer
|
|
91
|
-
object: agent:open-bot
|
|
92
|
-
|
|
93
|
-
tests:
|
|
94
|
-
- name: owners, admins and members hold the organization half
|
|
95
|
-
check:
|
|
96
|
-
- user: identity_account:olivia
|
|
97
|
-
object: organization:acme
|
|
98
|
-
assertions:
|
|
99
|
-
can_create_agent_instance: true
|
|
100
|
-
- user: identity_account:oscar
|
|
101
|
-
object: organization:acme
|
|
102
|
-
assertions:
|
|
103
|
-
can_create_agent_instance: true
|
|
104
|
-
- user: identity_account:dave
|
|
105
|
-
object: organization:acme
|
|
106
|
-
assertions:
|
|
107
|
-
can_create_agent_instance: true
|
|
108
|
-
|
|
109
|
-
- name: a viewer, a guest and an outsider do not
|
|
110
|
-
check:
|
|
111
|
-
- user: identity_account:vera
|
|
112
|
-
object: organization:acme
|
|
113
|
-
assertions:
|
|
114
|
-
can_create_agent_instance: false
|
|
115
|
-
can_create_session: false
|
|
116
|
-
- user: identity_account:greta
|
|
117
|
-
object: organization:acme
|
|
118
|
-
assertions:
|
|
119
|
-
can_create_agent_instance: false
|
|
120
|
-
can_create_session: true
|
|
121
|
-
- user: identity_account:mia
|
|
122
|
-
object: organization:acme
|
|
123
|
-
assertions:
|
|
124
|
-
can_create_agent_instance: false
|
|
125
|
-
|
|
126
|
-
- name: a member instantiates an org-visible agent, both halves held
|
|
127
|
-
check:
|
|
128
|
-
- user: identity_account:dave
|
|
129
|
-
object: agent:team-bot
|
|
130
|
-
assertions:
|
|
131
|
-
can_create_instance: true
|
|
132
|
-
can_execute: true
|
|
133
|
-
|
|
134
|
-
- name: a viewer may run the org-visible agent and still cannot instantiate it here
|
|
135
|
-
check:
|
|
136
|
-
- user: identity_account:vera
|
|
137
|
-
object: agent:team-bot
|
|
138
|
-
assertions:
|
|
139
|
-
can_create_instance: true
|
|
140
|
-
- user: identity_account:vera
|
|
141
|
-
object: organization:acme
|
|
142
|
-
assertions:
|
|
143
|
-
can_create_agent_instance: false
|
|
144
|
-
|
|
145
|
-
- name: a private agent gives the agent half to its author and the admins only
|
|
146
|
-
check:
|
|
147
|
-
- user: identity_account:oscar
|
|
148
|
-
object: agent:secret-bot
|
|
149
|
-
assertions:
|
|
150
|
-
can_create_instance: true
|
|
151
|
-
- user: identity_account:olivia
|
|
152
|
-
object: agent:secret-bot
|
|
153
|
-
assertions:
|
|
154
|
-
can_create_instance: true
|
|
155
|
-
- user: identity_account:dave
|
|
156
|
-
object: agent:secret-bot
|
|
157
|
-
assertions:
|
|
158
|
-
can_create_instance: false
|
|
159
|
-
- user: identity_account:mia
|
|
160
|
-
object: agent:secret-bot
|
|
161
|
-
assertions:
|
|
162
|
-
can_create_instance: false
|
|
163
|
-
|
|
164
|
-
- name: the tenant-family case, the agent half from platform_viewer and the organization half at home
|
|
165
|
-
check:
|
|
166
|
-
- user: identity_account:mia
|
|
167
|
-
object: agent:open-bot
|
|
168
|
-
assertions:
|
|
169
|
-
can_create_instance: true
|
|
170
|
-
- user: identity_account:mia
|
|
171
|
-
object: organization:consumer
|
|
172
|
-
assertions:
|
|
173
|
-
can_create_agent_instance: true
|
|
174
|
-
- user: identity_account:mia
|
|
175
|
-
object: organization:acme
|
|
176
|
-
assertions:
|
|
177
|
-
can_create_agent_instance: false
|