@dereekb/firebase 13.29.0 → 13.31.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/firebase",
3
- "version": "13.29.0",
3
+ "version": "13.31.0",
4
4
  "sideEffects": false,
5
5
  "exports": {
6
6
  "./test": {
@@ -24,10 +24,10 @@
24
24
  }
25
25
  },
26
26
  "peerDependencies": {
27
- "@dereekb/date": "13.29.0",
28
- "@dereekb/model": "13.29.0",
29
- "@dereekb/rxjs": "13.29.0",
30
- "@dereekb/util": "13.29.0",
27
+ "@dereekb/date": "13.31.0",
28
+ "@dereekb/model": "13.31.0",
29
+ "@dereekb/rxjs": "13.31.0",
30
+ "@dereekb/util": "13.31.0",
31
31
  "@firebase/rules-unit-testing": "5.0.0",
32
32
  "@marcbachmann/cel-js": "^7.6.1",
33
33
  "@typescript-eslint/parser": "8.59.3",
@@ -1,2 +1,5 @@
1
1
  export * from './oidc.error';
2
+ export * from './oidc.base';
3
+ export * from './oidc.interaction';
4
+ export * from './oidc.profile';
2
5
  export * from './oidc';
@@ -43,6 +43,15 @@ export type OidcScopeDetails<T extends OidcScope = OidcScope> = LabeledValueWith
43
43
  * @semanticTopic dereekb-firebase:oidc
44
44
  */
45
45
  export type OidcRedirectUri = string;
46
+ /**
47
+ * Unique client identifier for an OIDC client registration.
48
+ *
49
+ * @semanticType
50
+ * @semanticTopic identifier
51
+ * @semanticTopic string
52
+ * @semanticTopic dereekb-firebase:oidc
53
+ */
54
+ export type OidcEntryClientId = string;
46
55
  /**
47
56
  * The `client_secret_basic` confidential-client auth method (RFC 6749 §2.3.1, the
48
57
  * OAuth 2.0 default): the client sends its `client_id` and `client_secret` in the
@@ -1,5 +1,6 @@
1
1
  import { type LabeledValueWithDescription, type Maybe } from '@dereekb/util';
2
2
  import { type KnownOnCallFunctionType, type OnCallFunctionType } from '../../model/function';
3
+ import { type OidcScope } from './oidc.base';
3
4
  /**
4
5
  * Prefix shared by every callModel OIDC scope (e.g., `model.create`).
5
6
  *
@@ -125,3 +126,138 @@ export type ServiceTokenOidcScope = typeof SERVICE_TOKEN_OIDC_SCOPE;
125
126
  * restricted to privileged users.
126
127
  */
127
128
  export declare const SERVICE_TOKEN_OIDC_SCOPE_DETAILS: LabeledValueWithDescription<ServiceTokenOidcScope>;
129
+ /**
130
+ * A single requirement TERM in the callModel OIDC scope model.
131
+ *
132
+ * A term is satisfied when the caller holds the required scope(s):
133
+ * - a single {@link OidcScope} — the caller must hold exactly that scope; or
134
+ * - a `readonly` array of {@link OidcScope}s — an OR-group the caller satisfies by holding ANY one
135
+ * (an empty group imposes no requirement).
136
+ *
137
+ * Multiple terms combine with AND — see {@link oidcScopeTermsSatisfied}. The callModel gate ANDs the
138
+ * per-verb `model.<call>` scope with the effective GROUP term resolved for the model/handler.
139
+ */
140
+ export type OidcScopeTerm = OidcScope | readonly OidcScope[];
141
+ /**
142
+ * Parses a raw OIDC `scope` claim (a space-delimited string) into the granted scope set consumed by
143
+ * {@link oidcScopeTermSatisfied} / {@link oidcScopeTermsSatisfied}.
144
+ *
145
+ * The single source of truth for scope-string parsing, shared by the server-side `getOidcScopesFromRequest`
146
+ * (which reads `request.auth.token.scope`) and the model-api-layer enforcement (which reads the OIDC-validated
147
+ * token off the request auth). Returns `undefined` when the claim is not a string — i.e. the caller is not
148
+ * OIDC-authenticated (a regular Firebase ID token carries no `scope` claim) — so callers can distinguish
149
+ * "no OIDC scopes to enforce against" (bypass) from "OIDC caller that was granted zero scopes" (empty set).
150
+ *
151
+ * @param scope - The raw `scope` claim value, typically a space-delimited string.
152
+ * @returns A `Set` of the granted scopes, or `undefined` when `scope` is not a string.
153
+ */
154
+ export declare function oidcScopesFromScopeClaim(scope: unknown): Maybe<Set<OidcScope>>;
155
+ /**
156
+ * Verb-keyed form of {@link OidcModelScopeRequirement}: a term per {@link OnCallFunctionType}, with an
157
+ * optional `default` term applied to verbs without an explicit entry.
158
+ */
159
+ export interface OidcModelScopeRequirementVerbMap {
160
+ /**
161
+ * Fallback term applied to any verb without an explicit entry below.
162
+ */
163
+ readonly default?: OidcScopeTerm;
164
+ /**
165
+ * Per-verb term keyed by call type (e.g. `read`, `create`, `query`). A `read` entry is the only
166
+ * way to require a scope on a PLAIN READ, which has no per-function handler.
167
+ */
168
+ readonly [verb: string]: OidcScopeTerm | undefined;
169
+ }
170
+ /**
171
+ * Per-model callModel scope requirement, consulted by the model-api scope gate and the MCP visibility filter.
172
+ *
173
+ * Either a single {@link OidcScopeTerm} applied to EVERY verb, or an {@link OidcModelScopeRequirementVerbMap}
174
+ * (verb-keyed with an optional `default`). The verb-keyed form is the only way to require a scope on
175
+ * a plain read — a plain read has no per-function handler to hang a `requiredScope` on, but the
176
+ * scope gate still resolves its verb + model type, so a `read` entry here reaches it.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * // WorkerAcademyProgress is wholly LMS — same term for every verb:
181
+ * const wap: OidcModelScopeRequirement = ['hellosubs', 'lms'];
182
+ * // allow lms reads, require hellosubs for everything else:
183
+ * const worker: OidcModelScopeRequirement = { read: ['hellosubs', 'lms'], default: 'hellosubs' };
184
+ * ```
185
+ */
186
+ export type OidcModelScopeRequirement = OidcScopeTerm | OidcModelScopeRequirementVerbMap;
187
+ /**
188
+ * Returns whether a single {@link OidcScopeTerm} is satisfied by the granted scope set.
189
+ *
190
+ * A string term requires that exact scope; an array term is an OR-group satisfied by ANY member (an
191
+ * empty group is vacuously satisfied — no requirement).
192
+ *
193
+ * @param term - The scope term to test.
194
+ * @param grantedScopes - The scopes the caller holds.
195
+ * @returns `true` when the caller satisfies the term.
196
+ */
197
+ export declare function oidcScopeTermSatisfied(term: OidcScopeTerm, grantedScopes: ReadonlySet<OidcScope>): boolean;
198
+ /**
199
+ * Returns whether EVERY {@link OidcScopeTerm} is satisfied by the granted scope set (AND-of-ORs).
200
+ *
201
+ * The single source of truth shared by the server-side callModel scope enforcement
202
+ * (`assertModelApiOidcScope`) and the MCP tool-visibility filter, so enforcement and tool-list
203
+ * visibility never drift. An empty term list is vacuously satisfied.
204
+ *
205
+ * @param terms - The AND-ed scope terms; each is a single scope or an OR-group.
206
+ * @param grantedScopes - The scopes the caller holds.
207
+ * @returns `true` when the caller satisfies every term.
208
+ */
209
+ export declare function oidcScopeTermsSatisfied(terms: readonly OidcScopeTerm[], grantedScopes: ReadonlySet<OidcScope>): boolean;
210
+ /**
211
+ * Resolves the effective {@link OidcScopeTerm} an {@link OidcModelScopeRequirement} imposes for a
212
+ * given call verb.
213
+ *
214
+ * A single-term requirement applies to every verb; a verb-keyed requirement returns the matching
215
+ * verb entry, falling back to its `default`. Returns `undefined` when the requirement imposes no
216
+ * term for the verb.
217
+ *
218
+ * @param requirement - The per-model requirement.
219
+ * @param call - The call verb being resolved.
220
+ * @returns The effective term for the verb, or `undefined`.
221
+ */
222
+ export declare function resolveOidcModelScopeRequirement(requirement: OidcModelScopeRequirement, call: OnCallFunctionType): Maybe<OidcScopeTerm>;
223
+ /**
224
+ * Inputs to {@link resolveEffectiveOidcScopeTerms}.
225
+ */
226
+ export interface ResolveEffectiveOidcScopeTermsInput {
227
+ /**
228
+ * The per-verb `model.<call>` scope, if any — kept as its own AND term.
229
+ */
230
+ readonly perVerbScope?: Maybe<OidcScopeTerm>;
231
+ /**
232
+ * The per-function `requiredScope` from `withApiDetails`, if any — the finest (highest-precedence)
233
+ * group term.
234
+ */
235
+ readonly requiredScope?: Maybe<OidcScopeTerm>;
236
+ /**
237
+ * The model-level requirement for the targeted model type, if configured.
238
+ */
239
+ readonly modelRequirement?: Maybe<OidcModelScopeRequirement>;
240
+ /**
241
+ * The call verb, used to resolve a verb-keyed {@link modelRequirement}.
242
+ */
243
+ readonly call: OnCallFunctionType;
244
+ /**
245
+ * The configured default group term applied when no finer term overrides it.
246
+ */
247
+ readonly defaultRequiredScope?: Maybe<OidcScopeTerm>;
248
+ }
249
+ /**
250
+ * Resolves the full AND-ed list of {@link OidcScopeTerm}s enforced for one callModel op — the single
251
+ * composition rule shared by the server model-api scope gate and the MCP visibility filter (no drift).
252
+ *
253
+ * The list is the per-verb scope AND the effective GROUP term, where the group term is resolved by
254
+ * precedence: per-function `requiredScope` (finest) > model-level requirement (verb-resolved; covers
255
+ * plain reads) > configured default. Nullish and empty-OR-group terms are dropped, so an op with no
256
+ * requirement yields an empty list (no scope gate — the caller can skip reading scopes). With no
257
+ * config supplied and no per-function scope, the list is exactly `[perVerbScope]` (or empty), matching
258
+ * the pre-grouping behavior.
259
+ *
260
+ * @param input - The per-verb scope, per-function scope, model requirement, verb, and default.
261
+ * @returns The AND-ed scope terms to enforce (possibly empty).
262
+ */
263
+ export declare function resolveEffectiveOidcScopeTerms(input: ResolveEffectiveOidcScopeTermsInput): OidcScopeTerm[];
@@ -1,7 +1,6 @@
1
1
  import { type Maybe, type SpaceSeparatedString, type WebsiteUrlWithPrefix } from '@dereekb/util';
2
- import { type FirebaseAuthIdToken } from '../../common/auth/auth';
3
- import { type OidcEntryClientId } from './oidcmodel.id';
4
- import { type OidcScope } from './oidcmodel.interaction';
2
+ import { type FirebaseAuthIdToken } from '../auth';
3
+ import { type OidcEntryClientId, type OidcScope } from './oidc.base';
5
4
  /**
6
5
  * Request body sent by the frontend to complete a login interaction.
7
6
  *
@@ -0,0 +1,213 @@
1
+ import { type LabeledValueWithDescription } from '@dereekb/util';
2
+ import { type OidcScope } from './oidc.base';
3
+ /**
4
+ * Arbitrary key identifying an {@link OidcProviderProfile} (e.g. `'lms'`).
5
+ *
6
+ * @semanticType
7
+ * @semanticTopic string
8
+ * @semanticTopic dereekb-firebase:oidc
9
+ */
10
+ export type OidcProviderProfileKey = string;
11
+ /**
12
+ * How a scope unlocked by an {@link OidcProviderProfile} is enforced for a client
13
+ * carrying that profile.
14
+ *
15
+ * - `none`: the scope is merely unlocked/allowed — the client may request it, but it stays optional.
16
+ * - `required`: the scope is force-required — it is surfaced as a required (non-deselectable) scope
17
+ * at consent and the interaction is rejected if it is not granted.
18
+ */
19
+ export type OidcProviderProfileScopeRequireMode = 'none' | 'required';
20
+ /**
21
+ * A single scope entry within an {@link OidcProviderProfile}.
22
+ */
23
+ export interface OidcProviderProfileScopeConfig<S extends OidcScope = OidcScope> {
24
+ /**
25
+ * The scope this profile unlocks. It should be a scope that is otherwise restricted (not offered
26
+ * in the general scope picker) so that only clients carrying this profile can request it.
27
+ */
28
+ readonly scope: S;
29
+ /**
30
+ * How the scope is enforced. Defaults to `none` (unlock only, optional) when omitted.
31
+ */
32
+ readonly require?: OidcProviderProfileScopeRequireMode;
33
+ }
34
+ /**
35
+ * A named, admin-assignable preset that unlocks (and optionally force-requires) scopes for the OIDC
36
+ * clients it is assigned to.
37
+ *
38
+ * Provider profiles are declared statically in code (an exported registry) and supplied to the
39
+ * provider via {@link OidcProviderConfig.providerProfiles}. An admin assigns one or more profile keys
40
+ * to an OIDC client (persisted as `dbx_provider_profiles` client metadata). At consent, a scope
41
+ * referenced by any profile is treated as restricted: a client may only obtain it when one of its
42
+ * assigned profiles unlocks it.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const LMS_PROVIDER_PROFILE: OidcProviderProfile = {
47
+ * key: 'lms',
48
+ * label: 'LMS',
49
+ * scopes: [{ scope: 'lms', require: 'required' }]
50
+ * };
51
+ * ```
52
+ */
53
+ export interface OidcProviderProfile<S extends OidcScope = OidcScope> {
54
+ /**
55
+ * Unique key for the profile (e.g. `'lms'`).
56
+ */
57
+ readonly key: OidcProviderProfileKey;
58
+ /**
59
+ * Human-readable label, used in the admin profile picker.
60
+ */
61
+ readonly label: string;
62
+ /**
63
+ * Optional human-readable description, used in the admin profile picker.
64
+ */
65
+ readonly description?: string;
66
+ /**
67
+ * Whether this profile applies to a client that has NO profiles assigned (an empty or absent
68
+ * `dbx_provider_profiles`). Defaults to `false`.
69
+ *
70
+ * Lets an app make a coarse, broadly-available scope profile-gated — so the profile picker becomes
71
+ * the single control surface for scope grouping — without breaking every already-registered client.
72
+ * Multiple default profiles union.
73
+ *
74
+ * The fallback is exclusive: a client assigned ANY profile resolves to exactly its assigned
75
+ * profiles, so assigning a non-default profile does NOT additionally confer the default's scopes.
76
+ *
77
+ * Note a `require: 'required'` scope on a default profile is force-required for EVERY unassigned
78
+ * client — a default profile usually wants `require: 'none'`.
79
+ *
80
+ * @see oidcProviderProfilesForClient
81
+ */
82
+ readonly isDefault?: boolean;
83
+ /**
84
+ * Whether the scopes this profile unlocks may only be granted to admin users. Defaults to `false`.
85
+ *
86
+ * Equivalent to listing this profile's scopes in `OidcProviderConfig.adminOnlyScopes` — the two are
87
+ * unioned — but declared alongside the profile so the fact lives in one place rather than drifting
88
+ * between the shared registry and the server provider config.
89
+ *
90
+ * Combined with `require: 'required'`, this makes the whole client admin-only: the client always
91
+ * requests the scope, so a non-admin resolving its consent is always rejected with `access_denied`.
92
+ *
93
+ * Independent of {@link isDefault} and of the profile unlock gate — a scope may be subject to both
94
+ * gates.
95
+ *
96
+ * @see adminOnlyScopesForOidcProviderProfiles
97
+ */
98
+ readonly adminOnly?: boolean;
99
+ /**
100
+ * The scopes this profile unlocks, each with an optional require mode.
101
+ */
102
+ readonly scopes: readonly OidcProviderProfileScopeConfig<S>[];
103
+ }
104
+ /**
105
+ * Suffix appended to a default profile's description in {@link oidcProviderProfileDetails}, so an
106
+ * admin viewing the picker sees that leaving the field empty still grants that profile's scopes.
107
+ */
108
+ export declare const OIDC_PROVIDER_PROFILE_DEFAULT_DESCRIPTION_SUFFIX = "Applied by default when no profiles are assigned.";
109
+ /**
110
+ * Profile picker entry (label + key + description), mirroring {@link OidcScopeDetails}.
111
+ */
112
+ export type OidcProviderProfileDetails = LabeledValueWithDescription<OidcProviderProfileKey>;
113
+ /**
114
+ * Filters the provider-profile registry to the profiles matching the given assigned keys.
115
+ *
116
+ * @param profiles - The full provider-profile registry.
117
+ * @param keys - The profile keys assigned to a client (e.g. `OidcEntry` `dbx_provider_profiles`).
118
+ * @returns The registry profiles whose key is in `keys`.
119
+ */
120
+ export declare function oidcProviderProfilesForKeys<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[], keys: readonly OidcProviderProfileKey[] | undefined): OidcProviderProfile<S>[];
121
+ /**
122
+ * Filters the provider-profile registry to the profiles marked {@link OidcProviderProfile.isDefault}.
123
+ *
124
+ * @param profiles - The full provider-profile registry.
125
+ * @returns The registry profiles that apply to a client with no assigned profiles.
126
+ */
127
+ export declare function defaultOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): OidcProviderProfile<S>[];
128
+ /**
129
+ * Resolves the profiles that apply to a client: its assigned profiles, or — when it has NO profiles
130
+ * assigned — the registry's default profiles.
131
+ *
132
+ * The fallback is exclusive: a client with any assigned key resolves to exactly
133
+ * {@link oidcProviderProfilesForKeys}, so a non-default assignment never additionally confers the
134
+ * default profiles' scopes. A registry declaring no default behaves identically to
135
+ * {@link oidcProviderProfilesForKeys}.
136
+ *
137
+ * The fallback keys off the assigned key list being empty/absent rather than off the resolved set
138
+ * being empty, so a client whose assigned profile was later removed from the registry resolves to no
139
+ * profiles (fail-closed) rather than silently picking up the default.
140
+ *
141
+ * @param profiles - The full provider-profile registry.
142
+ * @param keys - The profile keys assigned to the client (its `dbx_provider_profiles`).
143
+ * @returns The client's assigned profiles, or the default profiles when none are assigned.
144
+ */
145
+ export declare function oidcProviderProfilesForClient<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[], keys: readonly OidcProviderProfileKey[] | undefined): OidcProviderProfile<S>[];
146
+ /**
147
+ * Collects every scope referenced by the given profiles.
148
+ *
149
+ * Passed the full registry, this is the set of "profile-gated" scopes — scopes a client may only
150
+ * obtain via a profile. Passed a client's assigned profiles, this is the set of scopes those
151
+ * profiles unlock for that client.
152
+ *
153
+ * Note a gated scope is not necessarily unavailable to an unassigned client: a scope unlocked by a
154
+ * default profile is gated yet reachable by every client. Use
155
+ * {@link assignmentOnlyScopesForOidcProviderProfiles} for the "requires an explicit assignment"
156
+ * subset (e.g. to exclude scopes from a general picker or from advertised scope metadata).
157
+ *
158
+ * @param profiles - The profiles to collect scopes from.
159
+ * @returns The union of every profile's scopes.
160
+ */
161
+ export declare function scopesForOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): Set<S>;
162
+ /**
163
+ * Collects the scopes marked `require: 'required'` across the given profiles.
164
+ *
165
+ * @param profiles - The profiles to collect required scopes from (typically a client's assigned profiles).
166
+ * @returns The union of every profile's `required` scopes.
167
+ */
168
+ export declare function requiredScopesForOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): Set<S>;
169
+ /**
170
+ * Collects the scopes unlocked by the registry's default profiles — the scopes every client can
171
+ * obtain, including one with no profiles assigned.
172
+ *
173
+ * @param profiles - The full provider-profile registry.
174
+ * @returns The union of every default profile's scopes. Empty when no profile is marked default.
175
+ */
176
+ export declare function defaultUnlockedScopesForOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): Set<S>;
177
+ /**
178
+ * Collects the gated scopes that are NOT unlocked by default — the scopes a client can only obtain
179
+ * via an explicit profile assignment.
180
+ *
181
+ * This is the set to exclude from a general scope picker or from advertised scope metadata (e.g. an
182
+ * MCP protected-resource document's `scopes_supported`). Prefer it over
183
+ * {@link scopesForOidcProviderProfiles} for that job: the full gated set would wrongly drop a
184
+ * default-unlocked scope that every client can in fact obtain. With no default declared the two are
185
+ * identical.
186
+ *
187
+ * @param profiles - The full provider-profile registry.
188
+ * @returns Every profile-gated scope minus the default-unlocked ones.
189
+ */
190
+ export declare function assignmentOnlyScopesForOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): Set<S>;
191
+ /**
192
+ * Collects the scopes of every profile marked {@link OidcProviderProfile.adminOnly}.
193
+ *
194
+ * Unioned with `OidcProviderConfig.adminOnlyScopes` by the consent admin-only gate: a consent
195
+ * requesting one of these scopes is hard-rejected with `access_denied` when the resolving user is
196
+ * not an admin.
197
+ *
198
+ * @param profiles - The full provider-profile registry.
199
+ * @returns The union of every admin-only profile's scopes. Empty when no profile is marked admin-only.
200
+ */
201
+ export declare function adminOnlyScopesForOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): Set<S>;
202
+ /**
203
+ * Builds picker entries for the given provider profiles, suitable for an admin profile-selection field.
204
+ *
205
+ * A default profile's description carries {@link OIDC_PROVIDER_PROFILE_DEFAULT_DESCRIPTION_SUFFIX} so
206
+ * an admin isn't surprised that an empty selection still grants scopes. Default profiles are
207
+ * deliberately not pre-selected — persisting the default as an explicit assignment would opt the
208
+ * client out of the fallback, so it would stop tracking the registry if the default later changed.
209
+ *
210
+ * @param profiles - The provider-profile registry.
211
+ * @returns One {@link OidcProviderProfileDetails} per profile.
212
+ */
213
+ export declare function oidcProviderProfileDetails<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): OidcProviderProfileDetails[];
@@ -4,6 +4,3 @@ export * from './oidcmodel.query';
4
4
  export * from './oidcmodel.api';
5
5
  export * from './oidcmodel.action';
6
6
  export * from './oidcmodel.data';
7
- export * from './oidcmodel.interaction';
8
- export * from './oidcmodel.interaction.oauth';
9
- export * from './oidc.profile';
@@ -1,11 +1,9 @@
1
1
  import { type Type } from 'arktype';
2
- import { type TargetModelParams, type OnCallCreateModelResult } from '../../common';
2
+ import { type TargetModelParams, type OnCallCreateModelResult, type OidcEntryClientId, type OidcRedirectUri, type OidcTokenEndpointAuthMethod } from '../../common';
3
3
  import { type InferredTargetModelParams } from '../../common/model/model/model.param';
4
4
  import { type ModelFirebaseCrudFunction, type FirebaseFunctionTypeConfigMap, type ModelFirebaseCrudFunctionConfigMap, type ModelFirebaseFunctionMap, type ModelFirebaseCreateFunction, type ModelFirebaseDeleteFunction, type ModelFirebaseUpdateFunction } from '../../client';
5
5
  import { type WebsiteUrlWithPrefix, type Maybe } from '@dereekb/util';
6
- import { type OidcEntryClientId } from './oidcmodel.id';
7
6
  import { type OidcModelTypes } from './oidcmodel';
8
- import { type OidcRedirectUri, type OidcTokenEndpointAuthMethod } from './oidcmodel.interaction';
9
7
  /**
10
8
  * Fields that can be changed on an existing OIDC client.
11
9
  *
@@ -41,7 +39,7 @@ export declare const createOidcClientFieldParamsType: import("arktype/internal/v
41
39
  readonly client_uri?: Maybe<string>;
42
40
  readonly dbx_max_session_ttl?: Maybe<number>;
43
41
  readonly dbx_provider_profiles?: Maybe<string[]>;
44
- token_endpoint_auth_method: "none" | "client_secret_basic" | "client_secret_post" | "client_secret_jwt" | "private_key_jwt";
42
+ token_endpoint_auth_method: "client_secret_basic" | "client_secret_post" | "client_secret_jwt" | "private_key_jwt" | "none";
45
43
  }, {}>;
46
44
  /**
47
45
  * Parameters for registering a new OAuth client for the target entity.
@@ -1,6 +1,5 @@
1
1
  import { type Maybe } from '@dereekb/util';
2
- import { type OidcEntryClientId } from './oidcmodel.id';
3
- import { type OidcRedirectUri } from './oidcmodel.interaction';
2
+ import { type OidcEntryClientId, type OidcRedirectUri } from '../../common';
4
3
  /**
5
4
  * Corresponds with readable content from a OidcEntry's payload.
6
5
  */
@@ -12,12 +12,3 @@ export type OidcEntryId = FirestoreModelId;
12
12
  * Full Firestore model key path for an OidcEntry document.
13
13
  */
14
14
  export type OidcEntryKey = FirestoreModelKey;
15
- /**
16
- * Unique client identifier for an OIDC client registration.
17
- *
18
- * @semanticType
19
- * @semanticTopic identifier
20
- * @semanticTopic string
21
- * @semanticTopic dereekb-firebase:oidc
22
- */
23
- export type OidcEntryClientId = string;
package/test/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@dereekb/firebase/test",
3
- "version": "13.29.0",
3
+ "version": "13.31.0",
4
4
  "peerDependencies": {
5
- "@dereekb/date": "13.29.0",
6
- "@dereekb/firebase": "13.29.0",
7
- "@dereekb/model": "13.29.0",
8
- "@dereekb/rxjs": "13.29.0",
9
- "@dereekb/util": "13.29.0",
5
+ "@dereekb/date": "13.31.0",
6
+ "@dereekb/firebase": "13.31.0",
7
+ "@dereekb/model": "13.31.0",
8
+ "@dereekb/rxjs": "13.31.0",
9
+ "@dereekb/util": "13.31.0",
10
10
  "@firebase/rules-unit-testing": "5.0.0",
11
11
  "date-fns": "^4.1.0",
12
12
  "firebase": "^12.12.1",
@@ -1,107 +0,0 @@
1
- import { type LabeledValueWithDescription } from '@dereekb/util';
2
- import { type OidcScope } from './oidcmodel.interaction';
3
- /**
4
- * Arbitrary key identifying an {@link OidcProviderProfile} (e.g. `'lms'`).
5
- *
6
- * @semanticType
7
- * @semanticTopic string
8
- * @semanticTopic dereekb-firebase:oidc
9
- */
10
- export type OidcProviderProfileKey = string;
11
- /**
12
- * How a scope unlocked by an {@link OidcProviderProfile} is enforced for a client
13
- * carrying that profile.
14
- *
15
- * - `none`: the scope is merely unlocked/allowed — the client may request it, but it stays optional.
16
- * - `required`: the scope is force-required — it is surfaced as a required (non-deselectable) scope
17
- * at consent and the interaction is rejected if it is not granted.
18
- */
19
- export type OidcProviderProfileScopeRequireMode = 'none' | 'required';
20
- /**
21
- * A single scope entry within an {@link OidcProviderProfile}.
22
- */
23
- export interface OidcProviderProfileScopeConfig<S extends OidcScope = OidcScope> {
24
- /**
25
- * The scope this profile unlocks. It should be a scope that is otherwise restricted (not offered
26
- * in the general scope picker) so that only clients carrying this profile can request it.
27
- */
28
- readonly scope: S;
29
- /**
30
- * How the scope is enforced. Defaults to `none` (unlock only, optional) when omitted.
31
- */
32
- readonly require?: OidcProviderProfileScopeRequireMode;
33
- }
34
- /**
35
- * A named, admin-assignable preset that unlocks (and optionally force-requires) scopes for the OIDC
36
- * clients it is assigned to.
37
- *
38
- * Provider profiles are declared statically in code (an exported registry) and supplied to the
39
- * provider via {@link OidcProviderConfig.providerProfiles}. An admin assigns one or more profile keys
40
- * to an OIDC client (persisted as `dbx_provider_profiles` client metadata). At consent, a scope
41
- * referenced by any profile is treated as restricted: a client may only obtain it when one of its
42
- * assigned profiles unlocks it.
43
- *
44
- * @example
45
- * ```ts
46
- * const LMS_PROVIDER_PROFILE: OidcProviderProfile = {
47
- * key: 'lms',
48
- * label: 'LMS',
49
- * scopes: [{ scope: 'lms', require: 'required' }]
50
- * };
51
- * ```
52
- */
53
- export interface OidcProviderProfile<S extends OidcScope = OidcScope> {
54
- /**
55
- * Unique key for the profile (e.g. `'lms'`).
56
- */
57
- readonly key: OidcProviderProfileKey;
58
- /**
59
- * Human-readable label, used in the admin profile picker.
60
- */
61
- readonly label: string;
62
- /**
63
- * Optional human-readable description, used in the admin profile picker.
64
- */
65
- readonly description?: string;
66
- /**
67
- * The scopes this profile unlocks, each with an optional require mode.
68
- */
69
- readonly scopes: readonly OidcProviderProfileScopeConfig<S>[];
70
- }
71
- /**
72
- * Profile picker entry (label + key + description), mirroring {@link OidcScopeDetails}.
73
- */
74
- export type OidcProviderProfileDetails = LabeledValueWithDescription<OidcProviderProfileKey>;
75
- /**
76
- * Filters the provider-profile registry to the profiles matching the given assigned keys.
77
- *
78
- * @param profiles - The full provider-profile registry.
79
- * @param keys - The profile keys assigned to a client (e.g. `OidcEntry` `dbx_provider_profiles`).
80
- * @returns The registry profiles whose key is in `keys`.
81
- */
82
- export declare function oidcProviderProfilesForKeys<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[], keys: readonly OidcProviderProfileKey[] | undefined): OidcProviderProfile<S>[];
83
- /**
84
- * Collects every scope referenced by the given profiles.
85
- *
86
- * Passed the full registry, this is the set of "profile-gated" scopes — scopes a client may only
87
- * obtain via a profile. Passed a client's assigned profiles, this is the set of scopes those
88
- * profiles unlock for that client.
89
- *
90
- * @param profiles - The profiles to collect scopes from.
91
- * @returns The union of every profile's scopes.
92
- */
93
- export declare function scopesForOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): Set<S>;
94
- /**
95
- * Collects the scopes marked `require: 'required'` across the given profiles.
96
- *
97
- * @param profiles - The profiles to collect required scopes from (typically a client's assigned profiles).
98
- * @returns The union of every profile's `required` scopes.
99
- */
100
- export declare function requiredScopesForOidcProviderProfiles<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): Set<S>;
101
- /**
102
- * Builds picker entries for the given provider profiles, suitable for an admin profile-selection field.
103
- *
104
- * @param profiles - The provider-profile registry.
105
- * @returns One {@link OidcProviderProfileDetails} per profile.
106
- */
107
- export declare function oidcProviderProfileDetails<S extends OidcScope = OidcScope>(profiles: readonly OidcProviderProfile<S>[]): OidcProviderProfileDetails[];