@adventurelabs/scout-core 1.4.74 → 1.4.75

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.
@@ -1,47 +1,148 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useScoutRefresh, } from "../hooks/useScoutRefresh";
4
- import { createContext, useContext, useMemo, useRef } from "react";
4
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
5
5
  import { createBrowserClient } from "@supabase/ssr";
6
- // Create context for the Supabase client
7
- const SupabaseContext = createContext(null);
8
- const ConnectionStatusContext = createContext(null);
9
- // Hook to use the Supabase client
10
- export function useSupabase() {
11
- const supabase = useContext(SupabaseContext);
12
- if (!supabase) {
13
- throw new Error("useSupabase must be used within a SupabaseProvider");
6
+ import { CLIENT_ABILITIES_TOKEN_TTL_SEC, } from "../types/client_abilities_token";
7
+ import { EnumWebResponse } from "../types/requests";
8
+ import { get_client_abilities_jwt_public_keys, mint_client_abilities_token, verify_client_abilities_token, } from "../helpers/client_abilities_token";
9
+ const ScoutRefreshContext = createContext(null);
10
+ const DEFAULT_REFRESH_BEFORE_EXPIRY_SEC = 120;
11
+ const DEFAULT_PUBLIC_KEYS_CACHE_MS = 10 * 60 * 1000;
12
+ function mintExpiresAt(mint, ttlSec) {
13
+ if (mint.exp > mint.iat) {
14
+ return mint.exp;
14
15
  }
15
- return supabase;
16
+ return mint.iat + ttlSec;
16
17
  }
17
- // Hook to use connection status
18
- export function useConnectionStatus() {
19
- const connectionStatus = useContext(ConnectionStatusContext);
20
- if (!connectionStatus) {
21
- throw new Error("useConnectionStatus must be used within a ScoutRefreshProvider");
18
+ function useScoutRefreshContext() {
19
+ const ctx = useContext(ScoutRefreshContext);
20
+ if (!ctx) {
21
+ throw new Error("Scout refresh hooks must be used within ScoutRefreshProvider");
22
22
  }
23
- return connectionStatus;
23
+ return ctx;
24
+ }
25
+ export function useSupabase() {
26
+ return useScoutRefreshContext().supabase;
27
+ }
28
+ /** Verified client abilities JWT (minted on a schedule by ScoutRefreshProvider). */
29
+ export function useClientAbilitiesMint() {
30
+ return useScoutRefreshContext().abilities;
31
+ }
32
+ function resolveAbilityParams(abilityParams) {
33
+ return {
34
+ mintClientAbilitiesToken: abilityParams?.mintClientAbilitiesToken ?? true,
35
+ clientAbilitiesTokenTtlSec: abilityParams?.clientAbilitiesTokenTtlSec ??
36
+ CLIENT_ABILITIES_TOKEN_TTL_SEC,
37
+ refreshBeforeExpirySec: abilityParams?.refreshBeforeExpirySec ??
38
+ DEFAULT_REFRESH_BEFORE_EXPIRY_SEC,
39
+ publicKeysCacheTtlMs: abilityParams?.publicKeysCacheTtlMs ?? DEFAULT_PUBLIC_KEYS_CACHE_MS,
40
+ };
41
+ }
42
+ function useClientAbilitiesMintLifecycle(supabase, config) {
43
+ const { mintClientAbilitiesToken: enabled, clientAbilitiesTokenTtlSec: ttlSec, refreshBeforeExpirySec, publicKeysCacheTtlMs, } = config;
44
+ const [mint, setMint] = useState(null);
45
+ const [isLoading, setIsLoading] = useState(false);
46
+ const [error, setError] = useState(null);
47
+ const inFlightRef = useRef(false);
48
+ const publicKeysRef = useRef(null);
49
+ const publicKeysAtRef = useRef(0);
50
+ const loadPublicKeys = useCallback(async (force = false) => {
51
+ const now = Date.now();
52
+ if (!force &&
53
+ publicKeysRef.current?.length &&
54
+ now - publicKeysAtRef.current < publicKeysCacheTtlMs) {
55
+ return publicKeysRef.current;
56
+ }
57
+ const { status, data, msg } = await get_client_abilities_jwt_public_keys(supabase);
58
+ if (status !== EnumWebResponse.SUCCESS || !data?.length) {
59
+ throw new Error(msg ?? "get_client_abilities_jwt_public_keys returned no keys");
60
+ }
61
+ publicKeysRef.current = data;
62
+ publicKeysAtRef.current = now;
63
+ return data;
64
+ }, [supabase, publicKeysCacheTtlMs]);
65
+ const refreshMint = useCallback(async () => {
66
+ if (!enabled || inFlightRef.current) {
67
+ return;
68
+ }
69
+ inFlightRef.current = true;
70
+ setIsLoading(true);
71
+ setError(null);
72
+ try {
73
+ const { data: { session }, } = await supabase.auth.getSession();
74
+ if (!session) {
75
+ setMint(null);
76
+ return;
77
+ }
78
+ const mintResponse = await mint_client_abilities_token(supabase);
79
+ if (mintResponse.status !== EnumWebResponse.SUCCESS ||
80
+ !mintResponse.data) {
81
+ setMint(null);
82
+ setError(mintResponse.msg ?? "mint failed");
83
+ return;
84
+ }
85
+ let keys = await loadPublicKeys();
86
+ let verified;
87
+ try {
88
+ verified = await verify_client_abilities_token(mintResponse.data, keys);
89
+ }
90
+ catch {
91
+ keys = await loadPublicKeys(true);
92
+ verified = await verify_client_abilities_token(mintResponse.data, keys);
93
+ }
94
+ setMint(verified);
95
+ }
96
+ catch (e) {
97
+ setMint(null);
98
+ setError(e instanceof Error ? e.message : "client abilities mint failed");
99
+ }
100
+ finally {
101
+ inFlightRef.current = false;
102
+ setIsLoading(false);
103
+ }
104
+ }, [enabled, supabase, loadPublicKeys]);
105
+ useEffect(() => {
106
+ if (!enabled) {
107
+ setMint(null);
108
+ setError(null);
109
+ return;
110
+ }
111
+ void refreshMint();
112
+ const { data: { subscription }, } = supabase.auth.onAuthStateChange((event) => {
113
+ if (event === "SIGNED_OUT") {
114
+ setMint(null);
115
+ setError(null);
116
+ return;
117
+ }
118
+ if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
119
+ void refreshMint();
120
+ }
121
+ });
122
+ return () => subscription.unsubscribe();
123
+ }, [enabled, supabase, refreshMint]);
124
+ useEffect(() => {
125
+ if (!enabled || !mint) {
126
+ return;
127
+ }
128
+ const nowSec = Math.floor(Date.now() / 1000);
129
+ const expSec = mintExpiresAt(mint, ttlSec);
130
+ const refreshAtSec = Math.max(expSec - refreshBeforeExpirySec, mint.iat + 1);
131
+ const delayMs = Math.max((refreshAtSec - nowSec) * 1000, 1000);
132
+ const timer = setTimeout(() => {
133
+ void refreshMint();
134
+ }, delayMs);
135
+ return () => clearTimeout(timer);
136
+ }, [enabled, mint, ttlSec, refreshBeforeExpirySec, refreshMint]);
137
+ return useMemo(() => ({ mint, isLoading, error, refreshMint }), [mint, isLoading, error, refreshMint]);
24
138
  }
25
- export function ScoutRefreshProvider({ children, ...refreshOptions }) {
26
- // Use refs to store the URL and key to prevent unnecessary recreations
27
- // Assumes Next.js environment variables (NEXT_PUBLIC_*)
139
+ export function ScoutRefreshProvider({ children, abilityParams, ...refreshOptions }) {
28
140
  const urlRef = useRef(process.env.NEXT_PUBLIC_SUPABASE_URL || "");
29
141
  const anonKeyRef = useRef(process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "");
30
- // Create a single Supabase client instance that only runs once
31
- const supabaseClient = useMemo(() => {
32
- console.log("[ScoutRefreshProvider] Creating Supabase client");
33
- return createBrowserClient(urlRef.current, anonKeyRef.current);
34
- }, []); // Empty dependency array ensures this only runs once
35
- useScoutRefresh({ ...refreshOptions, supabase: supabaseClient });
36
- // // Log connection status changes for debugging
37
- // if (connectionStatus.lastError) {
38
- // console.warn(
39
- // "[ScoutRefreshProvider] DB Listener error:",
40
- // connectionStatus.lastError
41
- // );
42
- // }
43
- // if (connectionStatus.isConnected) {
44
- // console.log("[ScoutRefreshProvider] ✅ DB Listener connected");
45
- // }
46
- return (_jsx(SupabaseContext.Provider, { value: supabaseClient, children: children }));
142
+ const supabase = useMemo(() => createBrowserClient(urlRef.current, anonKeyRef.current), []);
143
+ const abilitiesConfig = useMemo(() => resolveAbilityParams(abilityParams), [abilityParams]);
144
+ useScoutRefresh({ ...refreshOptions, supabase });
145
+ const abilities = useClientAbilitiesMintLifecycle(supabase, abilitiesConfig);
146
+ const value = useMemo(() => ({ supabase, abilities }), [supabase, abilities]);
147
+ return (_jsx(ScoutRefreshContext.Provider, { value: value, children: children }));
47
148
  }
@@ -0,0 +1,24 @@
1
+ /** Herd entry inside a minted client abilities JWT (matches edge / RPC payload). */
2
+ export interface IClientAbilitiesHerdClaim {
3
+ herd_id: number;
4
+ slug: string;
5
+ abilities: string[];
6
+ }
7
+ /** Response from `mint-client-abilities-token`. */
8
+ export interface IClientAbilitiesTokenMint {
9
+ token: string;
10
+ platform_superadmin: boolean;
11
+ herds: IClientAbilitiesHerdClaim[];
12
+ iat: number;
13
+ exp: number;
14
+ }
15
+ /** Entry from `get_client_abilities_jwt_public_keys()`. */
16
+ export interface IClientAbilitiesJwtPublicKeyEntry {
17
+ kid: string;
18
+ jwk: Record<string, unknown>;
19
+ }
20
+ export declare const CLIENT_ABILITIES_JWT_AUDIENCE = "scout-client";
21
+ /** Typical edge `CLIENT_ABILITIES_TOKEN_TTL_SEC` (scheduling uses JWT `exp` from mint). */
22
+ export declare const CLIENT_ABILITIES_TOKEN_TTL_SEC = 3600;
23
+ /** UI-only gate; RLS remains authoritative for data access. */
24
+ export declare function can_herd_ability(mint: IClientAbilitiesTokenMint | null | undefined, herd_id: number, ability: string): boolean;
@@ -0,0 +1,14 @@
1
+ export const CLIENT_ABILITIES_JWT_AUDIENCE = "scout-client";
2
+ /** Typical edge `CLIENT_ABILITIES_TOKEN_TTL_SEC` (scheduling uses JWT `exp` from mint). */
3
+ export const CLIENT_ABILITIES_TOKEN_TTL_SEC = 3600;
4
+ /** UI-only gate; RLS remains authoritative for data access. */
5
+ export function can_herd_ability(mint, herd_id, ability) {
6
+ if (!mint?.token) {
7
+ return false;
8
+ }
9
+ if (mint.platform_superadmin) {
10
+ return true;
11
+ }
12
+ const herd = mint.herds.find((h) => h.herd_id === herd_id);
13
+ return herd?.abilities.includes(ability) ?? false;
14
+ }
@@ -1,7 +1,6 @@
1
1
  import { SupabaseClient, User } from "@supabase/supabase-js";
2
2
  import { Database } from "./supabase";
3
3
  export type ScoutDatabaseClient = SupabaseClient<Database, "public">;
4
- export type Role = Database["public"]["Enums"]["role"];
5
4
  export type DeviceType = Database["public"]["Enums"]["device_type"];
6
5
  export type MediaType = Database["public"]["Enums"]["media_type"];
7
6
  export type TagObservationType = Database["public"]["Enums"]["tag_observation_type"];
@@ -27,6 +26,15 @@ export type ILayer = Database["public"]["Tables"]["layers"]["Row"];
27
26
  export type IAction = Database["public"]["Tables"]["actions"]["Row"];
28
27
  export type IZone = Database["public"]["Tables"]["zones"]["Row"];
29
28
  export type IUserRolePerHerd = Database["public"]["Tables"]["users_roles_per_herd"]["Row"];
29
+ export type IAbility = Database["public"]["Tables"]["abilities"]["Row"];
30
+ export type IHerdRole = Database["public"]["Tables"]["herd_roles"]["Row"];
31
+ export type IHerdRoleAbilityRow = Database["public"]["Tables"]["herd_role_abilities"]["Row"];
32
+ export type IHerdRoleWithAbilities = IHerdRole & {
33
+ abilities: IAbility[];
34
+ ability_ids: number[];
35
+ };
36
+ /** Stable machine id on `herd_roles` (e.g. admin, editor, viewer). Not `herds.slug`. */
37
+ export type HerdRoleSystemName = string;
30
38
  export type IHerdInvitation = Database["public"]["Tables"]["herd_invitations"]["Row"];
31
39
  export type IHerdInvitationWithHerdSlug = Database["public"]["CompositeTypes"]["herd_invitation_with_herd_slug"];
32
40
  export type IHerdAllowedDomain = Database["public"]["Tables"]["herd_allowed_domains"]["Row"];
@@ -141,7 +149,8 @@ export interface IEventWithSession extends IEvent {
141
149
  }
142
150
  export type IUserAndRole = {
143
151
  user: IUserProfileRow | null;
144
- role: Role;
152
+ herd_role_id: number;
153
+ herd_role: IHerdRole | null;
145
154
  };
146
155
  export interface IApiKeyScout {
147
156
  id: string;
@@ -7,6 +7,30 @@ export type Database = {
7
7
  };
8
8
  public: {
9
9
  Tables: {
10
+ abilities: {
11
+ Row: {
12
+ description: string | null;
13
+ id: number;
14
+ inserted_at: string;
15
+ is_system: boolean;
16
+ key: string;
17
+ };
18
+ Insert: {
19
+ description?: string | null;
20
+ id?: number;
21
+ inserted_at?: string;
22
+ is_system?: boolean;
23
+ key: string;
24
+ };
25
+ Update: {
26
+ description?: string | null;
27
+ id?: number;
28
+ inserted_at?: string;
29
+ is_system?: boolean;
30
+ key?: string;
31
+ };
32
+ Relationships: [];
33
+ };
10
34
  actions: {
11
35
  Row: {
12
36
  id: number;
@@ -331,6 +355,27 @@ export type Database = {
331
355
  }
332
356
  ];
333
357
  };
358
+ client_abilities_jwt_public_keys: {
359
+ Row: {
360
+ created_at: string;
361
+ kid: string;
362
+ public_jwk: Json;
363
+ revoked_at: string | null;
364
+ };
365
+ Insert: {
366
+ created_at?: string;
367
+ kid: string;
368
+ public_jwk: Json;
369
+ revoked_at?: string | null;
370
+ };
371
+ Update: {
372
+ created_at?: string;
373
+ kid?: string;
374
+ public_jwk?: Json;
375
+ revoked_at?: string | null;
376
+ };
377
+ Relationships: [];
378
+ };
334
379
  connectivity: {
335
380
  Row: {
336
381
  altitude: number;
@@ -840,9 +885,9 @@ export type Database = {
840
885
  email: string;
841
886
  expires_at: string | null;
842
887
  herd_id: number;
888
+ herd_role_id: number;
843
889
  id: number;
844
890
  invited_by: string;
845
- role: Database["public"]["Enums"]["role"];
846
891
  status: Database["public"]["Enums"]["herd_invitation_status"];
847
892
  };
848
893
  Insert: {
@@ -851,9 +896,9 @@ export type Database = {
851
896
  email: string;
852
897
  expires_at?: string | null;
853
898
  herd_id: number;
899
+ herd_role_id: number;
854
900
  id?: number;
855
901
  invited_by: string;
856
- role: Database["public"]["Enums"]["role"];
857
902
  status?: Database["public"]["Enums"]["herd_invitation_status"];
858
903
  };
859
904
  Update: {
@@ -862,9 +907,9 @@ export type Database = {
862
907
  email?: string;
863
908
  expires_at?: string | null;
864
909
  herd_id?: number;
910
+ herd_role_id?: number;
865
911
  id?: number;
866
912
  invited_by?: string;
867
- role?: Database["public"]["Enums"]["role"];
868
913
  status?: Database["public"]["Enums"]["herd_invitation_status"];
869
914
  };
870
915
  Relationships: [
@@ -875,6 +920,13 @@ export type Database = {
875
920
  referencedRelation: "herds";
876
921
  referencedColumns: ["id"];
877
922
  },
923
+ {
924
+ foreignKeyName: "herd_invitations_herd_role_id_fkey";
925
+ columns: ["herd_role_id"];
926
+ isOneToOne: false;
927
+ referencedRelation: "herd_roles";
928
+ referencedColumns: ["id"];
929
+ },
878
930
  {
879
931
  foreignKeyName: "herd_invitations_invited_by_fkey";
880
932
  columns: ["invited_by"];
@@ -884,6 +936,74 @@ export type Database = {
884
936
  }
885
937
  ];
886
938
  };
939
+ herd_role_abilities: {
940
+ Row: {
941
+ ability_id: number;
942
+ herd_role_id: number;
943
+ id: number;
944
+ };
945
+ Insert: {
946
+ ability_id: number;
947
+ herd_role_id: number;
948
+ id?: number;
949
+ };
950
+ Update: {
951
+ ability_id?: number;
952
+ herd_role_id?: number;
953
+ id?: number;
954
+ };
955
+ Relationships: [
956
+ {
957
+ foreignKeyName: "herd_role_abilities_ability_id_fkey";
958
+ columns: ["ability_id"];
959
+ isOneToOne: false;
960
+ referencedRelation: "abilities";
961
+ referencedColumns: ["id"];
962
+ },
963
+ {
964
+ foreignKeyName: "herd_role_abilities_herd_role_id_fkey";
965
+ columns: ["herd_role_id"];
966
+ isOneToOne: false;
967
+ referencedRelation: "herd_roles";
968
+ referencedColumns: ["id"];
969
+ }
970
+ ];
971
+ };
972
+ herd_roles: {
973
+ Row: {
974
+ herd_id: number;
975
+ id: number;
976
+ inserted_at: string;
977
+ is_system: boolean;
978
+ name: string;
979
+ system_name: string;
980
+ };
981
+ Insert: {
982
+ herd_id: number;
983
+ id?: number;
984
+ inserted_at?: string;
985
+ is_system?: boolean;
986
+ name: string;
987
+ system_name: string;
988
+ };
989
+ Update: {
990
+ herd_id?: number;
991
+ id?: number;
992
+ inserted_at?: string;
993
+ is_system?: boolean;
994
+ name?: string;
995
+ system_name?: string;
996
+ };
997
+ Relationships: [
998
+ {
999
+ foreignKeyName: "herd_roles_herd_id_fkey";
1000
+ columns: ["herd_id"];
1001
+ isOneToOne: false;
1002
+ referencedRelation: "herds";
1003
+ referencedColumns: ["id"];
1004
+ }
1005
+ ];
1006
+ };
887
1007
  herds: {
888
1008
  Row: {
889
1009
  auto_delete_media_with_humans: boolean | null;
@@ -1685,35 +1805,35 @@ export type Database = {
1685
1805
  users_roles_per_herd: {
1686
1806
  Row: {
1687
1807
  herd_id: number;
1808
+ herd_role_id: number;
1688
1809
  id: number;
1689
1810
  inserted_at: string;
1690
1811
  lifecycle: Database["public"]["Enums"]["entity_lifecycle"];
1691
1812
  lifecycle_changed_at: string;
1692
1813
  lifecycle_changed_by: string | null;
1693
1814
  lifecycle_reason: string | null;
1694
- role: Database["public"]["Enums"]["role"];
1695
1815
  user_id: string;
1696
1816
  };
1697
1817
  Insert: {
1698
1818
  herd_id: number;
1819
+ herd_role_id: number;
1699
1820
  id?: number;
1700
1821
  inserted_at?: string;
1701
1822
  lifecycle?: Database["public"]["Enums"]["entity_lifecycle"];
1702
1823
  lifecycle_changed_at?: string;
1703
1824
  lifecycle_changed_by?: string | null;
1704
1825
  lifecycle_reason?: string | null;
1705
- role: Database["public"]["Enums"]["role"];
1706
1826
  user_id: string;
1707
1827
  };
1708
1828
  Update: {
1709
1829
  herd_id?: number;
1830
+ herd_role_id?: number;
1710
1831
  id?: number;
1711
1832
  inserted_at?: string;
1712
1833
  lifecycle?: Database["public"]["Enums"]["entity_lifecycle"];
1713
1834
  lifecycle_changed_at?: string;
1714
1835
  lifecycle_changed_by?: string | null;
1715
1836
  lifecycle_reason?: string | null;
1716
- role?: Database["public"]["Enums"]["role"];
1717
1837
  user_id?: string;
1718
1838
  };
1719
1839
  Relationships: [
@@ -1724,6 +1844,13 @@ export type Database = {
1724
1844
  referencedRelation: "herds";
1725
1845
  referencedColumns: ["id"];
1726
1846
  },
1847
+ {
1848
+ foreignKeyName: "users_roles_per_herd_herd_role_id_fkey";
1849
+ columns: ["herd_role_id"];
1850
+ isOneToOne: false;
1851
+ referencedRelation: "herd_roles";
1852
+ referencedColumns: ["id"];
1853
+ },
1727
1854
  {
1728
1855
  foreignKeyName: "users_roles_per_herd_lifecycle_changed_by_fkey";
1729
1856
  columns: ["lifecycle_changed_by"];
@@ -1941,9 +2068,9 @@ export type Database = {
1941
2068
  email: string;
1942
2069
  expires_at: string | null;
1943
2070
  herd_id: number;
2071
+ herd_role_id: number;
1944
2072
  id: number;
1945
2073
  invited_by: string;
1946
- role: Database["public"]["Enums"]["role"];
1947
2074
  status: Database["public"]["Enums"]["herd_invitation_status"];
1948
2075
  }[];
1949
2076
  SetofOptions: {
@@ -2008,7 +2135,7 @@ export type Database = {
2008
2135
  p_email: string;
2009
2136
  p_expires_at?: string;
2010
2137
  p_herd_id: number;
2011
- p_role: Database["public"]["Enums"]["role"];
2138
+ p_herd_role_id: number;
2012
2139
  };
2013
2140
  Returns: {
2014
2141
  accepted_at: string | null;
@@ -2016,9 +2143,9 @@ export type Database = {
2016
2143
  email: string;
2017
2144
  expires_at: string | null;
2018
2145
  herd_id: number;
2146
+ herd_role_id: number;
2019
2147
  id: number;
2020
2148
  invited_by: string;
2021
- role: Database["public"]["Enums"]["role"];
2022
2149
  status: Database["public"]["Enums"]["herd_invitation_status"];
2023
2150
  };
2024
2151
  SetofOptions: {
@@ -2413,6 +2540,14 @@ export type Database = {
2413
2540
  isSetofReturn: true;
2414
2541
  };
2415
2542
  };
2543
+ get_client_abilities_jwt_public_keys: {
2544
+ Args: never;
2545
+ Returns: Json;
2546
+ };
2547
+ get_client_abilities_token_claims: {
2548
+ Args: never;
2549
+ Returns: Json;
2550
+ };
2416
2551
  get_connectivity_for_artifact: {
2417
2552
  Args: {
2418
2553
  artifact_id_caller: number;
@@ -3105,36 +3240,13 @@ export type Database = {
3105
3240
  };
3106
3241
  Returns: {
3107
3242
  herd_id: number;
3243
+ herd_role_id: number;
3108
3244
  id: number;
3109
3245
  inserted_at: string;
3110
3246
  lifecycle: Database["public"]["Enums"]["entity_lifecycle"];
3111
3247
  lifecycle_changed_at: string;
3112
3248
  lifecycle_changed_by: string | null;
3113
3249
  lifecycle_reason: string | null;
3114
- role: Database["public"]["Enums"]["role"];
3115
- user_id: string;
3116
- };
3117
- SetofOptions: {
3118
- from: "*";
3119
- to: "users_roles_per_herd";
3120
- isOneToOne: true;
3121
- isSetofReturn: false;
3122
- };
3123
- };
3124
- remove_user_from_herd_for_admin: {
3125
- Args: {
3126
- p_herd_id: number;
3127
- p_user_id: string;
3128
- };
3129
- Returns: {
3130
- herd_id: number;
3131
- id: number;
3132
- inserted_at: string;
3133
- lifecycle: Database["public"]["Enums"]["entity_lifecycle"];
3134
- lifecycle_changed_at: string;
3135
- lifecycle_changed_by: string | null;
3136
- lifecycle_reason: string | null;
3137
- role: Database["public"]["Enums"]["role"];
3138
3250
  user_id: string;
3139
3251
  };
3140
3252
  SetofOptions: {
@@ -3255,9 +3367,9 @@ export type Database = {
3255
3367
  email: string;
3256
3368
  expires_at: string | null;
3257
3369
  herd_id: number;
3370
+ herd_role_id: number;
3258
3371
  id: number;
3259
3372
  invited_by: string;
3260
- role: Database["public"]["Enums"]["role"];
3261
3373
  status: Database["public"]["Enums"]["herd_invitation_status"];
3262
3374
  }[];
3263
3375
  SetofOptions: {
@@ -3271,6 +3383,35 @@ export type Database = {
3271
3383
  Args: never;
3272
3384
  Returns: undefined;
3273
3385
  };
3386
+ remove_user_from_herd_for_admin: {
3387
+ Args: {
3388
+ p_herd_id: number;
3389
+ p_user_id: string;
3390
+ };
3391
+ Returns: {
3392
+ herd_id: number;
3393
+ herd_role_id: number;
3394
+ id: number;
3395
+ inserted_at: string;
3396
+ lifecycle: Database["public"]["Enums"]["entity_lifecycle"];
3397
+ lifecycle_changed_at: string;
3398
+ lifecycle_changed_by: string | null;
3399
+ lifecycle_reason: string | null;
3400
+ user_id: string;
3401
+ };
3402
+ SetofOptions: {
3403
+ from: "*";
3404
+ to: "users_roles_per_herd";
3405
+ isOneToOne: true;
3406
+ isSetofReturn: false;
3407
+ };
3408
+ };
3409
+ revoke_client_abilities_jwt_public_key: {
3410
+ Args: {
3411
+ p_kid: string;
3412
+ };
3413
+ Returns: undefined;
3414
+ };
3274
3415
  revoke_herd_invitations: {
3275
3416
  Args: {
3276
3417
  p_invitation_ids: number[];
@@ -3281,9 +3422,9 @@ export type Database = {
3281
3422
  email: string;
3282
3423
  expires_at: string | null;
3283
3424
  herd_id: number;
3425
+ herd_role_id: number;
3284
3426
  id: number;
3285
3427
  invited_by: string;
3286
- role: Database["public"]["Enums"]["role"];
3287
3428
  status: Database["public"]["Enums"]["herd_invitation_status"];
3288
3429
  }[];
3289
3430
  SetofOptions: {
@@ -3314,6 +3455,12 @@ export type Database = {
3314
3455
  isSetofReturn: true;
3315
3456
  };
3316
3457
  };
3458
+ seed_herd_default_roles: {
3459
+ Args: {
3460
+ p_herd_id: number;
3461
+ };
3462
+ Returns: undefined;
3463
+ };
3317
3464
  set_herd_location: {
3318
3465
  Args: {
3319
3466
  p_herd_id: number;
@@ -3343,6 +3490,13 @@ export type Database = {
3343
3490
  };
3344
3491
  Returns: undefined;
3345
3492
  };
3493
+ upsert_client_abilities_jwt_public_key: {
3494
+ Args: {
3495
+ p_kid: string;
3496
+ p_public_jwk: Json;
3497
+ };
3498
+ Returns: undefined;
3499
+ };
3346
3500
  upsert_pubsub_jwt_public_key: {
3347
3501
  Args: {
3348
3502
  p_kid: string;
@@ -3359,7 +3513,6 @@ export type Database = {
3359
3513
  herd_invitation_status: "pending" | "accepted" | "revoked" | "expired";
3360
3514
  media_type: "image" | "video" | "audio" | "text";
3361
3515
  plan_type: "mission" | "fence" | "rally" | "markov";
3362
- role: "admin" | "editor" | "viewer";
3363
3516
  tag_observation_type: "manual" | "auto";
3364
3517
  user_status: "ONLINE" | "OFFLINE";
3365
3518
  };
@@ -3505,7 +3658,8 @@ export type Database = {
3505
3658
  id: number | null;
3506
3659
  email: string | null;
3507
3660
  herd_id: number | null;
3508
- role: Database["public"]["Enums"]["role"] | null;
3661
+ herd_role_id: number | null;
3662
+ role_system_name: string | null;
3509
3663
  invited_by: string | null;
3510
3664
  status: Database["public"]["Enums"]["herd_invitation_status"] | null;
3511
3665
  created_at: string | null;
@@ -3686,7 +3840,6 @@ export declare const Constants: {
3686
3840
  readonly herd_invitation_status: readonly ["pending", "accepted", "revoked", "expired"];
3687
3841
  readonly media_type: readonly ["image", "video", "audio", "text"];
3688
3842
  readonly plan_type: readonly ["mission", "fence", "rally", "markov"];
3689
- readonly role: readonly ["admin", "editor", "viewer"];
3690
3843
  readonly tag_observation_type: readonly ["manual", "auto"];
3691
3844
  readonly user_status: readonly ["ONLINE", "OFFLINE"];
3692
3845
  };