@atlasauth/backend 0.25.0 → 0.27.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/CHANGELOG.md +42 -1
- package/dist/client/abac.d.ts +454 -0
- package/dist/client/abac.js +123 -0
- package/dist/client/abac.js.map +1 -1
- package/dist/client/access-policies.d.ts +84 -2
- package/dist/client/access-policies.js +8 -0
- package/dist/client/access-policies.js.map +1 -1
- package/dist/client/actions.d.ts +1 -1
- package/dist/client/actions.js.map +1 -1
- package/dist/client/agent-platform.d.ts +294 -0
- package/dist/client/agent-platform.js +132 -0
- package/dist/client/agent-platform.js.map +1 -0
- package/dist/client/analytics-reports.d.ts +1 -1
- package/dist/client/app-catalog.d.ts +60 -1
- package/dist/client/app-catalog.js +32 -2
- package/dist/client/app-catalog.js.map +1 -1
- package/dist/client/authz-decisions.d.ts +154 -0
- package/dist/client/authz-decisions.js +53 -0
- package/dist/client/authz-decisions.js.map +1 -0
- package/dist/client/connections.d.ts +519 -0
- package/dist/client/connections.js +171 -0
- package/dist/client/connections.js.map +1 -0
- package/dist/client/custom-oauth-providers.d.ts +15 -0
- package/dist/client/custom-oauth-providers.js.map +1 -1
- package/dist/client/desktop-mfa.d.ts +141 -0
- package/dist/client/desktop-mfa.js +58 -0
- package/dist/client/desktop-mfa.js.map +1 -0
- package/dist/client/devices.d.ts +130 -0
- package/dist/client/devices.js +54 -0
- package/dist/client/devices.js.map +1 -1
- package/dist/client/email-templates.d.ts +1 -1
- package/dist/client/email-templates.js.map +1 -1
- package/dist/client/fga.d.ts +301 -5
- package/dist/client/fga.js +81 -1
- package/dist/client/fga.js.map +1 -1
- package/dist/client/iga.d.ts +436 -0
- package/dist/client/iga.js +82 -0
- package/dist/client/iga.js.map +1 -0
- package/dist/client/index.d.ts +3767 -2443
- package/dist/client/index.js +51 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/least-privilege.d.ts +95 -0
- package/dist/client/least-privilege.js +28 -0
- package/dist/client/least-privilege.js.map +1 -0
- package/dist/client/log-streams.d.ts +1 -1
- package/dist/client/managed-grants.d.ts +52 -0
- package/dist/client/managed-grants.js +28 -0
- package/dist/client/managed-grants.js.map +1 -0
- package/dist/client/mcp-gateways.d.ts +220 -2
- package/dist/client/mcp-gateways.js +74 -0
- package/dist/client/mcp-gateways.js.map +1 -1
- package/dist/client/messaging.d.ts +11 -2
- package/dist/client/messaging.js.map +1 -1
- package/dist/client/oauth-clients.d.ts +4 -0
- package/dist/client/oauth-clients.js.map +1 -1
- package/dist/client/oauth-protocols.d.ts +116 -0
- package/dist/client/oauth-protocols.js +54 -0
- package/dist/client/oauth-protocols.js.map +1 -0
- package/dist/client/oauth-providers.d.ts +4 -4
- package/dist/client/openfga.d.ts +90 -3
- package/dist/client/openfga.js +27 -1
- package/dist/client/openfga.js.map +1 -1
- package/dist/client/org-ldap-connections.d.ts +3 -0
- package/dist/client/org-ldap-connections.js.map +1 -1
- package/dist/client/organizations.d.ts +14 -0
- package/dist/client/organizations.js.map +1 -1
- package/dist/client/policy-bundles.d.ts +105 -0
- package/dist/client/policy-bundles.js +38 -0
- package/dist/client/policy-bundles.js.map +1 -0
- package/dist/client/resources.d.ts +1 -0
- package/dist/client/resources.js.map +1 -1
- package/dist/client/risk-containment.d.ts +244 -0
- package/dist/client/risk-containment.js +120 -0
- package/dist/client/risk-containment.js.map +1 -0
- package/dist/client/saml-idp.d.ts +183 -0
- package/dist/client/saml-idp.js +71 -0
- package/dist/client/saml-idp.js.map +1 -0
- package/dist/client/scim-provisioning.d.ts +100 -4
- package/dist/client/scim-provisioning.js +30 -0
- package/dist/client/scim-provisioning.js.map +1 -1
- package/dist/client/scim-tokens.d.ts +34 -0
- package/dist/client/scim-tokens.js +17 -0
- package/dist/client/scim-tokens.js.map +1 -1
- package/dist/client/service-connectors.d.ts +1 -1
- package/dist/client/ssf.d.ts +31 -1
- package/dist/client/ssf.js +17 -0
- package/dist/client/ssf.js.map +1 -1
- package/dist/client/users.d.ts +9 -0
- package/dist/client/users.js +9 -0
- package/dist/client/users.js.map +1 -1
- package/dist/client/vault.d.ts +54 -0
- package/dist/client/vault.js +30 -0
- package/dist/client/vault.js.map +1 -1
- package/dist/client/vc.d.ts +62 -2
- package/dist/client/vc.js +15 -0
- package/dist/client/vc.js.map +1 -1
- package/dist/client/workflows.d.ts +182 -3
- package/dist/client/workflows.js +34 -0
- package/dist/client/workflows.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/oauth-resource.d.ts +30 -3
- package/dist/oauth-resource.js +43 -2
- package/dist/oauth-resource.js.map +1 -1
- package/dist/policy-bundle.d.ts +110 -0
- package/dist/policy-bundle.js +289 -0
- package/dist/policy-bundle.js.map +1 -0
- package/dist/txn-token.d.ts +36 -0
- package/dist/txn-token.js +30 -0
- package/dist/txn-token.js.map +1 -0
- package/dist/uma.d.ts +77 -0
- package/dist/uma.js +95 -0
- package/dist/uma.js.map +1 -0
- package/package.json +2 -2
package/dist/client/fga.d.ts
CHANGED
|
@@ -29,13 +29,35 @@ export interface FgaTuple {
|
|
|
29
29
|
relation: string;
|
|
30
30
|
/** The object of the tuple as `type:id`. */
|
|
31
31
|
target: string;
|
|
32
|
+
condition?: FgaTupleCondition;
|
|
33
|
+
/** Epoch ms after which the tuple stops granting. */
|
|
34
|
+
expires_at?: number;
|
|
32
35
|
created_at: number;
|
|
33
36
|
}
|
|
37
|
+
/** A model condition bound to a tuple, with the parameter values fixed on it. */
|
|
38
|
+
export interface FgaTupleCondition {
|
|
39
|
+
name: string;
|
|
40
|
+
context?: Record<string, unknown>;
|
|
41
|
+
}
|
|
34
42
|
/** A tuple key. `object` is the target as `type:id`; `target` is accepted too. */
|
|
35
43
|
export interface FgaTupleKey {
|
|
36
44
|
user: string;
|
|
37
45
|
relation: string;
|
|
38
46
|
object: string;
|
|
47
|
+
/** The tuple grants only while this model condition holds. */
|
|
48
|
+
condition?: FgaTupleCondition;
|
|
49
|
+
/** The tuple stops granting at this time (ISO 8601 or epoch ms, in the future); a sweep then deletes it. */
|
|
50
|
+
expires_at?: string | number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Freshness of a read. `MINIMIZE_LATENCY` (and the default) may be served from a
|
|
54
|
+
* short-lived cache; `HIGHER_CONSISTENCY` reads the primary.
|
|
55
|
+
*/
|
|
56
|
+
export type FgaConsistency = 'UNSPECIFIED' | 'MINIMIZE_LATENCY' | 'HIGHER_CONSISTENCY';
|
|
57
|
+
export interface FgaConsistencyOptions {
|
|
58
|
+
consistency?: FgaConsistency;
|
|
59
|
+
/** A token from a write: the read reflects at least that write. */
|
|
60
|
+
consistency_token?: string;
|
|
39
61
|
}
|
|
40
62
|
/** An OpenFGA authorization model to persist. Validated before storage. */
|
|
41
63
|
export interface FgaAuthorizationModelInput {
|
|
@@ -48,20 +70,80 @@ export interface FgaAuthorizationModelInput {
|
|
|
48
70
|
export type FgaTupleKeys = FgaTupleKey[] | {
|
|
49
71
|
tuple_keys: FgaTupleKey[];
|
|
50
72
|
};
|
|
51
|
-
export interface FgaCheckBody {
|
|
73
|
+
export interface FgaCheckBody extends FgaConsistencyOptions {
|
|
52
74
|
user: string;
|
|
53
75
|
relation: string;
|
|
54
76
|
object: string;
|
|
55
77
|
/** Defaults to the store's latest model. */
|
|
56
78
|
authorization_model_id?: string;
|
|
57
79
|
contextual_tuples?: FgaTupleKeys;
|
|
80
|
+
/** Values for tuple-condition parameters (a tuple's own context wins). */
|
|
81
|
+
context?: Record<string, unknown>;
|
|
58
82
|
}
|
|
59
|
-
export interface FgaListObjectsBody {
|
|
83
|
+
export interface FgaListObjectsBody extends FgaConsistencyOptions {
|
|
60
84
|
user: string;
|
|
61
85
|
relation: string;
|
|
62
86
|
type: string;
|
|
63
87
|
authorization_model_id?: string;
|
|
64
88
|
contextual_tuples?: FgaTupleKeys;
|
|
89
|
+
/** Page size; without it every object is returned. */
|
|
90
|
+
limit?: number;
|
|
91
|
+
/** The `next_cursor` of the previous page. */
|
|
92
|
+
starting_after?: string;
|
|
93
|
+
context?: Record<string, unknown>;
|
|
94
|
+
}
|
|
95
|
+
export interface FgaListUsersBody extends FgaConsistencyOptions {
|
|
96
|
+
/** `type:id`. */
|
|
97
|
+
object: string;
|
|
98
|
+
relation: string;
|
|
99
|
+
/** Exactly one filter; add `relation` to get usersets such as `group:eng#member`. */
|
|
100
|
+
user_filters: [{
|
|
101
|
+
type: string;
|
|
102
|
+
relation?: string;
|
|
103
|
+
}];
|
|
104
|
+
authorization_model_id?: string;
|
|
105
|
+
contextual_tuples?: FgaTupleKeys;
|
|
106
|
+
context?: Record<string, unknown>;
|
|
107
|
+
/** 1–1000; defaults to 1000. */
|
|
108
|
+
page_size?: number;
|
|
109
|
+
continuation_token?: string;
|
|
110
|
+
}
|
|
111
|
+
export interface FgaListUsersResult {
|
|
112
|
+
object: 'fga.list_users';
|
|
113
|
+
/** `type:id`, `type:id#relation`, or `type:*` for a public wildcard. */
|
|
114
|
+
users: string[];
|
|
115
|
+
/** Ids a wildcard in `users` does not cover. */
|
|
116
|
+
excluded_users: string[];
|
|
117
|
+
/** Pass back for the next page; null on the last. */
|
|
118
|
+
continuation_token: string | null;
|
|
119
|
+
authorization_model_id: string;
|
|
120
|
+
consistency_token: string;
|
|
121
|
+
}
|
|
122
|
+
export interface FgaReadChangesParams {
|
|
123
|
+
/** Only changes to tuples on objects of this type. */
|
|
124
|
+
type?: string;
|
|
125
|
+
/** 1–100; defaults to 50. */
|
|
126
|
+
page_size?: number;
|
|
127
|
+
continuation_token?: string;
|
|
128
|
+
/** RFC 3339: only changes at or after it. */
|
|
129
|
+
start_time?: string;
|
|
130
|
+
}
|
|
131
|
+
export interface FgaTupleChange {
|
|
132
|
+
object: 'fga.tuple_change';
|
|
133
|
+
operation: 'write' | 'delete';
|
|
134
|
+
user: string;
|
|
135
|
+
relation: string;
|
|
136
|
+
target: string;
|
|
137
|
+
condition?: FgaTupleCondition;
|
|
138
|
+
consistency_token: string;
|
|
139
|
+
created_at: number;
|
|
140
|
+
}
|
|
141
|
+
export interface FgaChangesPage {
|
|
142
|
+
object: 'list';
|
|
143
|
+
data: FgaTupleChange[];
|
|
144
|
+
has_more: boolean;
|
|
145
|
+
/** Save it and call again later to receive only newer changes. */
|
|
146
|
+
continuation_token: string;
|
|
65
147
|
}
|
|
66
148
|
/** One item in a batch check; `correlation_id` is echoed back to match results. */
|
|
67
149
|
export interface FgaBatchCheckItem {
|
|
@@ -70,16 +152,33 @@ export interface FgaBatchCheckItem {
|
|
|
70
152
|
object: string;
|
|
71
153
|
correlation_id?: string;
|
|
72
154
|
contextual_tuples?: FgaTupleKeys;
|
|
155
|
+
context?: Record<string, unknown>;
|
|
73
156
|
}
|
|
74
157
|
export interface FgaBatchCheckResult {
|
|
75
158
|
object: 'fga.batch_check';
|
|
76
159
|
authorization_model_id: string;
|
|
160
|
+
consistency_token: string;
|
|
77
161
|
result: Array<{
|
|
78
162
|
correlation_id: string;
|
|
79
163
|
allowed: boolean;
|
|
80
164
|
}>;
|
|
81
165
|
}
|
|
166
|
+
/** How the instance runs FGA reads and keeps its tuple change log. */
|
|
167
|
+
export interface FgaSettings {
|
|
168
|
+
object: 'fga.settings';
|
|
169
|
+
/** Result-cache TTL in ms; null uses the platform default, 0 turns the cache off. */
|
|
170
|
+
cache_ttl_ms: number | null;
|
|
171
|
+
/** Applied to reads that name no `consistency`. */
|
|
172
|
+
default_consistency: FgaConsistency;
|
|
173
|
+
/** Days of tuple change log kept; null keeps all of it. */
|
|
174
|
+
changelog_retention_days: number | null;
|
|
175
|
+
}
|
|
176
|
+
export type UpdateFgaSettingsBody = Partial<Omit<FgaSettings, 'object'>>;
|
|
82
177
|
export declare function fgaResource(request: RequestFn): {
|
|
178
|
+
settings: {
|
|
179
|
+
get(): Promise<FgaSettings>;
|
|
180
|
+
update(body: UpdateFgaSettingsBody): Promise<FgaSettings>;
|
|
181
|
+
};
|
|
83
182
|
stores: {
|
|
84
183
|
list(): Promise<ListPage<FgaStore>>;
|
|
85
184
|
create(body: {
|
|
@@ -97,14 +196,17 @@ export declare function fgaResource(request: RequestFn): {
|
|
|
97
196
|
create(storeId: string, body: FgaAuthorizationModelInput, idempotencyKey?: string): Promise<FgaAuthorizationModel>;
|
|
98
197
|
get(storeId: string, modelId: string): Promise<FgaAuthorizationModel>;
|
|
99
198
|
};
|
|
100
|
-
/** Write and/or delete tuples in one atomic call. */
|
|
199
|
+
/** Write and/or delete tuples in one atomic call. `on_duplicate` / `on_missing` = `error` refuse a repeat write or a delete of nothing. */
|
|
101
200
|
write(storeId: string, body: {
|
|
102
201
|
writes?: FgaTupleKeys;
|
|
103
202
|
deletes?: FgaTupleKeys;
|
|
203
|
+
on_duplicate?: "ignore" | "error";
|
|
204
|
+
on_missing?: "ignore" | "error";
|
|
104
205
|
}, idempotencyKey?: string): Promise<{
|
|
105
206
|
object: "fga.write_result";
|
|
106
207
|
writes: number;
|
|
107
208
|
deletes: number;
|
|
209
|
+
consistency_token: string;
|
|
108
210
|
}>;
|
|
109
211
|
/** Query stored tuples by any of user / relation / object. */
|
|
110
212
|
read(storeId: string, body: {
|
|
@@ -117,18 +219,106 @@ export declare function fgaResource(request: RequestFn): {
|
|
|
117
219
|
object: "fga.check";
|
|
118
220
|
allowed: boolean;
|
|
119
221
|
authorization_model_id: string;
|
|
222
|
+
consistency_token: string;
|
|
120
223
|
}>;
|
|
121
224
|
/** Resolve MANY access questions in one round trip (list-authorization UIs). */
|
|
122
225
|
batchCheck(storeId: string, body: {
|
|
123
226
|
checks: FgaBatchCheckItem[];
|
|
124
227
|
authorization_model_id?: string;
|
|
125
|
-
}): Promise<FgaBatchCheckResult>;
|
|
228
|
+
} & FgaConsistencyOptions): Promise<FgaBatchCheckResult>;
|
|
126
229
|
/** List the objects of a type a user has a relation to. */
|
|
127
230
|
listObjects(storeId: string, body: FgaListObjectsBody): Promise<{
|
|
128
231
|
object: "fga.list_objects";
|
|
129
232
|
objects: string[];
|
|
233
|
+
has_more: boolean;
|
|
234
|
+
next_cursor: string | null;
|
|
130
235
|
authorization_model_id: string;
|
|
236
|
+
consistency_token: string;
|
|
237
|
+
}>;
|
|
238
|
+
/**
|
|
239
|
+
* Who has a relation on an object: concrete users, usersets (give the filter
|
|
240
|
+
* a `relation`) and the `type:*` wildcard with `excluded_users`. One page.
|
|
241
|
+
*/
|
|
242
|
+
listUsers(storeId: string, body: FgaListUsersBody): Promise<FgaListUsersResult>;
|
|
243
|
+
/** {@link listUsers} following `continuation_token` until every page is collected. */
|
|
244
|
+
listAllUsers(storeId: string, body: FgaListUsersBody): Promise<FgaListUsersResult>;
|
|
245
|
+
/**
|
|
246
|
+
* The store's tuple change log, in commit order. The returned
|
|
247
|
+
* `continuation_token` works even on the last page: persist it and call again
|
|
248
|
+
* to receive only what changed since.
|
|
249
|
+
*/
|
|
250
|
+
readChanges(storeId: string, params?: FgaReadChangesParams): Promise<FgaChangesPage>;
|
|
251
|
+
/** What a local PDP syncs: a page of tuples (full), or the changes after `since` (a store revision). */
|
|
252
|
+
snapshot(storeId: string, params?: {
|
|
253
|
+
since?: number;
|
|
254
|
+
cursor?: string;
|
|
255
|
+
limit?: number;
|
|
256
|
+
}): Promise<FgaSnapshot>;
|
|
257
|
+
/** Bulk-import tuples (idempotent; `dry_run` reports without writing). */
|
|
258
|
+
importTuples(storeId: string, body: {
|
|
259
|
+
tuples: Array<FgaTupleKey>;
|
|
260
|
+
dry_run?: boolean;
|
|
261
|
+
}): Promise<{
|
|
262
|
+
object: "fga.import_result";
|
|
263
|
+
dry_run: boolean;
|
|
264
|
+
total: number;
|
|
265
|
+
new: number;
|
|
266
|
+
existing: number;
|
|
267
|
+
revision: number;
|
|
268
|
+
consistency_token?: string;
|
|
269
|
+
}>;
|
|
270
|
+
/** Run an FGA test suite in memory (the model from `dsl` / `modules`, or the store's). */
|
|
271
|
+
runTests(storeId: string, body: FgaTestSuite): Promise<FgaTestReport>;
|
|
272
|
+
/** The same, with no store: the model comes from `dsl` / `modules`. */
|
|
273
|
+
runTestsWithoutStore(body: FgaTestSuite): Promise<FgaTestReport>;
|
|
274
|
+
/** Validate a model and convert it DSL <-> JSON; `modules` compile to one model. */
|
|
275
|
+
transformModel(body: {
|
|
276
|
+
dsl?: string;
|
|
277
|
+
modules?: Array<{
|
|
278
|
+
name: string;
|
|
279
|
+
contents: string;
|
|
280
|
+
}>;
|
|
281
|
+
model?: Record<string, unknown>;
|
|
282
|
+
}): Promise<{
|
|
283
|
+
object: "fga.model_transform";
|
|
284
|
+
valid: true;
|
|
285
|
+
model: Record<string, unknown>;
|
|
286
|
+
dsl: string;
|
|
287
|
+
}>;
|
|
288
|
+
/** Nodes and edges of a model version, for a visualizer. */
|
|
289
|
+
modelGraph(storeId: string, modelId: string): Promise<{
|
|
290
|
+
object: "fga.model_graph";
|
|
291
|
+
model_id: string;
|
|
292
|
+
nodes: Array<{
|
|
293
|
+
id: string;
|
|
294
|
+
kind: "type" | "relation";
|
|
295
|
+
type: string;
|
|
296
|
+
relation?: string;
|
|
297
|
+
}>;
|
|
298
|
+
edges: Array<{
|
|
299
|
+
from: string;
|
|
300
|
+
to: string;
|
|
301
|
+
kind: "direct" | "computed" | "tupleset" | "parent";
|
|
302
|
+
label?: string;
|
|
303
|
+
}>;
|
|
131
304
|
}>;
|
|
305
|
+
/** What changed from the previous version (or `against`). */
|
|
306
|
+
modelDiff(storeId: string, modelId: string, against?: string): Promise<FgaModelDiff>;
|
|
307
|
+
/** OpenFGA assertions stored against a model version. */
|
|
308
|
+
assertions: {
|
|
309
|
+
get(storeId: string, modelId: string): Promise<{
|
|
310
|
+
authorization_model_id: string;
|
|
311
|
+
assertions: unknown[];
|
|
312
|
+
}>;
|
|
313
|
+
put(storeId: string, modelId: string, assertions: unknown[]): Promise<void>;
|
|
314
|
+
run(storeId: string, modelId: string): Promise<{
|
|
315
|
+
object: "fga.assertion_run";
|
|
316
|
+
passed: boolean;
|
|
317
|
+
total: number;
|
|
318
|
+
failed: number;
|
|
319
|
+
results: unknown[];
|
|
320
|
+
}>;
|
|
321
|
+
};
|
|
132
322
|
/** Expand the full userset tree for an object#relation. */
|
|
133
323
|
expand(storeId: string, body: {
|
|
134
324
|
object: string;
|
|
@@ -153,6 +343,7 @@ export declare function fgaResource(request: RequestFn): {
|
|
|
153
343
|
object: "fga.write_result";
|
|
154
344
|
writes: number;
|
|
155
345
|
deletes: number;
|
|
346
|
+
consistency_token: string;
|
|
156
347
|
}>;
|
|
157
348
|
read: (body: {
|
|
158
349
|
user?: string;
|
|
@@ -163,16 +354,23 @@ export declare function fgaResource(request: RequestFn): {
|
|
|
163
354
|
object: "fga.check";
|
|
164
355
|
allowed: boolean;
|
|
165
356
|
authorization_model_id: string;
|
|
357
|
+
consistency_token: string;
|
|
166
358
|
}>;
|
|
167
359
|
batchCheck: (body: {
|
|
168
360
|
checks: FgaBatchCheckItem[];
|
|
169
361
|
authorization_model_id?: string;
|
|
170
|
-
}) => Promise<FgaBatchCheckResult>;
|
|
362
|
+
} & FgaConsistencyOptions) => Promise<FgaBatchCheckResult>;
|
|
171
363
|
listObjects: (body: FgaListObjectsBody) => Promise<{
|
|
172
364
|
object: "fga.list_objects";
|
|
173
365
|
objects: string[];
|
|
366
|
+
has_more: boolean;
|
|
367
|
+
next_cursor: string | null;
|
|
174
368
|
authorization_model_id: string;
|
|
369
|
+
consistency_token: string;
|
|
175
370
|
}>;
|
|
371
|
+
listUsers: (body: FgaListUsersBody) => Promise<FgaListUsersResult>;
|
|
372
|
+
listAllUsers: (body: FgaListUsersBody) => Promise<FgaListUsersResult>;
|
|
373
|
+
readChanges: (params?: FgaReadChangesParams) => Promise<FgaChangesPage>;
|
|
176
374
|
expand: (body: {
|
|
177
375
|
object: string;
|
|
178
376
|
relation: string;
|
|
@@ -189,3 +387,101 @@ export declare function fgaResource(request: RequestFn): {
|
|
|
189
387
|
};
|
|
190
388
|
};
|
|
191
389
|
};
|
|
390
|
+
export interface FgaSnapshot {
|
|
391
|
+
object: 'fga.snapshot';
|
|
392
|
+
store_id: string;
|
|
393
|
+
model_id: string | null;
|
|
394
|
+
model: Record<string, unknown> | null;
|
|
395
|
+
full: boolean;
|
|
396
|
+
/** The store revision this snapshot is at; pass it back as `since`. */
|
|
397
|
+
revision: number;
|
|
398
|
+
tuples?: Array<FgaTupleKey>;
|
|
399
|
+
changes?: Array<FgaTupleKey & {
|
|
400
|
+
operation: 'write' | 'delete';
|
|
401
|
+
}>;
|
|
402
|
+
next_cursor?: string | null;
|
|
403
|
+
has_more: boolean;
|
|
404
|
+
}
|
|
405
|
+
export interface FgaTestSuite {
|
|
406
|
+
model_id?: string;
|
|
407
|
+
dsl?: string;
|
|
408
|
+
modules?: Array<{
|
|
409
|
+
name: string;
|
|
410
|
+
contents: string;
|
|
411
|
+
}>;
|
|
412
|
+
tuples?: Array<FgaTupleKey>;
|
|
413
|
+
tests: Array<{
|
|
414
|
+
name?: string;
|
|
415
|
+
tuples?: Array<FgaTupleKey>;
|
|
416
|
+
check?: Array<{
|
|
417
|
+
user: string;
|
|
418
|
+
object: string;
|
|
419
|
+
context?: Record<string, unknown>;
|
|
420
|
+
assertions: Record<string, boolean>;
|
|
421
|
+
}>;
|
|
422
|
+
list_objects?: Array<{
|
|
423
|
+
user: string;
|
|
424
|
+
type: string;
|
|
425
|
+
context?: Record<string, unknown>;
|
|
426
|
+
assertions: Record<string, string[]>;
|
|
427
|
+
}>;
|
|
428
|
+
list_users?: Array<{
|
|
429
|
+
object: string;
|
|
430
|
+
user_filter: {
|
|
431
|
+
type: string;
|
|
432
|
+
relation?: string;
|
|
433
|
+
} | Array<{
|
|
434
|
+
type: string;
|
|
435
|
+
relation?: string;
|
|
436
|
+
}>;
|
|
437
|
+
context?: Record<string, unknown>;
|
|
438
|
+
assertions: Record<string, {
|
|
439
|
+
users: string[];
|
|
440
|
+
}>;
|
|
441
|
+
}>;
|
|
442
|
+
}>;
|
|
443
|
+
}
|
|
444
|
+
export interface FgaTestReport {
|
|
445
|
+
object: 'fga.test_report';
|
|
446
|
+
passed: boolean;
|
|
447
|
+
total: number;
|
|
448
|
+
failed: number;
|
|
449
|
+
coverage: {
|
|
450
|
+
relations: number;
|
|
451
|
+
covered: number;
|
|
452
|
+
uncovered: string[];
|
|
453
|
+
};
|
|
454
|
+
results: Array<{
|
|
455
|
+
name: string;
|
|
456
|
+
passed: boolean;
|
|
457
|
+
checks: number;
|
|
458
|
+
failures: Array<{
|
|
459
|
+
kind: 'check' | 'list_objects' | 'list_users';
|
|
460
|
+
query: string;
|
|
461
|
+
expected: unknown;
|
|
462
|
+
actual: unknown;
|
|
463
|
+
error?: string;
|
|
464
|
+
}>;
|
|
465
|
+
}>;
|
|
466
|
+
}
|
|
467
|
+
export interface FgaModelDiff {
|
|
468
|
+
object: 'fga.model_diff';
|
|
469
|
+
from: string | null;
|
|
470
|
+
to: string;
|
|
471
|
+
types: {
|
|
472
|
+
added: string[];
|
|
473
|
+
removed: string[];
|
|
474
|
+
};
|
|
475
|
+
relations: {
|
|
476
|
+
added: string[];
|
|
477
|
+
removed: string[];
|
|
478
|
+
changed: string[];
|
|
479
|
+
};
|
|
480
|
+
conditions: {
|
|
481
|
+
added: string[];
|
|
482
|
+
removed: string[];
|
|
483
|
+
changed: string[];
|
|
484
|
+
};
|
|
485
|
+
breaking: boolean;
|
|
486
|
+
identical: boolean;
|
|
487
|
+
}
|
package/dist/client/fga.js
CHANGED
|
@@ -4,6 +4,14 @@ exports.fgaResource = fgaResource;
|
|
|
4
4
|
const request_1 = require("./request");
|
|
5
5
|
function fgaResource(request) {
|
|
6
6
|
const api = {
|
|
7
|
+
settings: {
|
|
8
|
+
get() {
|
|
9
|
+
return request({ method: 'GET', path: '/v1/fga/settings' });
|
|
10
|
+
},
|
|
11
|
+
update(body) {
|
|
12
|
+
return request({ method: 'PUT', path: '/v1/fga/settings', body });
|
|
13
|
+
},
|
|
14
|
+
},
|
|
7
15
|
stores: {
|
|
8
16
|
list() {
|
|
9
17
|
return request({ method: 'GET', path: '/v1/fga/stores' });
|
|
@@ -40,7 +48,7 @@ function fgaResource(request) {
|
|
|
40
48
|
});
|
|
41
49
|
},
|
|
42
50
|
},
|
|
43
|
-
/** Write and/or delete tuples in one atomic call. */
|
|
51
|
+
/** Write and/or delete tuples in one atomic call. `on_duplicate` / `on_missing` = `error` refuse a repeat write or a delete of nothing. */
|
|
44
52
|
write(storeId, body, idempotencyKey) {
|
|
45
53
|
return request({ method: 'POST', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/write`, body, idempotencyKey });
|
|
46
54
|
},
|
|
@@ -60,6 +68,75 @@ function fgaResource(request) {
|
|
|
60
68
|
listObjects(storeId, body) {
|
|
61
69
|
return request({ method: 'POST', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/list-objects`, body });
|
|
62
70
|
},
|
|
71
|
+
/**
|
|
72
|
+
* Who has a relation on an object: concrete users, usersets (give the filter
|
|
73
|
+
* a `relation`) and the `type:*` wildcard with `excluded_users`. One page.
|
|
74
|
+
*/
|
|
75
|
+
listUsers(storeId, body) {
|
|
76
|
+
return request({ method: 'POST', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/list-users`, body });
|
|
77
|
+
},
|
|
78
|
+
/** {@link listUsers} following `continuation_token` until every page is collected. */
|
|
79
|
+
async listAllUsers(storeId, body) {
|
|
80
|
+
let page = await api.listUsers(storeId, body);
|
|
81
|
+
const users = [...page.users];
|
|
82
|
+
while (page.continuation_token) {
|
|
83
|
+
page = await api.listUsers(storeId, { ...body, continuation_token: page.continuation_token });
|
|
84
|
+
users.push(...page.users);
|
|
85
|
+
}
|
|
86
|
+
return { ...page, users };
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* The store's tuple change log, in commit order. The returned
|
|
90
|
+
* `continuation_token` works even on the last page: persist it and call again
|
|
91
|
+
* to receive only what changed since.
|
|
92
|
+
*/
|
|
93
|
+
readChanges(storeId, params = {}) {
|
|
94
|
+
return request({
|
|
95
|
+
method: 'GET',
|
|
96
|
+
path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/changes`,
|
|
97
|
+
query: { ...params },
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
/** What a local PDP syncs: a page of tuples (full), or the changes after `since` (a store revision). */
|
|
101
|
+
snapshot(storeId, params = {}) {
|
|
102
|
+
return request({ method: 'GET', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/snapshot`, query: { ...params } });
|
|
103
|
+
},
|
|
104
|
+
/** Bulk-import tuples (idempotent; `dry_run` reports without writing). */
|
|
105
|
+
importTuples(storeId, body) {
|
|
106
|
+
return request({ method: 'POST', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/import`, body });
|
|
107
|
+
},
|
|
108
|
+
/** Run an FGA test suite in memory (the model from `dsl` / `modules`, or the store's). */
|
|
109
|
+
runTests(storeId, body) {
|
|
110
|
+
return request({ method: 'POST', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/tests`, body });
|
|
111
|
+
},
|
|
112
|
+
/** The same, with no store: the model comes from `dsl` / `modules`. */
|
|
113
|
+
runTestsWithoutStore(body) {
|
|
114
|
+
return request({ method: 'POST', path: '/v1/fga/tests', body });
|
|
115
|
+
},
|
|
116
|
+
/** Validate a model and convert it DSL <-> JSON; `modules` compile to one model. */
|
|
117
|
+
transformModel(body) {
|
|
118
|
+
return request({ method: 'POST', path: '/v1/fga/models/transform', body });
|
|
119
|
+
},
|
|
120
|
+
/** Nodes and edges of a model version, for a visualizer. */
|
|
121
|
+
modelGraph(storeId, modelId) {
|
|
122
|
+
return request({ method: 'GET', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/authorization-models/${(0, request_1.enc)(modelId)}/graph` });
|
|
123
|
+
},
|
|
124
|
+
/** What changed from the previous version (or `against`). */
|
|
125
|
+
modelDiff(storeId, modelId, against) {
|
|
126
|
+
return request({ method: 'GET', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/authorization-models/${(0, request_1.enc)(modelId)}/diff`, query: { against } });
|
|
127
|
+
},
|
|
128
|
+
/** OpenFGA assertions stored against a model version. */
|
|
129
|
+
assertions: {
|
|
130
|
+
get(storeId, modelId) {
|
|
131
|
+
return request({ method: 'GET', path: `/v1/openfga/stores/${(0, request_1.enc)(storeId)}/assertions/${(0, request_1.enc)(modelId)}` });
|
|
132
|
+
},
|
|
133
|
+
put(storeId, modelId, assertions) {
|
|
134
|
+
return request({ method: 'PUT', path: `/v1/openfga/stores/${(0, request_1.enc)(storeId)}/assertions/${(0, request_1.enc)(modelId)}`, body: { assertions } });
|
|
135
|
+
},
|
|
136
|
+
run(storeId, modelId) {
|
|
137
|
+
return request({ method: 'POST', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/authorization-models/${(0, request_1.enc)(modelId)}/assertions/run` });
|
|
138
|
+
},
|
|
139
|
+
},
|
|
63
140
|
/** Expand the full userset tree for an object#relation. */
|
|
64
141
|
expand(storeId, body) {
|
|
65
142
|
return request({ method: 'POST', path: `/v1/fga/stores/${(0, request_1.enc)(storeId)}/expand`, body });
|
|
@@ -77,6 +154,9 @@ function fgaResource(request) {
|
|
|
77
154
|
check: (body) => api.check(storeId, body),
|
|
78
155
|
batchCheck: (body) => api.batchCheck(storeId, body),
|
|
79
156
|
listObjects: (body) => api.listObjects(storeId, body),
|
|
157
|
+
listUsers: (body) => api.listUsers(storeId, body),
|
|
158
|
+
listAllUsers: (body) => api.listAllUsers(storeId, body),
|
|
159
|
+
readChanges: (params) => api.readChanges(storeId, params),
|
|
80
160
|
expand: (body) => api.expand(storeId, body),
|
|
81
161
|
models: {
|
|
82
162
|
list: () => api.models.list(storeId),
|
package/dist/client/fga.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fga.js","sourceRoot":"","sources":["../../src/client/fga.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"fga.js","sourceRoot":"","sources":["../../src/client/fga.ts"],"names":[],"mappings":"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"}
|