fluidattacks_integrates_dal 2.0.0__tar.gz

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 (29) hide show
  1. fluidattacks_integrates_dal-2.0.0/.envrc +2 -0
  2. fluidattacks_integrates_dal-2.0.0/PKG-INFO +11 -0
  3. fluidattacks_integrates_dal-2.0.0/build/default.nix +7 -0
  4. fluidattacks_integrates_dal-2.0.0/build/filter.nix +12 -0
  5. fluidattacks_integrates_dal-2.0.0/flake.lock +351 -0
  6. fluidattacks_integrates_dal-2.0.0/flake.nix +19 -0
  7. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/__init__.py +11 -0
  8. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/_cli.py +61 -0
  9. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/_logger.py +34 -0
  10. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/_typing.py +17 -0
  11. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/client.py +25 -0
  12. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/clients/__init__.py +28 -0
  13. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/clients/group/__init__.py +150 -0
  14. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/clients/organization/__init__.py +112 -0
  15. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/core.py +56 -0
  16. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/list_groups.py +16 -0
  17. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/py.typed +0 -0
  18. fluidattacks_integrates_dal-2.0.0/fluidattacks_integrates_dal/utils.py +26 -0
  19. fluidattacks_integrates_dal-2.0.0/mypy.ini +30 -0
  20. fluidattacks_integrates_dal-2.0.0/pyproject.toml +36 -0
  21. fluidattacks_integrates_dal-2.0.0/ruff.toml +33 -0
  22. fluidattacks_integrates_dal-2.0.0/tests/__init__.py +0 -0
  23. fluidattacks_integrates_dal-2.0.0/tests/arch/__init__.py +0 -0
  24. fluidattacks_integrates_dal-2.0.0/tests/arch/arch.py +43 -0
  25. fluidattacks_integrates_dal-2.0.0/tests/arch/test_arch.py +48 -0
  26. fluidattacks_integrates_dal-2.0.0/tests/py.typed +0 -0
  27. fluidattacks_integrates_dal-2.0.0/tests/test_core.py +12 -0
  28. fluidattacks_integrates_dal-2.0.0/tests/test_list_groups.py +44 -0
  29. fluidattacks_integrates_dal-2.0.0/uv.lock +737 -0
@@ -0,0 +1,2 @@
1
+ ln -f ../mypy.ini ./mypy.ini
2
+ use_flake ".#python311.devShell"
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: fluidattacks_integrates_dal
3
+ Version: 2.0.0
4
+ Summary: ASM Synchronous Data Access Layer
5
+ Author-email: Engineering Team <development@fluidattacks.com>
6
+ Requires-Python: >=3.11
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Requires-Dist: boto3 >=1.40.53, <2.0.0
9
+ Requires-Dist: click >=8.1.7, <9.0.0
10
+ Requires-Dist: fa-purity >=2.5.2, <3.0.0
11
+ Requires-Dist: fluidattacks-utils-logger >=1.0.0, <2.0.0
@@ -0,0 +1,7 @@
1
+ { nixpkgs, builders, scripts, src, }: {
2
+ inherit src;
3
+ root_path = "observes/common/integrates-dal";
4
+ module_name = "fluidattacks_integrates_dal";
5
+ pypi_token_var = "INTEGRATES_DAL_TOKEN";
6
+ override = b: b;
7
+ }
@@ -0,0 +1,12 @@
1
+ path_filter: src:
2
+ path_filter {
3
+ root = src;
4
+ include = [
5
+ "fluidattacks_integrates_dal"
6
+ "tests"
7
+ "pyproject.toml"
8
+ "mypy.ini"
9
+ "ruff.toml"
10
+ "uv.lock"
11
+ ];
12
+ }
@@ -0,0 +1,351 @@
1
+ {
2
+ "nodes": {
3
+ "flake-parts": {
4
+ "inputs": {
5
+ "nixpkgs-lib": "nixpkgs-lib"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1754487366,
9
+ "narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=",
10
+ "owner": "hercules-ci",
11
+ "repo": "flake-parts",
12
+ "rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "hercules-ci",
17
+ "repo": "flake-parts",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nix_filter": {
22
+ "locked": {
23
+ "lastModified": 1731533336,
24
+ "narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
25
+ "owner": "numtide",
26
+ "repo": "nix-filter",
27
+ "rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "numtide",
32
+ "repo": "nix-filter",
33
+ "type": "github"
34
+ }
35
+ },
36
+ "nix_filter_2": {
37
+ "locked": {
38
+ "lastModified": 1731533336,
39
+ "narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
40
+ "owner": "numtide",
41
+ "repo": "nix-filter",
42
+ "rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
43
+ "type": "github"
44
+ },
45
+ "original": {
46
+ "owner": "numtide",
47
+ "repo": "nix-filter",
48
+ "type": "github"
49
+ }
50
+ },
51
+ "nixpkgs": {
52
+ "locked": {
53
+ "lastModified": 1736441877,
54
+ "narHash": "sha256-m3+PhBFkDwqo9lBplG4AyMW8P4/KcioJRS1UG8N7okM=",
55
+ "owner": "nixos",
56
+ "repo": "nixpkgs",
57
+ "rev": "ce3899414dab3297cf025bfa356dc2da426feefd",
58
+ "type": "github"
59
+ },
60
+ "original": {
61
+ "owner": "nixos",
62
+ "repo": "nixpkgs",
63
+ "type": "github"
64
+ }
65
+ },
66
+ "nixpkgs-lib": {
67
+ "locked": {
68
+ "lastModified": 1753579242,
69
+ "narHash": "sha256-zvaMGVn14/Zz8hnp4VWT9xVnhc8vuL3TStRqwk22biA=",
70
+ "owner": "nix-community",
71
+ "repo": "nixpkgs.lib",
72
+ "rev": "0f36c44e01a6129be94e3ade315a5883f0228a6e",
73
+ "type": "github"
74
+ },
75
+ "original": {
76
+ "owner": "nix-community",
77
+ "repo": "nixpkgs.lib",
78
+ "type": "github"
79
+ }
80
+ },
81
+ "nixpkgs_2": {
82
+ "locked": {
83
+ "lastModified": 1758690382,
84
+ "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
85
+ "owner": "nixos",
86
+ "repo": "nixpkgs",
87
+ "rev": "e643668fd71b949c53f8626614b21ff71a07379d",
88
+ "type": "github"
89
+ },
90
+ "original": {
91
+ "owner": "nixos",
92
+ "ref": "nixos-unstable",
93
+ "repo": "nixpkgs",
94
+ "type": "github"
95
+ }
96
+ },
97
+ "nixpkgs_3": {
98
+ "locked": {
99
+ "lastModified": 1758690382,
100
+ "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
101
+ "owner": "nixos",
102
+ "repo": "nixpkgs",
103
+ "rev": "e643668fd71b949c53f8626614b21ff71a07379d",
104
+ "type": "github"
105
+ },
106
+ "original": {
107
+ "owner": "nixos",
108
+ "ref": "nixos-unstable",
109
+ "repo": "nixpkgs",
110
+ "type": "github"
111
+ }
112
+ },
113
+ "nixpkgs_4": {
114
+ "locked": {
115
+ "lastModified": 1761373498,
116
+ "narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=",
117
+ "owner": "nixos",
118
+ "repo": "nixpkgs",
119
+ "rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce",
120
+ "type": "github"
121
+ },
122
+ "original": {
123
+ "owner": "nixos",
124
+ "ref": "nixos-unstable",
125
+ "repo": "nixpkgs",
126
+ "type": "github"
127
+ }
128
+ },
129
+ "nixpkgs_flake": {
130
+ "locked": {
131
+ "lastModified": 1756313514,
132
+ "narHash": "sha256-3Xbak0pXR8ziNv1ghHyJ5a5Ti2kt/LWq6hKZVJTvjBs=",
133
+ "owner": "nixos",
134
+ "repo": "nixpkgs",
135
+ "rev": "181464235b2daff8725773fef43ffc9d6b02e1c2",
136
+ "type": "github"
137
+ },
138
+ "original": {
139
+ "owner": "nixos",
140
+ "repo": "nixpkgs",
141
+ "type": "github"
142
+ }
143
+ },
144
+ "observes_flake_builder": {
145
+ "inputs": {
146
+ "nix_filter": "nix_filter",
147
+ "nixpkgs_flake": "nixpkgs_flake",
148
+ "pynix_flake": "pynix_flake",
149
+ "pyproject-build-systems": "pyproject-build-systems",
150
+ "pyproject-nix": "pyproject-nix_2",
151
+ "shell-helpers": "shell-helpers",
152
+ "uv2nix": "uv2nix_2"
153
+ },
154
+ "locked": {
155
+ "dir": "observes/common/std_flake_2",
156
+ "lastModified": 1761684858,
157
+ "narHash": "sha256-gybMRO/MSOPXQjI//u2UKfvs8pD0sACqL2Kjp+xR4rI=",
158
+ "owner": "fluidattacks",
159
+ "repo": "universe",
160
+ "rev": "c5053864bb838edbe226d74a650d901c0270843b",
161
+ "type": "github"
162
+ },
163
+ "original": {
164
+ "dir": "observes/common/std_flake_2",
165
+ "owner": "fluidattacks",
166
+ "repo": "universe",
167
+ "rev": "c5053864bb838edbe226d74a650d901c0270843b",
168
+ "type": "github"
169
+ }
170
+ },
171
+ "pynix_flake": {
172
+ "inputs": {
173
+ "nix_filter": "nix_filter_2",
174
+ "nixpkgs": "nixpkgs"
175
+ },
176
+ "locked": {
177
+ "lastModified": 1758642502,
178
+ "narHash": "sha256-PD/bQMz2dqZSkydHyvRh+jS/0qoV8SdcIVs6sassteQ=",
179
+ "owner": "dmurciaatfluid",
180
+ "repo": "python_nix_builder",
181
+ "rev": "809aafe2e1995e72c15378d099bf251b78f04a20",
182
+ "type": "gitlab"
183
+ },
184
+ "original": {
185
+ "owner": "dmurciaatfluid",
186
+ "repo": "python_nix_builder",
187
+ "type": "gitlab"
188
+ }
189
+ },
190
+ "pyproject-build-systems": {
191
+ "inputs": {
192
+ "nixpkgs": "nixpkgs_2",
193
+ "pyproject-nix": "pyproject-nix",
194
+ "uv2nix": "uv2nix"
195
+ },
196
+ "locked": {
197
+ "lastModified": 1759113590,
198
+ "narHash": "sha256-fgxP2RCN4cg0jYiMYoETYc7TZ2JjgyvJa2y9l8oSUFE=",
199
+ "owner": "pyproject-nix",
200
+ "repo": "build-system-pkgs",
201
+ "rev": "dbfc0483b5952c6b86e36f8b3afeb9dde30ea4b5",
202
+ "type": "github"
203
+ },
204
+ "original": {
205
+ "owner": "pyproject-nix",
206
+ "repo": "build-system-pkgs",
207
+ "type": "github"
208
+ }
209
+ },
210
+ "pyproject-nix": {
211
+ "inputs": {
212
+ "nixpkgs": [
213
+ "observes_flake_builder",
214
+ "pyproject-build-systems",
215
+ "nixpkgs"
216
+ ]
217
+ },
218
+ "locked": {
219
+ "lastModified": 1758265079,
220
+ "narHash": "sha256-amLaLNwKSZPShQHzfgmc/9o76dU8xzN0743dWgvYlr8=",
221
+ "owner": "nix-community",
222
+ "repo": "pyproject.nix",
223
+ "rev": "02e9418fd4af638447dca4b17b1280da95527fc9",
224
+ "type": "github"
225
+ },
226
+ "original": {
227
+ "owner": "nix-community",
228
+ "repo": "pyproject.nix",
229
+ "type": "github"
230
+ }
231
+ },
232
+ "pyproject-nix_2": {
233
+ "inputs": {
234
+ "nixpkgs": "nixpkgs_3"
235
+ },
236
+ "locked": {
237
+ "lastModified": 1760402624,
238
+ "narHash": "sha256-jF6UKLs2uGc2rtved8Vrt58oTWjTQoAssuYs/0578Z4=",
239
+ "owner": "pyproject-nix",
240
+ "repo": "pyproject.nix",
241
+ "rev": "84c4ea102127c77058ea1ed7be7300261fafc7d2",
242
+ "type": "github"
243
+ },
244
+ "original": {
245
+ "owner": "pyproject-nix",
246
+ "repo": "pyproject.nix",
247
+ "type": "github"
248
+ }
249
+ },
250
+ "pyproject-nix_3": {
251
+ "inputs": {
252
+ "nixpkgs": [
253
+ "observes_flake_builder",
254
+ "uv2nix",
255
+ "nixpkgs"
256
+ ]
257
+ },
258
+ "locked": {
259
+ "lastModified": 1760402624,
260
+ "narHash": "sha256-jF6UKLs2uGc2rtved8Vrt58oTWjTQoAssuYs/0578Z4=",
261
+ "owner": "pyproject-nix",
262
+ "repo": "pyproject.nix",
263
+ "rev": "84c4ea102127c77058ea1ed7be7300261fafc7d2",
264
+ "type": "github"
265
+ },
266
+ "original": {
267
+ "owner": "pyproject-nix",
268
+ "repo": "pyproject.nix",
269
+ "type": "github"
270
+ }
271
+ },
272
+ "root": {
273
+ "inputs": {
274
+ "observes_flake_builder": "observes_flake_builder"
275
+ }
276
+ },
277
+ "shell-helpers": {
278
+ "inputs": {
279
+ "flake-parts": "flake-parts",
280
+ "nixpkgs": [
281
+ "observes_flake_builder",
282
+ "nixpkgs_flake"
283
+ ]
284
+ },
285
+ "locked": {
286
+ "dir": "common/utils/shell-helpers",
287
+ "lastModified": 1752896460,
288
+ "narHash": "sha256-AsyTatXMx839cGsF6knwTrDZHk3Eue2QD3eSP7bkmpg=",
289
+ "owner": "fluidattacks",
290
+ "repo": "universe",
291
+ "rev": "27749d2c3a2b018eb010a322e5e1352f993c9e86",
292
+ "type": "github"
293
+ },
294
+ "original": {
295
+ "dir": "common/utils/shell-helpers",
296
+ "owner": "fluidattacks",
297
+ "repo": "universe",
298
+ "rev": "27749d2c3a2b018eb010a322e5e1352f993c9e86",
299
+ "type": "github"
300
+ }
301
+ },
302
+ "uv2nix": {
303
+ "inputs": {
304
+ "nixpkgs": [
305
+ "observes_flake_builder",
306
+ "pyproject-build-systems",
307
+ "nixpkgs"
308
+ ],
309
+ "pyproject-nix": [
310
+ "observes_flake_builder",
311
+ "pyproject-build-systems",
312
+ "pyproject-nix"
313
+ ]
314
+ },
315
+ "locked": {
316
+ "lastModified": 1758933732,
317
+ "narHash": "sha256-HAmm1GBS1myZCFuog0DC2ZLaynvZtiUI2Crmo+cdQI0=",
318
+ "owner": "pyproject-nix",
319
+ "repo": "uv2nix",
320
+ "rev": "273ce18f913d8559e0d04f820d724308966d7c4d",
321
+ "type": "github"
322
+ },
323
+ "original": {
324
+ "owner": "pyproject-nix",
325
+ "repo": "uv2nix",
326
+ "type": "github"
327
+ }
328
+ },
329
+ "uv2nix_2": {
330
+ "inputs": {
331
+ "nixpkgs": "nixpkgs_4",
332
+ "pyproject-nix": "pyproject-nix_3"
333
+ },
334
+ "locked": {
335
+ "lastModified": 1761527626,
336
+ "narHash": "sha256-neDfvbpFlzUQfH9C+hVRUX0/RXUbJBidw4pFcdMYhZA=",
337
+ "owner": "pyproject-nix",
338
+ "repo": "uv2nix",
339
+ "rev": "46a8e8bbb2d9e34b686329ac16e4a8861394f03a",
340
+ "type": "github"
341
+ },
342
+ "original": {
343
+ "owner": "pyproject-nix",
344
+ "repo": "uv2nix",
345
+ "type": "github"
346
+ }
347
+ }
348
+ },
349
+ "root": "root",
350
+ "version": 7
351
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ description = "Common Integrates-dal";
3
+
4
+ inputs = {
5
+ observes_flake_builder = {
6
+ url =
7
+ "github:fluidattacks/universe/c5053864bb838edbe226d74a650d901c0270843b?shallow=1&dir=observes/common/std_flake_2";
8
+ };
9
+ };
10
+
11
+ outputs = { self, ... }@inputs:
12
+ let
13
+ build_args = { system, python_version, nixpkgs, builders, scripts }:
14
+ import ./build {
15
+ inherit nixpkgs builders scripts;
16
+ src = import ./build/filter.nix nixpkgs.nix-filter self;
17
+ };
18
+ in { packages = inputs.observes_flake_builder.outputs.build build_args; };
19
+ }
@@ -0,0 +1,11 @@
1
+ from fa_purity import (
2
+ Unsafe,
3
+ )
4
+
5
+ from ._logger import (
6
+ set_logger,
7
+ )
8
+
9
+ __version__ = "2.0.0"
10
+
11
+ Unsafe.compute(set_logger(__name__, __version__))
@@ -0,0 +1,61 @@
1
+ import logging
2
+ import sys
3
+
4
+ import click
5
+ from fa_purity import (
6
+ Cmd,
7
+ )
8
+ from fluidattacks_utils_logger import (
9
+ start_session,
10
+ )
11
+
12
+ from fluidattacks_integrates_dal._typing import (
13
+ NoReturn,
14
+ )
15
+
16
+ from . import (
17
+ list_groups,
18
+ )
19
+ from .clients.group import (
20
+ new_client as new_group_client,
21
+ )
22
+ from .clients.organization import (
23
+ new_client as new_org_client,
24
+ )
25
+ from .utils import (
26
+ new_client,
27
+ new_resource,
28
+ new_session,
29
+ )
30
+
31
+ LOG = logging.getLogger(__name__)
32
+
33
+
34
+ @click.command(help="Requires AWS authentication (retrieved from the environment)")
35
+ def list_all_groups() -> NoReturn:
36
+ clients = new_session().bind(
37
+ lambda s: new_client(s)
38
+ .map(new_org_client)
39
+ .bind(lambda o: new_resource(s).map(new_group_client).map(lambda g: (o, g))),
40
+ )
41
+ cmd: Cmd[None] = start_session() + clients.bind(
42
+ lambda t: list_groups.list_all_groups(t[0], t[1])
43
+ .map(lambda gs: "\n".join(g.name for g in gs))
44
+ .bind(
45
+ lambda s: Cmd.wrap_impure(
46
+ lambda: sys.stdout.write(s + "\n"), # type: ignore[misc]
47
+ ).map(
48
+ lambda _: None, # type: ignore[misc]
49
+ ),
50
+ ),
51
+ )
52
+ cmd.compute()
53
+
54
+
55
+ @click.group()
56
+ def main() -> None:
57
+ # cli group entrypoint
58
+ pass
59
+
60
+
61
+ main.add_command(list_all_groups)
@@ -0,0 +1,34 @@
1
+ from fa_purity import (
2
+ Cmd,
3
+ )
4
+ from fluidattacks_utils_logger import (
5
+ set_main_log,
6
+ )
7
+ from fluidattacks_utils_logger.env import (
8
+ current_app_env,
9
+ notifier_key,
10
+ observes_debug,
11
+ )
12
+ from fluidattacks_utils_logger.handlers import (
13
+ LoggingConf,
14
+ )
15
+
16
+
17
+ def set_logger(root_name: str, version: str) -> Cmd[None]:
18
+ n_key = notifier_key()
19
+ app_env = current_app_env()
20
+ debug = observes_debug()
21
+ conf = n_key.bind(
22
+ lambda key: app_env.map(
23
+ lambda env: LoggingConf(
24
+ "common",
25
+ version,
26
+ "./observes/common/integrates-dal",
27
+ False,
28
+ key,
29
+ env,
30
+ "observes",
31
+ ),
32
+ ),
33
+ )
34
+ return debug.bind(lambda d: conf.bind(lambda c: set_main_log(root_name, c, d, False)))
@@ -0,0 +1,17 @@
1
+ from collections.abc import Callable, Iterable, Iterator
2
+ from typing import Generic, NoReturn, TypeAlias, TypeVar, TypeVarTuple, Union
3
+
4
+ _T_arr = TypeVarTuple("_T_arr")
5
+ Dict = dict
6
+ Tuple: TypeAlias = tuple[*_T_arr] # type: ignore[misc]
7
+ FrozenSet = frozenset
8
+
9
+ __all__ = [
10
+ "Callable",
11
+ "Generic",
12
+ "Iterable",
13
+ "Iterator",
14
+ "NoReturn",
15
+ "TypeVar",
16
+ "Union",
17
+ ]
@@ -0,0 +1,25 @@
1
+ from collections.abc import (
2
+ Callable,
3
+ )
4
+ from dataclasses import (
5
+ dataclass,
6
+ )
7
+
8
+ from fa_purity import (
9
+ Stream,
10
+ )
11
+
12
+ from .core import (
13
+ GroupId,
14
+ OrganizationId,
15
+ )
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class OrgsClient:
20
+ all_orgs: Stream[OrganizationId]
21
+
22
+
23
+ @dataclass(frozen=True)
24
+ class GroupsClient:
25
+ get_groups: Callable[[OrganizationId], Stream[GroupId]]
@@ -0,0 +1,28 @@
1
+ from fa_purity import (
2
+ Cmd,
3
+ )
4
+
5
+ from fluidattacks_integrates_dal.client import (
6
+ GroupsClient,
7
+ OrgsClient,
8
+ )
9
+ from fluidattacks_integrates_dal.utils import (
10
+ new_client,
11
+ new_resource,
12
+ new_session,
13
+ )
14
+
15
+ from .group import (
16
+ new_client as _new_group_client,
17
+ )
18
+ from .organization import (
19
+ new_client as _new_org_client,
20
+ )
21
+
22
+
23
+ def new_group_client() -> Cmd[GroupsClient]:
24
+ return new_session().bind(new_resource).map(_new_group_client)
25
+
26
+
27
+ def new_org_client() -> Cmd[OrgsClient]:
28
+ return new_session().bind(new_client).map(_new_org_client)