@unisim/sdk 0.125.0 → 0.126.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/oauth.js ADDED
@@ -0,0 +1,132 @@
1
+ 'use client';
2
+ export const OAUTH_PROVIDERS = ['google', 'azure'];
3
+ /** Human label for a provider, for buttons and error text. */
4
+ export function oauthProviderLabel(provider) {
5
+ return provider === 'azure' ? 'Microsoft' : 'Google';
6
+ }
7
+ /**
8
+ * Begin a Microsoft / Google sign-in, upgrading an anonymous trial session in
9
+ * place where there is one. Resolves only if the redirect could not be
10
+ * started — on success the browser is already navigating away.
11
+ */
12
+ export async function startOAuthSignIn(supabase, provider, options = {}) {
13
+ const redirectTo = options.redirectTo ?? defaultRedirectTo();
14
+ let anonymous = false;
15
+ if (!options.forceNewSession) {
16
+ const { data } = await supabase.auth.getSession();
17
+ anonymous = data.session?.user?.is_anonymous === true;
18
+ }
19
+ if (anonymous) {
20
+ const { error } = await supabase.auth.linkIdentity({
21
+ provider,
22
+ options: { redirectTo },
23
+ });
24
+ return { mode: 'link', error: error ? normaliseError(error) : null };
25
+ }
26
+ const { error } = await supabase.auth.signInWithOAuth({
27
+ provider,
28
+ options: { redirectTo },
29
+ });
30
+ return { mode: 'signin', error: error ? normaliseError(error) : null };
31
+ }
32
+ /**
33
+ * Sign out of the anonymous session and start a fresh provider sign-in.
34
+ *
35
+ * The escape hatch for `identity_already_exists`: the visitor's chosen account
36
+ * already belongs to a different Universal ID, so their anonymous work cannot
37
+ * be carried over by any means. Call this only after they have confirmed they
38
+ * are willing to leave it behind.
39
+ */
40
+ export async function abandonTrialAndSignIn(supabase, provider, options = {}) {
41
+ // `scope: 'local'` — the anonymous session is being discarded on this device,
42
+ // and a global sign-out would be a pointless network round trip against a
43
+ // user we are about to stop being.
44
+ await supabase.auth.signOut({ scope: 'local' });
45
+ return startOAuthSignIn(supabase, provider, { ...options, forceNewSession: true });
46
+ }
47
+ /**
48
+ * Read an OAuth failure off the URL we were just redirected back to.
49
+ *
50
+ * ⚠️ **Both the query string and the hash have to be checked.** Supabase's
51
+ * PKCE flow reports failures as query params, the implicit flow puts them in
52
+ * the fragment, and which one you get depends on project configuration rather
53
+ * than on anything in this repo. Checking one of the two produces a page that
54
+ * looks like a completely successful sign-in that simply did not sign anybody
55
+ * in — the single worst outcome for this feature.
56
+ */
57
+ export function readOAuthError(href) {
58
+ if (!href && typeof window === 'undefined')
59
+ return null;
60
+ const url = new URL(href ?? window.location.href);
61
+ for (const params of [url.searchParams, new URLSearchParams(url.hash.replace(/^#/, ''))]) {
62
+ const bucket = params.get('error');
63
+ const code = params.get('error_code');
64
+ const description = params.get('error_description');
65
+ if (bucket || code || description) {
66
+ return {
67
+ code: code ?? bucket ?? null,
68
+ // URLSearchParams already decodes, but providers double-encode the
69
+ // '+' that separates words often enough to be worth normalising.
70
+ message: (description ?? bucket ?? 'Sign-in failed').replace(/\+/g, ' '),
71
+ };
72
+ }
73
+ }
74
+ return null;
75
+ }
76
+ /**
77
+ * Strip the OAuth error params from the address bar without adding a history
78
+ * entry, so a reload (or a second attempt) doesn't resurrect a dead error.
79
+ */
80
+ export function clearOAuthError() {
81
+ if (typeof window === 'undefined')
82
+ return;
83
+ const url = new URL(window.location.href);
84
+ let touched = false;
85
+ for (const key of ['error', 'error_code', 'error_description']) {
86
+ if (url.searchParams.has(key)) {
87
+ url.searchParams.delete(key);
88
+ touched = true;
89
+ }
90
+ }
91
+ if (/(^|[#&])error(_code|_description)?=/.test(url.hash)) {
92
+ url.hash = '';
93
+ touched = true;
94
+ }
95
+ if (touched)
96
+ window.history.replaceState(null, '', url.toString());
97
+ }
98
+ /**
99
+ * Whether a failure means "that account already belongs to somebody else", the
100
+ * one case where the anonymous work genuinely cannot be carried across and the
101
+ * user has a decision to make.
102
+ */
103
+ export function isIdentityCollision(error) {
104
+ if (!error)
105
+ return false;
106
+ if (error.code === 'identity_already_exists')
107
+ return true;
108
+ return /already (been )?(linked|registered|exists)/i.test(error.message);
109
+ }
110
+ /** Whether the project is missing the "Allow manual linking" setting. */
111
+ export function isManualLinkingDisabled(error) {
112
+ if (!error)
113
+ return false;
114
+ if (error.code === 'manual_linking_disabled')
115
+ return true;
116
+ return /manual linking is disabled/i.test(error.message);
117
+ }
118
+ // ── Internals ─────────────────────────────────────────────────────────────────
119
+ function defaultRedirectTo() {
120
+ if (typeof window === 'undefined')
121
+ return undefined;
122
+ const url = new URL(window.location.href);
123
+ for (const key of ['error', 'error_code', 'error_description'])
124
+ url.searchParams.delete(key);
125
+ url.hash = '';
126
+ return url.toString();
127
+ }
128
+ function normaliseError(error) {
129
+ const e = error;
130
+ return { message: e?.message ?? 'Sign-in failed', code: e?.code ?? null };
131
+ }
132
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { useUniversal } from './provider.js';
2
+ export interface OrgSecuritySettings {
3
+ requireMfa: boolean;
4
+ requireSso: boolean;
5
+ }
6
+ export interface UseOrgSecurityResult {
7
+ settings: OrgSecuritySettings;
8
+ loading: boolean;
9
+ /**
10
+ * Non-null when the query FAILED. Callers must not read this as "nothing is
11
+ * required" — a policy that disappears whenever the network hiccups is not a
12
+ * policy. Gates should hold, or retry, rather than fail open.
13
+ */
14
+ error: string | null;
15
+ refresh: () => void;
16
+ /** Admin write. Rejected by RLS for anyone who isn't owner/admin of the org. */
17
+ save: (next: Partial<OrgSecuritySettings>) => Promise<{
18
+ ok: true;
19
+ } | {
20
+ ok: false;
21
+ error: string;
22
+ }>;
23
+ }
24
+ export declare function useOrgSecurity(orgId?: string | null): UseOrgSecurityResult;
25
+ export interface MfaFactor {
26
+ id: string;
27
+ friendlyName: string | null;
28
+ /** Supabase marks a factor 'unverified' until the first correct code. */
29
+ verified: boolean;
30
+ createdAt: string | null;
31
+ }
32
+ export interface UseMfaFactorsResult {
33
+ factors: MfaFactor[];
34
+ /** True once at least one factor is VERIFIED — an unverified one protects nothing. */
35
+ enrolled: boolean;
36
+ loading: boolean;
37
+ error: string | null;
38
+ refresh: () => void;
39
+ }
40
+ export declare function useMfaFactors(): UseMfaFactorsResult;
41
+ /**
42
+ * Whether this session has actually passed a second factor, as opposed to
43
+ * merely having one enrolled.
44
+ *
45
+ * `nextLevel === 'aal2'` means the user HAS a verified factor;
46
+ * `currentLevel === 'aal2'` means they have used it in this session. The gap
47
+ * between the two is the challenge step — read them separately, because
48
+ * conflating them either nags a user who has just passed the challenge or
49
+ * waves through one who never started it.
50
+ */
51
+ export declare function readAssuranceLevel(supabase: ReturnType<typeof useUniversal>['supabase']): Promise<{
52
+ current: string | null;
53
+ next: string | null;
54
+ challengeRequired: boolean;
55
+ }>;
56
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAgB5C,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;CACpB;AAID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,gFAAgF;IAChF,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,mBAAmB,CAAC,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnG;AAED,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,oBAAoB,CAgE1E;AAID,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,yEAAyE;IACzE,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,sFAAsF;IACtF,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,aAAa,IAAI,mBAAmB,CAsDnD;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,UAAU,CAAC,GACpD,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAAE,CAAC,CAQtF"}
@@ -0,0 +1,129 @@
1
+ 'use client';
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ import { useUniversal } from './provider.js';
4
+ const NOTHING_REQUIRED = { requireMfa: false, requireSso: false };
5
+ export function useOrgSecurity(orgId) {
6
+ const { supabase, activeOrgId, session } = useUniversal();
7
+ const targetOrg = orgId ?? activeOrgId ?? null;
8
+ const [settings, setSettings] = useState(NOTHING_REQUIRED);
9
+ const [loading, setLoading] = useState(true);
10
+ const [error, setError] = useState(null);
11
+ const [nonce, setNonce] = useState(0);
12
+ const refresh = useCallback(() => setNonce((n) => n + 1), []);
13
+ useEffect(() => {
14
+ if (!session || !targetOrg) {
15
+ setSettings(NOTHING_REQUIRED);
16
+ setError(null);
17
+ setLoading(false);
18
+ return;
19
+ }
20
+ let cancelled = false;
21
+ setLoading(true);
22
+ supabase
23
+ .from('org_security_settings')
24
+ .select('require_mfa, require_sso')
25
+ .eq('org_id', targetOrg)
26
+ .maybeSingle()
27
+ .then(({ data, error: queryError }) => {
28
+ if (cancelled)
29
+ return;
30
+ if (queryError) {
31
+ setError(queryError.message);
32
+ setSettings(NOTHING_REQUIRED);
33
+ }
34
+ else {
35
+ setError(null);
36
+ setSettings({
37
+ requireMfa: data?.require_mfa === true,
38
+ requireSso: data?.require_sso === true,
39
+ });
40
+ }
41
+ setLoading(false);
42
+ });
43
+ return () => { cancelled = true; };
44
+ }, [supabase, session, targetOrg, nonce]);
45
+ const save = useCallback(async (next) => {
46
+ if (!targetOrg)
47
+ return { ok: false, error: 'No active organisation' };
48
+ const merged = { ...settings, ...next };
49
+ // Upsert, because the common case is that no row exists yet. updated_at
50
+ // and updated_by are written by the 0138 trigger — never send them.
51
+ const { error: writeError } = await supabase
52
+ .from('org_security_settings')
53
+ .upsert({ org_id: targetOrg, require_mfa: merged.requireMfa, require_sso: merged.requireSso }, { onConflict: 'org_id' });
54
+ if (writeError)
55
+ return { ok: false, error: writeError.message };
56
+ setSettings(merged);
57
+ return { ok: true };
58
+ }, [supabase, targetOrg, settings]);
59
+ return { settings, loading, error, refresh, save };
60
+ }
61
+ export function useMfaFactors() {
62
+ const { supabase, session } = useUniversal();
63
+ const [factors, setFactors] = useState([]);
64
+ const [loading, setLoading] = useState(true);
65
+ const [error, setError] = useState(null);
66
+ const [nonce, setNonce] = useState(0);
67
+ const refresh = useCallback(() => setNonce((n) => n + 1), []);
68
+ const userId = session?.user?.id ?? null;
69
+ const isAnonymous = session?.user?.is_anonymous === true;
70
+ useEffect(() => {
71
+ // An anonymous trial user has no factors and cannot enrol one — asking
72
+ // costs a round trip per page and answers nothing.
73
+ if (!userId || isAnonymous) {
74
+ setFactors([]);
75
+ setError(null);
76
+ setLoading(false);
77
+ return;
78
+ }
79
+ let cancelled = false;
80
+ setLoading(true);
81
+ supabase.auth.mfa.listFactors().then(({ data, error: listError }) => {
82
+ if (cancelled)
83
+ return;
84
+ if (listError) {
85
+ setError(listError.message);
86
+ setFactors([]);
87
+ }
88
+ else {
89
+ setError(null);
90
+ setFactors((data?.all ?? []).map((f) => ({
91
+ id: f.id,
92
+ friendlyName: f.friendly_name ?? null,
93
+ verified: f.status === 'verified',
94
+ createdAt: f.created_at ?? null,
95
+ })));
96
+ }
97
+ setLoading(false);
98
+ });
99
+ return () => { cancelled = true; };
100
+ }, [supabase, userId, isAnonymous, nonce]);
101
+ return {
102
+ factors,
103
+ enrolled: factors.some((f) => f.verified),
104
+ loading,
105
+ error,
106
+ refresh,
107
+ };
108
+ }
109
+ /**
110
+ * Whether this session has actually passed a second factor, as opposed to
111
+ * merely having one enrolled.
112
+ *
113
+ * `nextLevel === 'aal2'` means the user HAS a verified factor;
114
+ * `currentLevel === 'aal2'` means they have used it in this session. The gap
115
+ * between the two is the challenge step — read them separately, because
116
+ * conflating them either nags a user who has just passed the challenge or
117
+ * waves through one who never started it.
118
+ */
119
+ export async function readAssuranceLevel(supabase) {
120
+ const { data, error } = await supabase.auth.mfa.getAuthenticatorAssuranceLevel();
121
+ if (error || !data)
122
+ return { current: null, next: null, challengeRequired: false };
123
+ return {
124
+ current: data.currentLevel,
125
+ next: data.nextLevel,
126
+ challengeRequired: data.nextLevel === 'aal2' && data.currentLevel !== 'aal2',
127
+ };
128
+ }
129
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAqB5C,MAAM,gBAAgB,GAAwB,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;AAgBtF,MAAM,UAAU,cAAc,CAAC,KAAqB;IAClD,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAA;IACzD,MAAM,SAAS,GAAG,KAAK,IAAI,WAAW,IAAI,IAAI,CAAA;IAE9C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAsB,gBAAgB,CAAC,CAAA;IAC/E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IACvD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IAErC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAE7D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;YAC3B,WAAW,CAAC,gBAAgB,CAAC,CAAA;YAC7B,QAAQ,CAAC,IAAI,CAAC,CAAA;YACd,UAAU,CAAC,KAAK,CAAC,CAAA;YACjB,OAAM;QACR,CAAC;QACD,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhB,QAAQ;aACL,IAAI,CAAC,uBAAuB,CAAC;aAC7B,MAAM,CAAC,0BAA0B,CAAC;aAClC,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;aACvB,WAAW,EAAE;aACb,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE;YACpC,IAAI,SAAS;gBAAE,OAAM;YACrB,IAAI,UAAU,EAAE,CAAC;gBACf,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;gBAC5B,WAAW,CAAC,gBAAgB,CAAC,CAAA;YAC/B,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,CAAA;gBACd,WAAW,CAAC;oBACV,UAAU,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI;oBACtC,UAAU,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI;iBACvC,CAAC,CAAA;YACJ,CAAC;YACD,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;QAEJ,OAAO,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAA,CAAC,CAAC,CAAA;IACnC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAA;IAEzC,MAAM,IAAI,GAAG,WAAW,CACtB,KAAK,EAAE,IAAkC,EAAE,EAAE;QAC3C,IAAI,CAAC,SAAS;YAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAA;QAC9E,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAA;QACvC,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,QAAQ;aACzC,IAAI,CAAC,uBAAuB,CAAC;aAC7B,MAAM,CACL,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,UAAU,EAAE,EACrF,EAAE,UAAU,EAAE,QAAQ,EAAE,CACzB,CAAA;QACH,IAAI,UAAU;YAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,KAAK,EAAE,UAAU,CAAC,OAAO,EAAE,CAAA;QACxE,WAAW,CAAC,MAAM,CAAC,CAAA;QACnB,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,CAAA;IAC9B,CAAC,EACD,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAChC,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AACpD,CAAC;AAqBD,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAA;IAC5C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAc,EAAE,CAAC,CAAA;IACvD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IACvD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IAErC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAE7D,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,CAAA;IACxC,MAAM,WAAW,GACd,OAAO,EAAE,IAA+C,EAAE,YAAY,KAAK,IAAI,CAAA;IAElF,SAAS,CAAC,GAAG,EAAE;QACb,uEAAuE;QACvE,mDAAmD;QACnD,IAAI,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC;YAC3B,UAAU,CAAC,EAAE,CAAC,CAAA;YACd,QAAQ,CAAC,IAAI,CAAC,CAAA;YACd,UAAU,CAAC,KAAK,CAAC,CAAA;YACjB,OAAM;QACR,CAAC;QACD,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE;YAClE,IAAI,SAAS;gBAAE,OAAM;YACrB,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;gBAC3B,UAAU,CAAC,EAAE,CAAC,CAAA;YAChB,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,CAAA;gBACd,UAAU,CACR,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC5B,EAAE,EAAE,CAAC,CAAC,EAAE;oBACR,YAAY,EAAE,CAAC,CAAC,aAAa,IAAI,IAAI;oBACrC,QAAQ,EAAE,CAAC,CAAC,MAAM,KAAK,UAAU;oBACjC,SAAS,EAAE,CAAC,CAAC,UAAU,IAAI,IAAI;iBAChC,CAAC,CAAC,CACJ,CAAA;YACH,CAAC;YACD,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;QAEF,OAAO,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAA,CAAC,CAAC,CAAA;IACnC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAA;IAE1C,OAAO;QACL,OAAO;QACP,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;QACzC,OAAO;QACP,KAAK;QACL,OAAO;KACR,CAAA;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAqD;IAErD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,8BAA8B,EAAE,CAAA;IAChF,IAAI,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAA;IAClF,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,YAAY;QAC1B,IAAI,EAAE,IAAI,CAAC,SAAS;QACpB,iBAAiB,EAAE,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,KAAK,MAAM;KAC7E,CAAA;AACH,CAAC"}
@@ -8,7 +8,12 @@ export interface SuiteNativeApp {
8
8
  * not legal in a URL scheme and hyphens are.
9
9
  */
10
10
  scheme: string;
11
- /** iOS bundle identifier — the app's `appId` in its capacitor.config. */
11
+ /**
12
+ * iOS bundle identifier — the app's `appId` in its capacitor.config, or for a
13
+ * natively-built app (Ergo Assess) its `PRODUCT_BUNDLE_IDENTIFIER`. Used to
14
+ * work out which app a plist belongs to, never to open one: iOS opens on the
15
+ * scheme.
16
+ */
12
17
  iosBundleId: string;
13
18
  /** Android application id. Usually the same string; Universal AI's is not. */
14
19
  androidPackage: string;
@@ -16,15 +21,33 @@ export interface SuiteNativeApp {
16
21
  /**
17
22
  * Every suite product that has a native build, and only those.
18
23
  *
19
- * ⚠️ **Being in the switcher is not enough to be in here.** Ergo Assess, Exports
20
- * and the rest are web-only; listing them would put a scheme nobody answers
21
- * into thirteen Info.plists and mark rows "Installed" that can never be. A
22
- * product missing from this list simply keeps today's behaviour — the https
23
- * link — which is the correct answer for a product with no app.
24
+ * ⚠️ **Being in the switcher is not enough to be in here.** Exports, Webinar and
25
+ * the rest are web-only; listing them would put a scheme nobody answers into
26
+ * fourteen Info.plists and mark rows "Installed" that can never be. A product
27
+ * missing from this list simply keeps today's behaviour — the https link —
28
+ * which is the correct answer for a product with no app.
24
29
  *
25
30
  * Universal Family has a native build and is deliberately absent for the same
26
31
  * reason: it has no row in the switcher to open.
27
32
  *
33
+ * ⚠️ **Ergo Assess used to be in that web-only sentence and is the reason this
34
+ * paragraph is worth re-reading rather than trusting.** It shipped a native app
35
+ * on both platforms while this list still called it web-only, so its switcher
36
+ * row went on falling back to the https link — the website, inside the webview
37
+ * the user was already in — while every other Assess app handed off. Nothing
38
+ * reported it: a missing registry entry is indistinguishable from "not
39
+ * installed", which is the same silence the three copies of this list have
40
+ * always had. **An app gaining a native build is a change to THIS file.**
41
+ *
42
+ * Ergo is also the first entry that is not a Capacitor app: it is a SwiftUI /
43
+ * Compose pair, so it has no `ios/App/App/` and its bundle id keeps the
44
+ * `com.universalsimulation.` prefix its Xcode project was generated under
45
+ * rather than the `uk.co.unisim.` the Capacitor apps share. Neither matters to
46
+ * the handoff — iOS matches on the scheme and Android on the package, and both
47
+ * are declared below — but it does mean `add-suite-app-links.mjs` has to find
48
+ * its plist by a different path, and that its own switcher rows cannot hand off
49
+ * yet, because its native nav bar has no switcher to tap.
50
+ *
28
51
  * Universal AI is listed, and is the one entry where the two platform ids
29
52
  * differ: its Capacitor `appId` `com.universal-ai.app` is legal on iOS and
30
53
  * illegal on Android (a hyphen cannot appear in a Java package), so its Android
@@ -1 +1 @@
1
- {"version":3,"file":"suiteApps.d.ts","sourceRoot":"","sources":["../src/suiteApps.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,EAAE,EAAE,cAAc,CAAA;IAClB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EActD,CAAA;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,cAAc,GAAG,SAAS,CAE7E;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAOD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAkBjE;AAUD,iDAAiD;AACjD,wBAAgB,uBAAuB,SAEtC;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAWvE"}
1
+ {"version":3,"file":"suiteApps.d.ts","sourceRoot":"","sources":["../src/suiteApps.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,EAAE,EAAE,cAAc,CAAA;IAClB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAetD,CAAA;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,GAAG,cAAc,GAAG,SAAS,CAE7E;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAOD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAkBjE;AAUD,iDAAiD;AACjD,wBAAgB,uBAAuB,SAEtC;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAWvE"}
package/dist/suiteApps.js CHANGED
@@ -19,7 +19,7 @@
19
19
  // • **iOS** matches on SCHEME, and `canOpenURL` answers `false` — with only a
20
20
  // console line to say why — for any scheme the CALLING app has not listed
21
21
  // in its own `LSApplicationQueriesSchemes`. So every app needs every other
22
- // app's scheme in its Info.plist. `scripts/sync-native-app-links.mjs`
22
+ // app's scheme in its Info.plist. `scripts/add-suite-app-links.mjs`
23
23
  // writes that from this file; nobody should be hand-editing the lists.
24
24
  //
25
25
  // • **Android** matches on PACKAGE, and needs no per-app change at all: the
@@ -36,15 +36,33 @@ import { isNativeShell, capacitorPlugin } from './sessionStorage.js';
36
36
  /**
37
37
  * Every suite product that has a native build, and only those.
38
38
  *
39
- * ⚠️ **Being in the switcher is not enough to be in here.** Ergo Assess, Exports
40
- * and the rest are web-only; listing them would put a scheme nobody answers
41
- * into thirteen Info.plists and mark rows "Installed" that can never be. A
42
- * product missing from this list simply keeps today's behaviour — the https
43
- * link — which is the correct answer for a product with no app.
39
+ * ⚠️ **Being in the switcher is not enough to be in here.** Exports, Webinar and
40
+ * the rest are web-only; listing them would put a scheme nobody answers into
41
+ * fourteen Info.plists and mark rows "Installed" that can never be. A product
42
+ * missing from this list simply keeps today's behaviour — the https link —
43
+ * which is the correct answer for a product with no app.
44
44
  *
45
45
  * Universal Family has a native build and is deliberately absent for the same
46
46
  * reason: it has no row in the switcher to open.
47
47
  *
48
+ * ⚠️ **Ergo Assess used to be in that web-only sentence and is the reason this
49
+ * paragraph is worth re-reading rather than trusting.** It shipped a native app
50
+ * on both platforms while this list still called it web-only, so its switcher
51
+ * row went on falling back to the https link — the website, inside the webview
52
+ * the user was already in — while every other Assess app handed off. Nothing
53
+ * reported it: a missing registry entry is indistinguishable from "not
54
+ * installed", which is the same silence the three copies of this list have
55
+ * always had. **An app gaining a native build is a change to THIS file.**
56
+ *
57
+ * Ergo is also the first entry that is not a Capacitor app: it is a SwiftUI /
58
+ * Compose pair, so it has no `ios/App/App/` and its bundle id keeps the
59
+ * `com.universalsimulation.` prefix its Xcode project was generated under
60
+ * rather than the `uk.co.unisim.` the Capacitor apps share. Neither matters to
61
+ * the handoff — iOS matches on the scheme and Android on the package, and both
62
+ * are declared below — but it does mean `add-suite-app-links.mjs` has to find
63
+ * its plist by a different path, and that its own switcher rows cannot hand off
64
+ * yet, because its native nav bar has no switcher to tap.
65
+ *
48
66
  * Universal AI is listed, and is the one entry where the two platform ids
49
67
  * differ: its Capacitor `appId` `com.universal-ai.app` is legal on iOS and
50
68
  * illegal on Android (a hyphen cannot appear in a Java package), so its Android
@@ -53,6 +71,7 @@ import { isNativeShell, capacitorPlugin } from './sessionStorage.js';
53
71
  * is here so that stops being true the moment the badge comes off.
54
72
  */
55
73
  export const SUITE_NATIVE_APPS = [
74
+ { id: 'ergo_assess', scheme: 'unisim-ergo-assess', iosBundleId: 'com.universalsimulation.ergoassesscapture', androidPackage: 'com.universalsimulation.ergoassesscapture' },
56
75
  { id: 'cyber_assess', scheme: 'unisim-cyber-assess', iosBundleId: 'uk.co.unisim.cyberassess', androidPackage: 'uk.co.unisim.cyberassess' },
57
76
  { id: 'workplace_assess', scheme: 'unisim-workplace-assess', iosBundleId: 'uk.co.unisim.wfhassess', androidPackage: 'uk.co.unisim.wfhassess' },
58
77
  { id: 'fire_assess', scheme: 'unisim-fire-assess', iosBundleId: 'uk.co.unisim.fireassess', androidPackage: 'uk.co.unisim.fireassess' },
@@ -1 +1 @@
1
- {"version":3,"file":"suiteApps.js","sourceRoot":"","sources":["../src/suiteApps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"suiteApps.js","sourceRoot":"","sources":["../src/suiteApps.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unisim/sdk",
3
- "version": "0.125.0",
3
+ "version": "0.126.0",
4
4
  "description": "Shared React SDK for the Universal Suite — auth, entitlements, usage telemetry, changelog, org admin.",
5
5
  "license": "MIT",
6
6
  "author": "Universal Simulation Ltd",
@@ -61,6 +61,8 @@
61
61
  "test:session-storage": "npm run build && node tests/session-storage.browser.mjs",
62
62
  "test:shared-signout": "node tests/shared-signout.mjs",
63
63
  "test:suite-apps": "npm run build && node tests/suite-apps.mjs",
64
+ "test:suite-switcher": "npm run build && node tests/suite-switcher-close.browser.mjs",
65
+ "test:multi-org": "npm run build && node tests/multi-org.mjs",
64
66
  "prepublishOnly": "npm run typecheck && npm run build"
65
67
  },
66
68
  "dependencies": {