@spotto/contract 1.0.70-alpha.13 → 1.0.70-alpha.15

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 (53) hide show
  1. package/dist/actions/[id]/patch/request.d.ts +4 -0
  2. package/dist/actions/get/response.d.ts +4 -0
  3. package/dist/assets/download/query.d.ts +7 -0
  4. package/dist/assets/get/query.d.ts +2 -0
  5. package/dist/fields/[id]/get.d.ts +3 -0
  6. package/dist/fields/[id]/patch/request.d.ts +4 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +1 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/locations/get/query.d.ts +2 -0
  11. package/dist/organisations/constants.d.ts +11 -0
  12. package/dist/usergroups/[id]/index.d.ts +1 -0
  13. package/dist/usergroups/[id]/index.js +18 -0
  14. package/dist/usergroups/[id]/index.js.map +1 -0
  15. package/dist/usergroups/[id]/patch/index.d.ts +2 -0
  16. package/dist/usergroups/[id]/patch/index.js +19 -0
  17. package/dist/usergroups/[id]/patch/index.js.map +1 -0
  18. package/dist/usergroups/[id]/patch/request.d.ts +12 -0
  19. package/dist/usergroups/[id]/patch/request.js +3 -0
  20. package/dist/usergroups/[id]/patch/request.js.map +1 -0
  21. package/dist/usergroups/[id]/patch/response.d.ts +1 -0
  22. package/dist/usergroups/[id]/patch/response.js +3 -0
  23. package/dist/usergroups/[id]/patch/response.js.map +1 -0
  24. package/dist/usergroups/get/index.d.ts +2 -0
  25. package/dist/usergroups/get/index.js +19 -0
  26. package/dist/usergroups/get/index.js.map +1 -0
  27. package/dist/usergroups/get/query.d.ts +12 -0
  28. package/dist/usergroups/get/query.js +3 -0
  29. package/dist/usergroups/get/query.js.map +1 -0
  30. package/dist/usergroups/get/response.d.ts +26 -0
  31. package/dist/usergroups/get/response.js +3 -0
  32. package/dist/usergroups/get/response.js.map +1 -0
  33. package/dist/usergroups/index.d.ts +4 -0
  34. package/dist/usergroups/index.js +21 -0
  35. package/dist/usergroups/index.js.map +1 -0
  36. package/dist/usergroups/post/index.d.ts +2 -0
  37. package/dist/usergroups/post/index.js +19 -0
  38. package/dist/usergroups/post/index.js.map +1 -0
  39. package/dist/usergroups/post/request.d.ts +11 -0
  40. package/dist/usergroups/post/request.js +3 -0
  41. package/dist/usergroups/post/request.js.map +1 -0
  42. package/dist/usergroups/post/response.d.ts +1 -0
  43. package/dist/usergroups/post/response.js +3 -0
  44. package/dist/usergroups/post/response.js.map +1 -0
  45. package/dist/usergroups/shared.d.ts +25 -0
  46. package/dist/usergroups/shared.js +11 -0
  47. package/dist/usergroups/shared.js.map +1 -0
  48. package/dist/users/[id]/get/response.d.ts +0 -2
  49. package/dist/users/[id]/patch/request.d.ts +5 -1
  50. package/dist/users/current.d.ts +22 -4
  51. package/dist/users/get/query.d.ts +0 -2
  52. package/dist/users/post/request.d.ts +6 -1
  53. package/package.json +2 -2
@@ -1,4 +1,5 @@
1
1
  import { ActionEffect, ActionEvent, ActionPresentation, ActionTargetEntity } from '../../shared';
2
+ import { PermissionGrant } from '../../../usergroups/shared';
2
3
  /** `name` is immutable. `event: null` clears the custom history label. */
3
4
  export interface UpdateActionRequest {
4
5
  label?: string;
@@ -9,4 +10,7 @@ export interface UpdateActionRequest {
9
10
  event?: ActionEvent | null;
10
11
  /** Replaced wholesale; an empty array clears every effect. */
11
12
  effects?: ActionEffect[];
13
+ /** UI-only visibility grants — replaced wholesale; [] clears them (usable
14
+ * by everyone). Every group id must exist in the org; `level` ignored. */
15
+ permissions?: PermissionGrant[];
12
16
  }
@@ -1,4 +1,5 @@
1
1
  import { IEntityMeta } from '../../shared';
2
+ import { PermissionGrant } from '../../usergroups/shared';
2
3
  import { ActionEffect, ActionEvent, ActionPresentation, ActionTargetEntity } from '../shared';
3
4
  import { GetActionsQuery } from './query';
4
5
  export interface GetActionResponse {
@@ -16,6 +17,9 @@ export interface GetActionResponse {
16
17
  event?: ActionEvent;
17
18
  /** Run on submit in author order (§4.2); absent = none. */
18
19
  effects?: ActionEffect[];
20
+ /** UI-only visibility grants — binary for actions (`level` ignored; any
21
+ * grant ⇒ members-only). Absent/empty = usable by everyone. */
22
+ permissions?: PermissionGrant[];
19
23
  meta?: IEntityMeta;
20
24
  }
21
25
  export interface GetActionsResponse {
@@ -7,4 +7,11 @@ export interface DownloadAssetsQuery extends AssetFilters {
7
7
  timestampFormat?: TimestampFormat;
8
8
  timezone?: string;
9
9
  withEntityLinks?: boolean;
10
+ /**
11
+ * Export column curation: keep only the custom-field columns for these
12
+ * field ids. Omitted ⇒ every field column (existing API callers
13
+ * unchanged). Ids that resolve to no field are dropped silently — this
14
+ * is UI curation, not access control.
15
+ */
16
+ fieldIds?: string[];
10
17
  }
@@ -60,6 +60,8 @@ export interface AssetFilters {
60
60
  createdAt?: DateCondition[];
61
61
  updatedAt?: DateCondition[];
62
62
  lastSeen?: DateCondition[];
63
+ /** Offline-sync delta read: matches records whose `lastChanged` >= this ms-epoch. */
64
+ updatedAfter?: number;
63
65
  }
64
66
  export interface GetAssetsQuery extends AssetFilters {
65
67
  page?: number;
@@ -1,4 +1,5 @@
1
1
  import { FieldDataType, FieldInputType } from '../constants';
2
+ import { PermissionGrant } from '../../usergroups/shared';
2
3
  export interface GetFieldResponse {
3
4
  id: string;
4
5
  name: string;
@@ -14,6 +15,8 @@ export interface GetFieldResponse {
14
15
  decimalMin?: number;
15
16
  decimalMax?: number;
16
17
  decimalPlaces?: number;
18
+ /** UI-only visibility grants (usergroups); absent/empty = open. */
19
+ permissions?: PermissionGrant[];
17
20
  meta?: {
18
21
  created: number;
19
22
  updated?: number;
@@ -1,4 +1,5 @@
1
1
  import { FieldInputType } from '../../constants';
2
+ import { PermissionGrant } from '../../../usergroups/shared';
2
3
  export interface UpdateFieldRequestOption {
3
4
  value: string;
4
5
  previousValue?: string;
@@ -15,4 +16,7 @@ export interface UpdateFieldRequest {
15
16
  decimalMin?: number | null;
16
17
  decimalMax?: number | null;
17
18
  decimalPlaces?: number | null;
19
+ /** UI-only visibility grants — replaced wholesale; [] clears them (open).
20
+ * Every group id must exist in the org. */
21
+ permissions?: PermissionGrant[];
18
22
  }
package/dist/index.d.ts CHANGED
@@ -25,3 +25,4 @@ export * from './views';
25
25
  export * from './forms';
26
26
  export * from './actions';
27
27
  export * from './submissions';
28
+ export * from './usergroups';
package/dist/index.js CHANGED
@@ -41,4 +41,5 @@ __exportStar(require("./views"), exports);
41
41
  __exportStar(require("./forms"), exports);
42
42
  __exportStar(require("./actions"), exports);
43
43
  __exportStar(require("./submissions"), exports);
44
+ __exportStar(require("./usergroups"), exports);
44
45
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,uCAAoB;AACpB,2CAAwB;AACxB,iDAA8B;AAC9B,2CAAwB;AACxB,2CAAwB;AACxB,8CAA2B;AAC3B,6CAA0B;AAC1B,kDAA+B;AAC/B,4CAAyB;AACzB,0CAAuB;AACvB,yCAAsB;AACtB,8CAA2B;AAC3B,0CAAuB;AACvB,8CAA2B;AAC3B,0CAAuB;AACvB,2CAAwB;AACxB,8CAA2B;AAC3B,2CAAwB;AACxB,8CAA2B;AAC3B,2CAAwB;AACxB,4CAAyB;AACzB,wCAAqB;AACrB,0CAAuB;AACvB,0CAAuB;AACvB,4CAAyB;AACzB,gDAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,uCAAoB;AACpB,2CAAwB;AACxB,iDAA8B;AAC9B,2CAAwB;AACxB,2CAAwB;AACxB,8CAA2B;AAC3B,6CAA0B;AAC1B,kDAA+B;AAC/B,4CAAyB;AACzB,0CAAuB;AACvB,yCAAsB;AACtB,8CAA2B;AAC3B,0CAAuB;AACvB,8CAA2B;AAC3B,0CAAuB;AACvB,2CAAwB;AACxB,8CAA2B;AAC3B,2CAAwB;AACxB,8CAA2B;AAC3B,2CAAwB;AACxB,4CAAyB;AACzB,wCAAqB;AACrB,0CAAuB;AACvB,0CAAuB;AACvB,4CAAyB;AACzB,gDAA6B;AAC7B,+CAA4B"}
@@ -22,6 +22,8 @@ export interface LocationFilters {
22
22
  */
23
23
  manifestId?: string;
24
24
  manifestIds?: string[];
25
+ /** Offline-sync delta read: matches records whose `lastChanged` >= this ms-epoch. */
26
+ updatedAfter?: number;
25
27
  }
26
28
  export interface GetLocationsQuery extends LocationFilters {
27
29
  page?: number;
@@ -21,12 +21,23 @@ export interface SnapshotPreferences {
21
21
  export interface WorkflowPreferences {
22
22
  mainMenuEnabled?: boolean;
23
23
  }
24
+ /**
25
+ * Org toggle for the usergroups feature set (field/action visibility +
26
+ * location record scope). Default OFF: enforcement, hiding, and the
27
+ * /users/current access lists all short-circuit; usergroup data stays
28
+ * inert. Every flip to ON recomputes all user caches (and bootstraps the
29
+ * "all" group iff the org has zero usergroups).
30
+ */
31
+ export interface UsergroupPreferences {
32
+ enabled: boolean;
33
+ }
24
34
  export interface Preferences {
25
35
  readers: ReaderPreferences;
26
36
  assets: AssetPreferences;
27
37
  locations: LocationPreferences;
28
38
  snapshots?: SnapshotPreferences;
29
39
  workflows?: WorkflowPreferences;
40
+ usergroups?: UsergroupPreferences;
30
41
  mainMenuLinks?: Array<{
31
42
  label: string;
32
43
  url: string;
@@ -0,0 +1 @@
1
+ export * from './patch';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./patch"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/usergroups/[id]/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB"}
@@ -0,0 +1,2 @@
1
+ export * from './request';
2
+ export * from './response';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./request"), exports);
18
+ __exportStar(require("./response"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/usergroups/[id]/patch/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB;AACzB,6CAA0B"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Membership and scope are replaced wholesale; an empty array clears either
3
+ * (a scope-less group abstains from location scope). `allLocations: false`
4
+ * clears the sentinel. Changes that alter the actor's own membership are
5
+ * rejected (the own-role-guard rule).
6
+ */
7
+ export interface UpdateUsergroupRequest {
8
+ name?: string;
9
+ members?: string[];
10
+ locationScope?: string[];
11
+ allLocations?: boolean;
12
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../../../src/usergroups/[id]/patch/request.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export { GetUsergroupResponse as UpdateUsergroupResponse } from '../../get/response';
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../../src/usergroups/[id]/patch/response.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export * from './query';
2
+ export * from './response';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./query"), exports);
18
+ __exportStar(require("./response"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/usergroups/get/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB;AACvB,6CAA0B"}
@@ -0,0 +1,12 @@
1
+ import { StandardSortFields, SortOrders } from '../../shared';
2
+ export declare type UsergroupEmbedField = 'meta';
3
+ export interface GetUsergroupsQuery {
4
+ page?: number;
5
+ limit?: number;
6
+ ids?: string[];
7
+ sort?: StandardSortFields;
8
+ sortOrder?: SortOrders;
9
+ embed?: Array<UsergroupEmbedField>;
10
+ /** Usergroups a given user id is a member of. */
11
+ member?: string;
12
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/usergroups/get/query.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { IEntityMeta } from '../../shared';
2
+ import { GetUsergroupsQuery } from './query';
3
+ export interface GetUsergroupResponse {
4
+ id: string;
5
+ name: string;
6
+ /** User ids. Membership's source of truth lives here, never on the user. */
7
+ members: string[];
8
+ /**
9
+ * Location-name path prefixes this group confines its members to. Absent
10
+ * or empty = the group abstains from location scope (it may exist purely
11
+ * for field/action grants).
12
+ */
13
+ locationScope?: string[];
14
+ /**
15
+ * The explicit "entire organisation" sentinel — never expressed as the
16
+ * root location's path (the root's name is the empty string). Emitted
17
+ * only when true.
18
+ */
19
+ allLocations?: boolean;
20
+ meta?: IEntityMeta;
21
+ }
22
+ export interface GetUsergroupsResponse {
23
+ query: GetUsergroupsQuery | null;
24
+ total: number;
25
+ items: GetUsergroupResponse[];
26
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../src/usergroups/get/response.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export * from './shared';
2
+ export * from './get';
3
+ export * from './post';
4
+ export * from './[id]';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./shared"), exports);
18
+ __exportStar(require("./get"), exports);
19
+ __exportStar(require("./post"), exports);
20
+ __exportStar(require("./[id]"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/usergroups/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,wCAAqB;AACrB,yCAAsB;AACtB,yCAAsB"}
@@ -0,0 +1,2 @@
1
+ export * from './request';
2
+ export * from './response';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./request"), exports);
18
+ __exportStar(require("./response"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/usergroups/post/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB;AACzB,6CAA0B"}
@@ -0,0 +1,11 @@
1
+ export interface PostUsergroupRequest {
2
+ name: string;
3
+ /** User ids. The actor's own id is rejected — nobody edits their own
4
+ * memberships (the own-role-guard rule). */
5
+ members?: string[];
6
+ /** Non-empty location-name path prefixes; omitted/empty = the group
7
+ * abstains from location scope. Never the root path — "entire
8
+ * organisation" is `allLocations: true`. */
9
+ locationScope?: string[];
10
+ allLocations?: boolean;
11
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/usergroups/post/request.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export { GetUsergroupResponse as PostUsergroupResponse } from '../get/response';
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../src/usergroups/post/response.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Effective access level a field grant confers. Most-permissive wins across
3
+ * a user's groups; a field with no grants at all is open (EDIT) to everyone.
4
+ * Actions reuse the grant shape with `level` ignored (binary: any grant ⇒
5
+ * members-only).
6
+ */
7
+ export declare const PERMISSION_GRANT_LEVELS: readonly ["NONE", "VIEW", "EDIT"];
8
+ export declare type PermissionGrantLevel = (typeof PERMISSION_GRANT_LEVELS)[number];
9
+ /** One usergroup's grant on a field or action. */
10
+ export interface PermissionGrant {
11
+ /** Usergroup id — must exist in the organisation at write time. */
12
+ group: string;
13
+ level: PermissionGrantLevel;
14
+ }
15
+ /**
16
+ * A user's resolved location scope, derived from their usergroups: any
17
+ * `allLocations` group — or no location-defining group at all — resolves to
18
+ * unconfined; otherwise the union of the groups' `locationScope` prefixes.
19
+ * Emitted on GET /users/current so the client can detect scope changes.
20
+ */
21
+ export declare type UsergroupsScope = {
22
+ unconfined: true;
23
+ } | {
24
+ paths: string[];
25
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PERMISSION_GRANT_LEVELS = void 0;
4
+ /**
5
+ * Effective access level a field grant confers. Most-permissive wins across
6
+ * a user's groups; a field with no grants at all is open (EDIT) to everyone.
7
+ * Actions reuse the grant shape with `level` ignored (binary: any grant ⇒
8
+ * members-only).
9
+ */
10
+ exports.PERMISSION_GRANT_LEVELS = ['NONE', 'VIEW', 'EDIT'];
11
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/usergroups/shared.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACU,QAAA,uBAAuB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,CAAA"}
@@ -4,8 +4,6 @@ export interface BaseGetUserResponse {
4
4
  name: string;
5
5
  role: IEmbeddedEntity;
6
6
  organisation: IEmbeddedEntity;
7
- permissionLocationId: string;
8
- permissionLocationPath: string;
9
7
  homeLocationId: string;
10
8
  homeLocationPath: string;
11
9
  meta?: IEntityMeta;
@@ -1,6 +1,10 @@
1
1
  export interface UpdateUserRequest {
2
2
  name?: string;
3
3
  role?: string;
4
- permissionLocationId?: string;
5
4
  homeLocationId?: string;
5
+ /**
6
+ * Complete usergroup membership for the target (group ids) — replaced
7
+ * wholesale; [] clears every membership. Never applied to yourself.
8
+ */
9
+ usergroups?: string[];
6
10
  }
@@ -3,6 +3,12 @@ import { Preferences } from '../organisations/constants';
3
3
  import { Integrations } from '../integrations/constants';
4
4
  import { System } from '../system';
5
5
  import { HomeLayout } from './home-layout';
6
+ import { PermissionGrantLevel, UsergroupsScope } from '../usergroups/shared';
7
+ /** One entry of the §1.7 field access list — every org field appears. */
8
+ export interface FieldAccessEntry {
9
+ id: string;
10
+ level: PermissionGrantLevel;
11
+ }
6
12
  export interface EmbeddedRole extends IEmbeddedEntity {
7
13
  permissions: string[];
8
14
  }
@@ -16,8 +22,6 @@ export interface CurrentUserResponse {
16
22
  name: string;
17
23
  role: EmbeddedRole;
18
24
  organisation: EmbeddedOrganisation;
19
- permissionLocationId: string;
20
- permissionLocationPath: string;
21
25
  homeLocationId: string;
22
26
  homeLocationPath: string;
23
27
  meta?: IEntityMeta;
@@ -35,14 +39,28 @@ export interface CurrentUserResponse {
35
39
  * user customises — the client then renders its built-in default layout.
36
40
  */
37
41
  homeLayout?: HomeLayout;
42
+ /**
43
+ * UI-only visibility lists (usergroups feature) — COMPLETE: every org
44
+ * field appears with the caller's effective level (grant-less ⇒ EDIT;
45
+ * admin bypass ⇒ all EDIT), every usable action id appears. All three
46
+ * keys are omitted entirely when the org toggle is OFF — client rule:
47
+ * absent list (or absent id) ⇒ open.
48
+ */
49
+ fieldAccess?: FieldAccessEntry[];
50
+ actionAccess?: string[];
51
+ /**
52
+ * The caller's resolved location scope, verbatim from the user-doc cache.
53
+ * The offline client treats a CHANGE in this value (including appearing/
54
+ * disappearing) as its delta-cursor + cache reset trigger — delta reads
55
+ * never re-deliver docs whose lastChanged predates the cursor.
56
+ */
57
+ usergroupsScope?: UsergroupsScope;
38
58
  }
39
59
  export interface CurrentUserPublicResponse {
40
60
  id: string;
41
61
  name: string;
42
62
  role: EmbeddedRole;
43
63
  organisation: EmbeddedOrganisation;
44
- permissionLocationId: string;
45
- permissionLocationPath: string;
46
64
  homeLocationId: string;
47
65
  homeLocationPath: string;
48
66
  meta?: IEntityMeta;
@@ -10,8 +10,6 @@ export interface GetUsersQuery {
10
10
  sort?: StandardSortFields;
11
11
  sortOrder?: SortOrders;
12
12
  embed?: Array<UserEmbedField>;
13
- permissionLocationId?: string;
14
- permissionLocationPathBeginsWith?: string;
15
13
  homeLocationId?: string;
16
14
  homeLocationPathBeginsWith?: string;
17
15
  }
@@ -1,8 +1,13 @@
1
1
  export interface BasePostUserRequest {
2
2
  name: string;
3
3
  role: string;
4
- permissionLocationId?: string;
5
4
  homeLocationId?: string;
5
+ /**
6
+ * Complete usergroup membership for the new user (group ids). Enforced
7
+ * per the closure invariant when the org toggle is ON; omitted = no
8
+ * groups (resolves unconfined).
9
+ */
10
+ usergroups?: string[];
6
11
  }
7
12
  export interface PostExternalUserRequest extends BasePostUserRequest {
8
13
  type: 'EXTERNAL';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spotto/contract",
3
3
  "license": "ISC",
4
- "version": "1.0.70-alpha.13",
4
+ "version": "1.0.70-alpha.15",
5
5
  "description": "Spotto's API Contract type definitions",
6
6
  "main": "./dist/index.js",
7
7
  "files": [
@@ -18,5 +18,5 @@
18
18
  "@types/geojson": "^7946.0.11",
19
19
  "shx": "^0.3.4"
20
20
  },
21
- "gitHead": "ee164edbac29f51e60ef9c6046399a9e0ac4c316"
21
+ "gitHead": "1639adf5cd5b9bbac1c3f6aa3c6127bf1e3ee882"
22
22
  }