@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.
Files changed (227) hide show
  1. package/README.md +2 -0
  2. package/dist/authorization/authorizer.d.ts +3 -3
  3. package/dist/authorization/authorizer.js +3 -3
  4. package/dist/authorization/derived-tuples.js +6 -1
  5. package/dist/authorization/derived-tuples.js.map +1 -1
  6. package/dist/authorization/evaluator.d.ts +9 -10
  7. package/dist/authorization/evaluator.d.ts.map +1 -1
  8. package/dist/authorization/evaluator.js.map +1 -1
  9. package/dist/authorization/list-read-scope.d.ts.map +1 -1
  10. package/dist/authorization/list-read-scope.js +29 -18
  11. package/dist/authorization/list-read-scope.js.map +1 -1
  12. package/dist/authorization/model/bindings.d.ts +41 -0
  13. package/dist/authorization/model/bindings.d.ts.map +1 -0
  14. package/dist/authorization/model/bindings.js +89 -0
  15. package/dist/authorization/model/bindings.js.map +1 -0
  16. package/dist/authorization/model/data/authorization-model.json +3141 -0
  17. package/dist/authorization/model/default-of.d.ts +2 -2
  18. package/dist/authorization/model/execution-viewer.d.ts +3 -0
  19. package/dist/authorization/model/execution-viewer.d.ts.map +1 -0
  20. package/dist/authorization/model/execution-viewer.js +50 -0
  21. package/dist/authorization/model/execution-viewer.js.map +1 -0
  22. package/dist/authorization/model/index.d.ts +33 -21
  23. package/dist/authorization/model/index.d.ts.map +1 -1
  24. package/dist/authorization/model/index.js +74 -52
  25. package/dist/authorization/model/index.js.map +1 -1
  26. package/dist/authorization/model/openfga-json.d.ts +18 -0
  27. package/dist/authorization/model/openfga-json.d.ts.map +1 -0
  28. package/dist/authorization/model/openfga-json.js +266 -0
  29. package/dist/authorization/model/openfga-json.js.map +1 -0
  30. package/dist/authorization/model/rewrite.d.ts +39 -67
  31. package/dist/authorization/model/rewrite.d.ts.map +1 -1
  32. package/dist/authorization/model/rewrite.js +1 -117
  33. package/dist/authorization/model/rewrite.js.map +1 -1
  34. package/dist/authorization/strict-json.d.ts +20 -0
  35. package/dist/authorization/strict-json.d.ts.map +1 -0
  36. package/dist/authorization/strict-json.js +45 -0
  37. package/dist/authorization/strict-json.js.map +1 -0
  38. package/dist/boot/compose.d.ts.map +1 -1
  39. package/dist/boot/compose.js +9 -7
  40. package/dist/boot/compose.js.map +1 -1
  41. package/dist/domain/workflowexecution/list-index.d.ts +1 -1
  42. package/dist/extensions/list-read-scope.d.ts +20 -3
  43. package/dist/extensions/list-read-scope.d.ts.map +1 -1
  44. package/dist/extensions/list-read-scope.js +20 -1
  45. package/dist/extensions/list-read-scope.js.map +1 -1
  46. package/dist/index.d.ts +7 -8
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +15 -5
  49. package/dist/index.js.map +1 -1
  50. package/package.json +7 -6
  51. package/src/authorization/README.md +41 -34
  52. package/src/authorization/__tests__/authorizer.test.ts +5 -14
  53. package/src/authorization/__tests__/derived-tuples.test.ts +29 -27
  54. package/src/authorization/__tests__/evaluator.test.ts +53 -160
  55. package/src/authorization/__tests__/facts.test.ts +5 -11
  56. package/src/authorization/__tests__/list-read-scope.measure.test.ts +12 -20
  57. package/src/authorization/__tests__/list-read-scope.test.ts +15 -14
  58. package/src/authorization/__tests__/organization-directory.test.ts +2 -2
  59. package/src/authorization/__tests__/store-test-kit.ts +246 -0
  60. package/src/authorization/__tests__/store-tests.test.ts +92 -223
  61. package/src/authorization/__tests__/support.ts +30 -2
  62. package/src/authorization/__tests__/throwaway-model.ts +75 -0
  63. package/src/authorization/__tests__/wire-permissions.test.ts +141 -107
  64. package/src/authorization/authorizer.ts +3 -3
  65. package/src/authorization/derived-tuples.ts +7 -2
  66. package/src/authorization/evaluator.ts +8 -10
  67. package/src/authorization/list-read-scope.ts +37 -22
  68. package/src/authorization/model/__tests__/openfga-json.test.ts +353 -0
  69. package/src/authorization/model/__tests__/registry.test.ts +345 -277
  70. package/src/authorization/model/bindings.ts +131 -0
  71. package/src/authorization/model/data/authorization-model.json +3141 -0
  72. package/src/authorization/model/default-of.ts +2 -2
  73. package/src/authorization/model/execution-viewer.ts +56 -0
  74. package/src/authorization/model/index.ts +81 -72
  75. package/src/authorization/model/openfga-json.ts +310 -0
  76. package/src/authorization/model/rewrite.ts +39 -188
  77. package/src/authorization/strict-json.ts +52 -0
  78. package/src/boot/compose.ts +9 -7
  79. package/src/extensions/__tests__/built-in-authorization-composed.test.ts +3 -6
  80. package/src/extensions/list-read-scope.ts +32 -4
  81. package/src/index.ts +15 -44
  82. package/dist/authorization/model/agent.d.ts +0 -2
  83. package/dist/authorization/model/agent.d.ts.map +0 -1
  84. package/dist/authorization/model/agent.js +0 -43
  85. package/dist/authorization/model/agent.js.map +0 -1
  86. package/dist/authorization/model/agent_channel.d.ts +0 -2
  87. package/dist/authorization/model/agent_channel.d.ts.map +0 -1
  88. package/dist/authorization/model/agent_channel.js +0 -39
  89. package/dist/authorization/model/agent_channel.js.map +0 -1
  90. package/dist/authorization/model/agent_execution.d.ts +0 -2
  91. package/dist/authorization/model/agent_execution.d.ts.map +0 -1
  92. package/dist/authorization/model/agent_execution.js +0 -25
  93. package/dist/authorization/model/agent_execution.js.map +0 -1
  94. package/dist/authorization/model/agent_instance.d.ts +0 -2
  95. package/dist/authorization/model/agent_instance.d.ts.map +0 -1
  96. package/dist/authorization/model/agent_instance.js +0 -48
  97. package/dist/authorization/model/agent_instance.js.map +0 -1
  98. package/dist/authorization/model/agent_share.d.ts +0 -2
  99. package/dist/authorization/model/agent_share.d.ts.map +0 -1
  100. package/dist/authorization/model/agent_share.js +0 -29
  101. package/dist/authorization/model/agent_share.js.map +0 -1
  102. package/dist/authorization/model/api_key.d.ts +0 -2
  103. package/dist/authorization/model/api_key.d.ts.map +0 -1
  104. package/dist/authorization/model/api_key.js +0 -27
  105. package/dist/authorization/model/api_key.js.map +0 -1
  106. package/dist/authorization/model/artifact.d.ts +0 -2
  107. package/dist/authorization/model/artifact.d.ts.map +0 -1
  108. package/dist/authorization/model/artifact.js +0 -27
  109. package/dist/authorization/model/artifact.js.map +0 -1
  110. package/dist/authorization/model/channel_app.d.ts +0 -2
  111. package/dist/authorization/model/channel_app.d.ts.map +0 -1
  112. package/dist/authorization/model/channel_app.js +0 -28
  113. package/dist/authorization/model/channel_app.js.map +0 -1
  114. package/dist/authorization/model/environment.d.ts +0 -2
  115. package/dist/authorization/model/environment.d.ts.map +0 -1
  116. package/dist/authorization/model/environment.js +0 -33
  117. package/dist/authorization/model/environment.js.map +0 -1
  118. package/dist/authorization/model/execution_context.d.ts +0 -2
  119. package/dist/authorization/model/execution_context.d.ts.map +0 -1
  120. package/dist/authorization/model/execution_context.js +0 -19
  121. package/dist/authorization/model/execution_context.js.map +0 -1
  122. package/dist/authorization/model/iam_policy.d.ts +0 -2
  123. package/dist/authorization/model/iam_policy.d.ts.map +0 -1
  124. package/dist/authorization/model/iam_policy.js +0 -31
  125. package/dist/authorization/model/iam_policy.js.map +0 -1
  126. package/dist/authorization/model/identity_account.d.ts +0 -2
  127. package/dist/authorization/model/identity_account.d.ts.map +0 -1
  128. package/dist/authorization/model/identity_account.js +0 -25
  129. package/dist/authorization/model/identity_account.js.map +0 -1
  130. package/dist/authorization/model/mcp_server.d.ts +0 -2
  131. package/dist/authorization/model/mcp_server.d.ts.map +0 -1
  132. package/dist/authorization/model/mcp_server.js +0 -38
  133. package/dist/authorization/model/mcp_server.js.map +0 -1
  134. package/dist/authorization/model/memory.d.ts +0 -2
  135. package/dist/authorization/model/memory.d.ts.map +0 -1
  136. package/dist/authorization/model/memory.js +0 -26
  137. package/dist/authorization/model/memory.js.map +0 -1
  138. package/dist/authorization/model/oauth_app.d.ts +0 -2
  139. package/dist/authorization/model/oauth_app.d.ts.map +0 -1
  140. package/dist/authorization/model/oauth_app.js +0 -31
  141. package/dist/authorization/model/oauth_app.js.map +0 -1
  142. package/dist/authorization/model/organization.d.ts +0 -2
  143. package/dist/authorization/model/organization.d.ts.map +0 -1
  144. package/dist/authorization/model/organization.js +0 -58
  145. package/dist/authorization/model/organization.js.map +0 -1
  146. package/dist/authorization/model/platform_client.d.ts +0 -2
  147. package/dist/authorization/model/platform_client.d.ts.map +0 -1
  148. package/dist/authorization/model/platform_client.js +0 -31
  149. package/dist/authorization/model/platform_client.js.map +0 -1
  150. package/dist/authorization/model/plugin.d.ts +0 -2
  151. package/dist/authorization/model/plugin.d.ts.map +0 -1
  152. package/dist/authorization/model/plugin.js +0 -45
  153. package/dist/authorization/model/plugin.js.map +0 -1
  154. package/dist/authorization/model/schedule.d.ts +0 -2
  155. package/dist/authorization/model/schedule.d.ts.map +0 -1
  156. package/dist/authorization/model/schedule.js +0 -34
  157. package/dist/authorization/model/schedule.js.map +0 -1
  158. package/dist/authorization/model/session.d.ts +0 -2
  159. package/dist/authorization/model/session.d.ts.map +0 -1
  160. package/dist/authorization/model/session.js +0 -38
  161. package/dist/authorization/model/session.js.map +0 -1
  162. package/dist/authorization/model/skill.d.ts +0 -2
  163. package/dist/authorization/model/skill.d.ts.map +0 -1
  164. package/dist/authorization/model/skill.js +0 -39
  165. package/dist/authorization/model/skill.js.map +0 -1
  166. package/dist/authorization/model/workflow.d.ts +0 -2
  167. package/dist/authorization/model/workflow.d.ts.map +0 -1
  168. package/dist/authorization/model/workflow.js +0 -39
  169. package/dist/authorization/model/workflow.js.map +0 -1
  170. package/dist/authorization/model/workflow_execution.d.ts +0 -2
  171. package/dist/authorization/model/workflow_execution.d.ts.map +0 -1
  172. package/dist/authorization/model/workflow_execution.js +0 -33
  173. package/dist/authorization/model/workflow_execution.js.map +0 -1
  174. package/dist/authorization/model/workflow_instance.d.ts +0 -2
  175. package/dist/authorization/model/workflow_instance.d.ts.map +0 -1
  176. package/dist/authorization/model/workflow_instance.js +0 -96
  177. package/dist/authorization/model/workflow_instance.js.map +0 -1
  178. package/dist/authorization/store-test-kit.d.ts +0 -62
  179. package/dist/authorization/store-test-kit.d.ts.map +0 -1
  180. package/dist/authorization/store-test-kit.js +0 -265
  181. package/dist/authorization/store-test-kit.js.map +0 -1
  182. package/src/authorization/__tests__/enterprise-model.ts +0 -59
  183. package/src/authorization/__tests__/fixtures/fga/agent-channel-owner.fga.yaml +0 -112
  184. package/src/authorization/__tests__/fixtures/fga/agent-instance-creation.fga.yaml +0 -177
  185. package/src/authorization/__tests__/fixtures/fga/agent-share-owner.fga.yaml +0 -109
  186. package/src/authorization/__tests__/fixtures/fga/artifact-org-and-owner.fga.yaml +0 -128
  187. package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +0 -318
  188. package/src/authorization/__tests__/fixtures/fga/channel-app-owner.fga.yaml +0 -125
  189. package/src/authorization/__tests__/fixtures/fga/channel-participation.fga.yaml +0 -201
  190. package/src/authorization/__tests__/fixtures/fga/channel-session-visibility.fga.yaml +0 -187
  191. package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +0 -214
  192. package/src/authorization/__tests__/fixtures/fga/mcp-server-authoring.fga.yaml +0 -129
  193. package/src/authorization/__tests__/fixtures/fga/memory-subject-only.fga.yaml +0 -72
  194. package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +0 -308
  195. package/src/authorization/__tests__/fixtures/fga/org-shared-environment.fga.yaml +0 -144
  196. package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +0 -199
  197. package/src/authorization/__tests__/fixtures/fga/provider-standing-viewer.fga.yaml +0 -40
  198. package/src/authorization/__tests__/fixtures/fga/reserved-label-writer.fga.yaml +0 -41
  199. package/src/authorization/__tests__/fixtures/fga/schedule-owner.fga.yaml +0 -113
  200. package/src/authorization/__tests__/fixtures/fga/schedule-session-visibility.fga.yaml +0 -214
  201. package/src/authorization/__tests__/fixtures/fga/session-personal-resource.fga.yaml +0 -117
  202. package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +0 -190
  203. package/src/authorization/model/agent.ts +0 -64
  204. package/src/authorization/model/agent_channel.ts +0 -57
  205. package/src/authorization/model/agent_execution.ts +0 -33
  206. package/src/authorization/model/agent_instance.ts +0 -66
  207. package/src/authorization/model/agent_share.ts +0 -40
  208. package/src/authorization/model/api_key.ts +0 -28
  209. package/src/authorization/model/artifact.ts +0 -38
  210. package/src/authorization/model/channel_app.ts +0 -39
  211. package/src/authorization/model/environment.ts +0 -48
  212. package/src/authorization/model/execution_context.ts +0 -20
  213. package/src/authorization/model/iam_policy.ts +0 -42
  214. package/src/authorization/model/identity_account.ts +0 -26
  215. package/src/authorization/model/mcp_server.ts +0 -59
  216. package/src/authorization/model/memory.ts +0 -27
  217. package/src/authorization/model/oauth_app.ts +0 -43
  218. package/src/authorization/model/organization.ts +0 -59
  219. package/src/authorization/model/platform_client.ts +0 -43
  220. package/src/authorization/model/plugin.ts +0 -66
  221. package/src/authorization/model/schedule.ts +0 -49
  222. package/src/authorization/model/session.ts +0 -50
  223. package/src/authorization/model/skill.ts +0 -60
  224. package/src/authorization/model/workflow.ts +0 -60
  225. package/src/authorization/model/workflow_execution.ts +0 -46
  226. package/src/authorization/model/workflow_instance.ts +0 -125
  227. 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