@objectstack/plugin-security 9.9.1 → 9.11.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/dist/index.d.mts +253 -22
- package/dist/index.d.ts +253 -22
- package/dist/index.js +310 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +307 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -89,6 +89,8 @@ declare class SecurityPlugin implements Plugin {
|
|
|
89
89
|
*/
|
|
90
90
|
private metadata;
|
|
91
91
|
private ql;
|
|
92
|
+
/** ADR-0055: cache the resolved master-detail relation per controlled_by_parent object. */
|
|
93
|
+
private cbpRelCache;
|
|
92
94
|
private dbLoader?;
|
|
93
95
|
private logger;
|
|
94
96
|
constructor(options?: SecurityPluginOptions);
|
|
@@ -143,6 +145,45 @@ declare class SecurityPlugin implements Plugin {
|
|
|
143
145
|
* applies (caller adds no filter).
|
|
144
146
|
*/
|
|
145
147
|
private computeRlsFilter;
|
|
148
|
+
/**
|
|
149
|
+
* Resolve a controlled_by_parent object's master-detail relation (the FK field
|
|
150
|
+
* key + the master object name), or null. Prefers a required `master_detail`
|
|
151
|
+
* field; falls back to any `master_detail`, then a required `lookup`. Cached.
|
|
152
|
+
*/
|
|
153
|
+
private resolveCbpRelation;
|
|
154
|
+
/**
|
|
155
|
+
* ADR-0055 — master-detail "controlled by parent" READ derivation.
|
|
156
|
+
*
|
|
157
|
+
* For an object whose `sharingModel` is `controlled_by_parent`, access is
|
|
158
|
+
* derived from the master: return a filter `masterFK IN (<master ids this user
|
|
159
|
+
* can read>)`. The id set is resolved by running the MASTER's own read RLS
|
|
160
|
+
* (reused via `computeRlsFilter`) under a system context — no middleware
|
|
161
|
+
* re-entry, so no recursion. An empty set yields `{ masterFK: { $in: [] } }`,
|
|
162
|
+
* which matches no rows (fail closed). A misconfigured object (no
|
|
163
|
+
* master_detail/lookup to derive from) denies all reads (defense-in-depth;
|
|
164
|
+
* spec validation should prevent authoring it). Returns null when the object is
|
|
165
|
+
* not controlled_by_parent.
|
|
166
|
+
*
|
|
167
|
+
* v1 scope (ADR-0055): single level — the master's OWN controlled_by_parent is
|
|
168
|
+
* not traversed transitively; master accessibility is the master's RLS filter
|
|
169
|
+
* (sharing-service grants on the master are not folded in).
|
|
170
|
+
*/
|
|
171
|
+
private computeControlledByParentFilter;
|
|
172
|
+
/**
|
|
173
|
+
* ADR-0055 — master-detail "controlled by parent" WRITE enforcement.
|
|
174
|
+
*
|
|
175
|
+
* A by-id write (insert/update/delete) to a controlled_by_parent detail
|
|
176
|
+
* requires EDIT access to its master: the caller must hold CRUD `update` on the
|
|
177
|
+
* master object AND the master row must be visible under the master's write RLS.
|
|
178
|
+
* This is the write-side companion to the read derivation — the RLS read filter
|
|
179
|
+
* never applies to a by-id write (the #1994 class), so without this a member
|
|
180
|
+
* could mutate a detail under a master they cannot edit. Throws on denial;
|
|
181
|
+
* no-op when the object is not controlled_by_parent.
|
|
182
|
+
*
|
|
183
|
+
* v1 scope: single-id writes. Bulk writes flow through the AST and are already
|
|
184
|
+
* scoped by the controlled-by-parent READ filter (to readable masters).
|
|
185
|
+
*/
|
|
186
|
+
private assertControlledByParentWrite;
|
|
146
187
|
/**
|
|
147
188
|
* Collect all RLS policies from permission sets applicable to the given object/operation.
|
|
148
189
|
*/
|
|
@@ -230,9 +271,19 @@ interface RLSUserContext {
|
|
|
230
271
|
* current user (incl. self). Pre-resolved by the runtime so RLS can
|
|
231
272
|
* scope identity tables like `sys_user` via
|
|
232
273
|
* `id IN (current_user.org_user_ids)` without needing subquery
|
|
233
|
-
* support in the compiler.
|
|
274
|
+
* support in the compiler. This is the one well-known membership set;
|
|
275
|
+
* arbitrary §7.3.1 sets arrive via `ExecutionContext.rlsMembership`
|
|
276
|
+
* and are merged in under their own keys (see {@link RLSCompiler.compileFilter}).
|
|
234
277
|
*/
|
|
235
278
|
org_user_ids?: string[];
|
|
279
|
+
/**
|
|
280
|
+
* The caller's unique, auth-enforced email. RLS expressions reference it as
|
|
281
|
+
* `current_user.email` for human-readable, *seedable* owner scoping
|
|
282
|
+
* (`owner = current_user.email`). Email is exposed because it is UNIQUE; the
|
|
283
|
+
* user's display `name` is deliberately NOT exposed — names collide, and a
|
|
284
|
+
* collision on an ownership predicate is an access-control leak.
|
|
285
|
+
*/
|
|
286
|
+
email?: string;
|
|
236
287
|
[key: string]: unknown;
|
|
237
288
|
}
|
|
238
289
|
/**
|
|
@@ -258,6 +309,11 @@ declare const RLS_DENY_FILTER: Record<string, unknown>;
|
|
|
258
309
|
* Converts `using` / `check` expressions into ObjectQL-compatible filter conditions.
|
|
259
310
|
*/
|
|
260
311
|
declare class RLSCompiler {
|
|
312
|
+
/** Optional logger so a SILENTLY-dropped (uncompilable-shape) policy is observable (ADR-0056 D4). */
|
|
313
|
+
private logger?;
|
|
314
|
+
setLogger(logger: {
|
|
315
|
+
warn?: (message: string, meta?: Record<string, unknown>) => void;
|
|
316
|
+
} | undefined): void;
|
|
261
317
|
/**
|
|
262
318
|
* Compile RLS policies into a query filter for the given user context.
|
|
263
319
|
* Multiple policies for the same object/operation are OR-combined (any match allows access).
|
|
@@ -275,10 +331,17 @@ declare class RLSCompiler {
|
|
|
275
331
|
/**
|
|
276
332
|
* Compile a single RLS expression into a query filter.
|
|
277
333
|
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* -
|
|
281
|
-
* -
|
|
334
|
+
* This reference compiler recognizes exactly four forms — anything else
|
|
335
|
+
* returns `null` and (via {@link compileFilter}) fails closed:
|
|
336
|
+
* - `field = current_user.property` → `{ field: <value> }`
|
|
337
|
+
* - `field = 'literal_value'` → `{ field: 'literal_value' }`
|
|
338
|
+
* - `field IN (current_user.array)` → `{ field: { $in: [...] } }`
|
|
339
|
+
* (the array may be a §7.3.1 pre-resolved membership set)
|
|
340
|
+
* - `1 = 1` → `{}` (always-true / no restriction)
|
|
341
|
+
*
|
|
342
|
+
* There is intentionally no support for subqueries, `LIKE`/`ILIKE`,
|
|
343
|
+
* regex, `ANY`/`ALL`, `AND`/`OR`/`NOT`, or `NULL` checks — express those
|
|
344
|
+
* needs as a `current_user.*` property the runtime pre-resolves instead.
|
|
282
345
|
*/
|
|
283
346
|
compileExpression(expression: string, userCtx: RLSUserContext): Record<string, unknown> | null;
|
|
284
347
|
/**
|
|
@@ -355,7 +418,7 @@ declare const securityObjects: ((Omit<{
|
|
|
355
418
|
abstract: boolean;
|
|
356
419
|
datasource: string;
|
|
357
420
|
fields: Record<string, {
|
|
358
|
-
type: "number" | "boolean" | "tags" | "select" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "
|
|
421
|
+
type: "number" | "boolean" | "tags" | "select" | "email" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "time" | "text" | "textarea" | "phone" | "markdown" | "html" | "richtext" | "toggle" | "multiselect" | "radio" | "checkboxes" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "composite" | "repeater" | "location" | "address" | "json" | "color" | "rating" | "slider" | "qrcode" | "vector";
|
|
359
422
|
required: boolean;
|
|
360
423
|
searchable: boolean;
|
|
361
424
|
multiple: boolean;
|
|
@@ -561,7 +624,7 @@ declare const securityObjects: ((Omit<{
|
|
|
561
624
|
description?: string | undefined;
|
|
562
625
|
icon?: string | undefined;
|
|
563
626
|
tags?: string[] | undefined;
|
|
564
|
-
managedBy?: "
|
|
627
|
+
managedBy?: "platform" | "system" | "config" | "append-only" | "better-auth" | undefined;
|
|
565
628
|
userActions?: {
|
|
566
629
|
create?: boolean | undefined;
|
|
567
630
|
import?: boolean | undefined;
|
|
@@ -790,6 +853,29 @@ declare const securityObjects: ((Omit<{
|
|
|
790
853
|
titleField: string;
|
|
791
854
|
progressField?: string | undefined;
|
|
792
855
|
dependenciesField?: string | undefined;
|
|
856
|
+
colorField?: string | undefined;
|
|
857
|
+
parentField?: string | undefined;
|
|
858
|
+
typeField?: string | undefined;
|
|
859
|
+
baselineStartField?: string | undefined;
|
|
860
|
+
baselineEndField?: string | undefined;
|
|
861
|
+
groupByField?: string | undefined;
|
|
862
|
+
resourceView?: boolean | undefined;
|
|
863
|
+
assigneeField?: string | undefined;
|
|
864
|
+
effortField?: string | undefined;
|
|
865
|
+
capacity?: number | undefined;
|
|
866
|
+
tooltipFields?: (string | {
|
|
867
|
+
field: string;
|
|
868
|
+
label?: string | undefined;
|
|
869
|
+
})[] | undefined;
|
|
870
|
+
quickFilters?: {
|
|
871
|
+
field: string;
|
|
872
|
+
label?: string | undefined;
|
|
873
|
+
options?: (string | {
|
|
874
|
+
value: string | number;
|
|
875
|
+
label?: string | undefined;
|
|
876
|
+
})[] | undefined;
|
|
877
|
+
}[] | undefined;
|
|
878
|
+
autoZoomToFilter?: boolean | undefined;
|
|
793
879
|
} | undefined;
|
|
794
880
|
gallery?: {
|
|
795
881
|
coverFit: "cover" | "contain";
|
|
@@ -953,7 +1039,7 @@ declare const securityObjects: ((Omit<{
|
|
|
953
1039
|
clone: boolean;
|
|
954
1040
|
apiMethods?: ("aggregate" | "update" | "delete" | "restore" | "purge" | "search" | "create" | "import" | "list" | "get" | "upsert" | "bulk" | "history" | "export")[] | undefined;
|
|
955
1041
|
} | undefined;
|
|
956
|
-
sharingModel?: "full" | "read" | "private" | "read_write" | undefined;
|
|
1042
|
+
sharingModel?: "full" | "read" | "private" | "public_read" | "public_read_write" | "controlled_by_parent" | "read_write" | undefined;
|
|
957
1043
|
publicSharing?: {
|
|
958
1044
|
enabled: boolean;
|
|
959
1045
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -985,7 +1071,7 @@ declare const securityObjects: ((Omit<{
|
|
|
985
1071
|
} | {
|
|
986
1072
|
language: "js";
|
|
987
1073
|
source: string;
|
|
988
|
-
capabilities: ("api.read" | "api.write" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
1074
|
+
capabilities: ("api.read" | "api.write" | "api.transaction" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
989
1075
|
timeoutMs?: number | undefined;
|
|
990
1076
|
memoryMb?: number | undefined;
|
|
991
1077
|
} | undefined;
|
|
@@ -2677,7 +2763,7 @@ declare const securityObjects: ((Omit<{
|
|
|
2677
2763
|
abstract: boolean;
|
|
2678
2764
|
datasource: string;
|
|
2679
2765
|
fields: Record<string, {
|
|
2680
|
-
type: "number" | "boolean" | "tags" | "select" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "
|
|
2766
|
+
type: "number" | "boolean" | "tags" | "select" | "email" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "time" | "text" | "textarea" | "phone" | "markdown" | "html" | "richtext" | "toggle" | "multiselect" | "radio" | "checkboxes" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "composite" | "repeater" | "location" | "address" | "json" | "color" | "rating" | "slider" | "qrcode" | "vector";
|
|
2681
2767
|
required: boolean;
|
|
2682
2768
|
searchable: boolean;
|
|
2683
2769
|
multiple: boolean;
|
|
@@ -2883,7 +2969,7 @@ declare const securityObjects: ((Omit<{
|
|
|
2883
2969
|
description?: string | undefined;
|
|
2884
2970
|
icon?: string | undefined;
|
|
2885
2971
|
tags?: string[] | undefined;
|
|
2886
|
-
managedBy?: "
|
|
2972
|
+
managedBy?: "platform" | "system" | "config" | "append-only" | "better-auth" | undefined;
|
|
2887
2973
|
userActions?: {
|
|
2888
2974
|
create?: boolean | undefined;
|
|
2889
2975
|
import?: boolean | undefined;
|
|
@@ -3112,6 +3198,29 @@ declare const securityObjects: ((Omit<{
|
|
|
3112
3198
|
titleField: string;
|
|
3113
3199
|
progressField?: string | undefined;
|
|
3114
3200
|
dependenciesField?: string | undefined;
|
|
3201
|
+
colorField?: string | undefined;
|
|
3202
|
+
parentField?: string | undefined;
|
|
3203
|
+
typeField?: string | undefined;
|
|
3204
|
+
baselineStartField?: string | undefined;
|
|
3205
|
+
baselineEndField?: string | undefined;
|
|
3206
|
+
groupByField?: string | undefined;
|
|
3207
|
+
resourceView?: boolean | undefined;
|
|
3208
|
+
assigneeField?: string | undefined;
|
|
3209
|
+
effortField?: string | undefined;
|
|
3210
|
+
capacity?: number | undefined;
|
|
3211
|
+
tooltipFields?: (string | {
|
|
3212
|
+
field: string;
|
|
3213
|
+
label?: string | undefined;
|
|
3214
|
+
})[] | undefined;
|
|
3215
|
+
quickFilters?: {
|
|
3216
|
+
field: string;
|
|
3217
|
+
label?: string | undefined;
|
|
3218
|
+
options?: (string | {
|
|
3219
|
+
value: string | number;
|
|
3220
|
+
label?: string | undefined;
|
|
3221
|
+
})[] | undefined;
|
|
3222
|
+
}[] | undefined;
|
|
3223
|
+
autoZoomToFilter?: boolean | undefined;
|
|
3115
3224
|
} | undefined;
|
|
3116
3225
|
gallery?: {
|
|
3117
3226
|
coverFit: "cover" | "contain";
|
|
@@ -3275,7 +3384,7 @@ declare const securityObjects: ((Omit<{
|
|
|
3275
3384
|
clone: boolean;
|
|
3276
3385
|
apiMethods?: ("aggregate" | "update" | "delete" | "restore" | "purge" | "search" | "create" | "import" | "list" | "get" | "upsert" | "bulk" | "history" | "export")[] | undefined;
|
|
3277
3386
|
} | undefined;
|
|
3278
|
-
sharingModel?: "full" | "read" | "private" | "read_write" | undefined;
|
|
3387
|
+
sharingModel?: "full" | "read" | "private" | "public_read" | "public_read_write" | "controlled_by_parent" | "read_write" | undefined;
|
|
3279
3388
|
publicSharing?: {
|
|
3280
3389
|
enabled: boolean;
|
|
3281
3390
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -3307,7 +3416,7 @@ declare const securityObjects: ((Omit<{
|
|
|
3307
3416
|
} | {
|
|
3308
3417
|
language: "js";
|
|
3309
3418
|
source: string;
|
|
3310
|
-
capabilities: ("api.read" | "api.write" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
3419
|
+
capabilities: ("api.read" | "api.write" | "api.transaction" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
3311
3420
|
timeoutMs?: number | undefined;
|
|
3312
3421
|
memoryMb?: number | undefined;
|
|
3313
3422
|
} | undefined;
|
|
@@ -5428,7 +5537,7 @@ declare const securityObjects: ((Omit<{
|
|
|
5428
5537
|
abstract: boolean;
|
|
5429
5538
|
datasource: string;
|
|
5430
5539
|
fields: Record<string, {
|
|
5431
|
-
type: "number" | "boolean" | "tags" | "select" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "
|
|
5540
|
+
type: "number" | "boolean" | "tags" | "select" | "email" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "time" | "text" | "textarea" | "phone" | "markdown" | "html" | "richtext" | "toggle" | "multiselect" | "radio" | "checkboxes" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "composite" | "repeater" | "location" | "address" | "json" | "color" | "rating" | "slider" | "qrcode" | "vector";
|
|
5432
5541
|
required: boolean;
|
|
5433
5542
|
searchable: boolean;
|
|
5434
5543
|
multiple: boolean;
|
|
@@ -5634,7 +5743,7 @@ declare const securityObjects: ((Omit<{
|
|
|
5634
5743
|
description?: string | undefined;
|
|
5635
5744
|
icon?: string | undefined;
|
|
5636
5745
|
tags?: string[] | undefined;
|
|
5637
|
-
managedBy?: "
|
|
5746
|
+
managedBy?: "platform" | "system" | "config" | "append-only" | "better-auth" | undefined;
|
|
5638
5747
|
userActions?: {
|
|
5639
5748
|
create?: boolean | undefined;
|
|
5640
5749
|
import?: boolean | undefined;
|
|
@@ -5863,6 +5972,29 @@ declare const securityObjects: ((Omit<{
|
|
|
5863
5972
|
titleField: string;
|
|
5864
5973
|
progressField?: string | undefined;
|
|
5865
5974
|
dependenciesField?: string | undefined;
|
|
5975
|
+
colorField?: string | undefined;
|
|
5976
|
+
parentField?: string | undefined;
|
|
5977
|
+
typeField?: string | undefined;
|
|
5978
|
+
baselineStartField?: string | undefined;
|
|
5979
|
+
baselineEndField?: string | undefined;
|
|
5980
|
+
groupByField?: string | undefined;
|
|
5981
|
+
resourceView?: boolean | undefined;
|
|
5982
|
+
assigneeField?: string | undefined;
|
|
5983
|
+
effortField?: string | undefined;
|
|
5984
|
+
capacity?: number | undefined;
|
|
5985
|
+
tooltipFields?: (string | {
|
|
5986
|
+
field: string;
|
|
5987
|
+
label?: string | undefined;
|
|
5988
|
+
})[] | undefined;
|
|
5989
|
+
quickFilters?: {
|
|
5990
|
+
field: string;
|
|
5991
|
+
label?: string | undefined;
|
|
5992
|
+
options?: (string | {
|
|
5993
|
+
value: string | number;
|
|
5994
|
+
label?: string | undefined;
|
|
5995
|
+
})[] | undefined;
|
|
5996
|
+
}[] | undefined;
|
|
5997
|
+
autoZoomToFilter?: boolean | undefined;
|
|
5866
5998
|
} | undefined;
|
|
5867
5999
|
gallery?: {
|
|
5868
6000
|
coverFit: "cover" | "contain";
|
|
@@ -6026,7 +6158,7 @@ declare const securityObjects: ((Omit<{
|
|
|
6026
6158
|
clone: boolean;
|
|
6027
6159
|
apiMethods?: ("aggregate" | "update" | "delete" | "restore" | "purge" | "search" | "create" | "import" | "list" | "get" | "upsert" | "bulk" | "history" | "export")[] | undefined;
|
|
6028
6160
|
} | undefined;
|
|
6029
|
-
sharingModel?: "full" | "read" | "private" | "read_write" | undefined;
|
|
6161
|
+
sharingModel?: "full" | "read" | "private" | "public_read" | "public_read_write" | "controlled_by_parent" | "read_write" | undefined;
|
|
6030
6162
|
publicSharing?: {
|
|
6031
6163
|
enabled: boolean;
|
|
6032
6164
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -6058,7 +6190,7 @@ declare const securityObjects: ((Omit<{
|
|
|
6058
6190
|
} | {
|
|
6059
6191
|
language: "js";
|
|
6060
6192
|
source: string;
|
|
6061
|
-
capabilities: ("api.read" | "api.write" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
6193
|
+
capabilities: ("api.read" | "api.write" | "api.transaction" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
6062
6194
|
timeoutMs?: number | undefined;
|
|
6063
6195
|
memoryMb?: number | undefined;
|
|
6064
6196
|
} | undefined;
|
|
@@ -7271,7 +7403,7 @@ declare const securityObjects: ((Omit<{
|
|
|
7271
7403
|
abstract: boolean;
|
|
7272
7404
|
datasource: string;
|
|
7273
7405
|
fields: Record<string, {
|
|
7274
|
-
type: "number" | "boolean" | "tags" | "select" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "
|
|
7406
|
+
type: "number" | "boolean" | "tags" | "select" | "email" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "lookup" | "master_detail" | "currency" | "percent" | "password" | "secret" | "time" | "text" | "textarea" | "phone" | "markdown" | "html" | "richtext" | "toggle" | "multiselect" | "radio" | "checkboxes" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "composite" | "repeater" | "location" | "address" | "json" | "color" | "rating" | "slider" | "qrcode" | "vector";
|
|
7275
7407
|
required: boolean;
|
|
7276
7408
|
searchable: boolean;
|
|
7277
7409
|
multiple: boolean;
|
|
@@ -7477,7 +7609,7 @@ declare const securityObjects: ((Omit<{
|
|
|
7477
7609
|
description?: string | undefined;
|
|
7478
7610
|
icon?: string | undefined;
|
|
7479
7611
|
tags?: string[] | undefined;
|
|
7480
|
-
managedBy?: "
|
|
7612
|
+
managedBy?: "platform" | "system" | "config" | "append-only" | "better-auth" | undefined;
|
|
7481
7613
|
userActions?: {
|
|
7482
7614
|
create?: boolean | undefined;
|
|
7483
7615
|
import?: boolean | undefined;
|
|
@@ -7706,6 +7838,29 @@ declare const securityObjects: ((Omit<{
|
|
|
7706
7838
|
titleField: string;
|
|
7707
7839
|
progressField?: string | undefined;
|
|
7708
7840
|
dependenciesField?: string | undefined;
|
|
7841
|
+
colorField?: string | undefined;
|
|
7842
|
+
parentField?: string | undefined;
|
|
7843
|
+
typeField?: string | undefined;
|
|
7844
|
+
baselineStartField?: string | undefined;
|
|
7845
|
+
baselineEndField?: string | undefined;
|
|
7846
|
+
groupByField?: string | undefined;
|
|
7847
|
+
resourceView?: boolean | undefined;
|
|
7848
|
+
assigneeField?: string | undefined;
|
|
7849
|
+
effortField?: string | undefined;
|
|
7850
|
+
capacity?: number | undefined;
|
|
7851
|
+
tooltipFields?: (string | {
|
|
7852
|
+
field: string;
|
|
7853
|
+
label?: string | undefined;
|
|
7854
|
+
})[] | undefined;
|
|
7855
|
+
quickFilters?: {
|
|
7856
|
+
field: string;
|
|
7857
|
+
label?: string | undefined;
|
|
7858
|
+
options?: (string | {
|
|
7859
|
+
value: string | number;
|
|
7860
|
+
label?: string | undefined;
|
|
7861
|
+
})[] | undefined;
|
|
7862
|
+
}[] | undefined;
|
|
7863
|
+
autoZoomToFilter?: boolean | undefined;
|
|
7709
7864
|
} | undefined;
|
|
7710
7865
|
gallery?: {
|
|
7711
7866
|
coverFit: "cover" | "contain";
|
|
@@ -7869,7 +8024,7 @@ declare const securityObjects: ((Omit<{
|
|
|
7869
8024
|
clone: boolean;
|
|
7870
8025
|
apiMethods?: ("aggregate" | "update" | "delete" | "restore" | "purge" | "search" | "create" | "import" | "list" | "get" | "upsert" | "bulk" | "history" | "export")[] | undefined;
|
|
7871
8026
|
} | undefined;
|
|
7872
|
-
sharingModel?: "full" | "read" | "private" | "read_write" | undefined;
|
|
8027
|
+
sharingModel?: "full" | "read" | "private" | "public_read" | "public_read_write" | "controlled_by_parent" | "read_write" | undefined;
|
|
7873
8028
|
publicSharing?: {
|
|
7874
8029
|
enabled: boolean;
|
|
7875
8030
|
allowedAudiences?: ("email" | "public" | "link_only" | "signed_in")[] | undefined;
|
|
@@ -7901,7 +8056,7 @@ declare const securityObjects: ((Omit<{
|
|
|
7901
8056
|
} | {
|
|
7902
8057
|
language: "js";
|
|
7903
8058
|
source: string;
|
|
7904
|
-
capabilities: ("api.read" | "api.write" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
8059
|
+
capabilities: ("api.read" | "api.write" | "api.transaction" | "crypto.uuid" | "crypto.hash" | "log")[];
|
|
7905
8060
|
timeoutMs?: number | undefined;
|
|
7906
8061
|
memoryMb?: number | undefined;
|
|
7907
8062
|
} | undefined;
|
|
@@ -8800,6 +8955,7 @@ declare const securityObjects: ((Omit<{
|
|
|
8800
8955
|
declare const securityDefaultPermissionSets: {
|
|
8801
8956
|
name: string;
|
|
8802
8957
|
isProfile: boolean;
|
|
8958
|
+
isDefault: boolean;
|
|
8803
8959
|
objects: Record<string, {
|
|
8804
8960
|
allowCreate: boolean;
|
|
8805
8961
|
allowRead: boolean;
|
|
@@ -8884,4 +9040,79 @@ declare function backfillOrgAdminGrants(ql: any, options?: {
|
|
|
8884
9040
|
skipped: number;
|
|
8885
9041
|
}>;
|
|
8886
9042
|
|
|
8887
|
-
|
|
9043
|
+
/**
|
|
9044
|
+
* bootstrapPlatformAdmin — first-boot platform admin promotion.
|
|
9045
|
+
*
|
|
9046
|
+
* Two responsibilities, both idempotent and run on `kernel:ready`:
|
|
9047
|
+
*
|
|
9048
|
+
* 1. **Seed `sys_permission_set` rows** for each `defaultPermissionSets`
|
|
9049
|
+
* entry (admin_full_access / member_default / viewer_readonly).
|
|
9050
|
+
*
|
|
9051
|
+
* 2. **Promote the first registered user to platform admin** by
|
|
9052
|
+
* inserting a `sys_user_permission_set` row that points at
|
|
9053
|
+
* `admin_full_access` with `organization_id = NULL` (= cross-tenant).
|
|
9054
|
+
* If a platform admin already exists, this is a no-op forever.
|
|
9055
|
+
*
|
|
9056
|
+
* The "create a Default Organization for the freshly-promoted admin"
|
|
9057
|
+
* behavior moved to `@objectstack/plugin-org-scoping` (see
|
|
9058
|
+
* `ensureDefaultOrganization`). Install that plugin to get
|
|
9059
|
+
* multi-tenant bootstrap.
|
|
9060
|
+
*/
|
|
9061
|
+
|
|
9062
|
+
interface BootstrapOptions {
|
|
9063
|
+
/** Logger from PluginContext. */
|
|
9064
|
+
logger?: {
|
|
9065
|
+
info: (message: string, meta?: Record<string, any>) => void;
|
|
9066
|
+
warn: (message: string, meta?: Record<string, any>) => void;
|
|
9067
|
+
};
|
|
9068
|
+
}
|
|
9069
|
+
/**
|
|
9070
|
+
* Persist seed permission sets and promote the first registered user to
|
|
9071
|
+
* platform admin. Safe to call multiple times.
|
|
9072
|
+
*/
|
|
9073
|
+
declare function bootstrapPlatformAdmin(ql: any, bootstrapPermissionSets: PermissionSet[], options?: BootstrapOptions): Promise<{
|
|
9074
|
+
seeded: number;
|
|
9075
|
+
adminPromoted: boolean;
|
|
9076
|
+
reason?: string;
|
|
9077
|
+
/** Count of seeded rows re-owned to the freshly-promoted admin. */
|
|
9078
|
+
ownershipClaimed?: number;
|
|
9079
|
+
}>;
|
|
9080
|
+
|
|
9081
|
+
interface ClaimOwnershipOptions {
|
|
9082
|
+
logger?: {
|
|
9083
|
+
info: (message: string, meta?: Record<string, any>) => void;
|
|
9084
|
+
warn: (message: string, meta?: Record<string, any>) => void;
|
|
9085
|
+
};
|
|
9086
|
+
}
|
|
9087
|
+
/**
|
|
9088
|
+
* Re-own every orphan seed row (owner_id NULL or usr_system) to `adminUserId`.
|
|
9089
|
+
*
|
|
9090
|
+
* Walks `ql.registry.getAllObjects()`, filters to schemas that
|
|
9091
|
+
* (a) are not `managedBy` (skip sys_/auth/platform tables),
|
|
9092
|
+
* (b) are not `sys_*`-namespaced,
|
|
9093
|
+
* (c) declare an `owner_id` field,
|
|
9094
|
+
* and updates the unowned rows as `isSystem`. Returns a per-object summary.
|
|
9095
|
+
*/
|
|
9096
|
+
declare function claimSeedOwnership(ql: any, adminUserId: string, options?: ClaimOwnershipOptions): Promise<{
|
|
9097
|
+
object: string;
|
|
9098
|
+
count: number;
|
|
9099
|
+
}[]>;
|
|
9100
|
+
|
|
9101
|
+
/**
|
|
9102
|
+
* ADR-0056 D7 — resolve the app-declared default profile NAME from a stack's
|
|
9103
|
+
* `permissions[]` array.
|
|
9104
|
+
*
|
|
9105
|
+
* A permission set marked `isProfile && isDefault` declares the app's default
|
|
9106
|
+
* access posture for users with no explicit grants. The {@link SecurityPlugin}
|
|
9107
|
+
* constructor scans its `defaultPermissionSets` option for that flag — but the
|
|
9108
|
+
* CLI constructs `new SecurityPlugin()` with NO options, so an `isDefault`
|
|
9109
|
+
* profile declared purely in app METADATA would never be honored. The CLI calls
|
|
9110
|
+
* this helper to pull the name out of the stack and pass it as
|
|
9111
|
+
* `fallbackPermissionSet`, wiring the declaration through to `pnpm dev`.
|
|
9112
|
+
*
|
|
9113
|
+
* Returns the first matching profile's `name`, or `undefined` when none is
|
|
9114
|
+
* declared (callers then keep the built-in `member_default` fallback).
|
|
9115
|
+
*/
|
|
9116
|
+
declare function appDefaultProfileName(permissions: unknown): string | undefined;
|
|
9117
|
+
|
|
9118
|
+
export { FieldMasker, PermissionDeniedError, PermissionEvaluator, RLSCompiler, RLS_DENY_FILTER, SECURITY_PLUGIN_ID, SECURITY_PLUGIN_VERSION, SecurityPlugin, appDefaultProfileName, backfillOrgAdminGrants, bootstrapPlatformAdmin, claimSeedOwnership, isPermissionDeniedError, reconcileOrgAdminGrant, securityDefaultPermissionSets, securityObjects, securityPluginManifestHeader };
|