@samyx/preview-stacks-client 0.29.0 → 0.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/dist/index.d.ts CHANGED
@@ -173,21 +173,29 @@ export declare function createClient(opts: ClientOptions): {
173
173
  * to call — this is the configuration around it.
174
174
  */
175
175
  sso: {
176
- /** `clientSecret` comes back as a mask. There is no route that returns the real one. */
176
+ /** Every stored provider (secrets never come back `secretSet` is all a read learns). */
177
177
  config: () => Promise<SsoConfigResponse>;
178
178
  /**
179
- * Save. Omit `clientSecret` (or send the mask back) to keep the stored one. For `mode: 'oidc'`
180
- * the issuer is fetched here, so a bad one is a 400 now rather than a failed login later.
179
+ * Save one provider under `key`, a lowercase slug. `key` may be omitted on a host with at
180
+ * most one provider an empty host derives it from the config, a one-provider host replaces
181
+ * that one — which is what PUT meant before keys existed; with several it is a 400. Omit
182
+ * `clientSecret` to keep that key's stored one. For `mode: 'oidc'` the issuer is fetched
183
+ * here, so a bad one is a 400 now rather than a failed login later.
181
184
  */
182
185
  save: (config: Partial<SsoConfig> & {
186
+ key?: string;
183
187
  clientSecret?: string;
184
188
  }) => Promise<{
185
189
  ok: true;
190
+ key: string;
186
191
  config: SsoConfig;
187
192
  callbackUrl: string;
188
193
  }>;
189
- /** Forget the provider. Nobody is deleted — accounts it created keep working. */
190
- remove: () => Promise<{
194
+ /**
195
+ * Forget one provider — or the only one, when `key` is omitted (a 400 names the keys when
196
+ * there are several). Nobody is deleted — accounts it created keep working.
197
+ */
198
+ remove: (key?: string) => Promise<{
191
199
  ok: true;
192
200
  }>;
193
201
  };
package/dist/index.js CHANGED
@@ -93,7 +93,7 @@ function createClient(opts) {
93
93
  sso: {
94
94
  config: () => get("/api/sso/config"),
95
95
  save: (config) => put("/api/sso/config", config),
96
- remove: () => del("/api/sso/config")
96
+ remove: (key) => del(key ? `/api/sso/config/${enc(key)}` : "/api/sso/config")
97
97
  },
98
98
  jobs: {
99
99
  list: () => get("/api/jobs").then((r) => r.jobs),
package/dist/types.d.ts CHANGED
@@ -34,10 +34,17 @@ export type Health = {
34
34
  /** False only in loopback dev mode, where the server refuses to bind off-localhost. */
35
35
  authEnforced: boolean;
36
36
  hasUsers?: boolean;
37
- /** The configured identity provider, or null. Readable BEFORE authenticating — a login page needs it. */
37
+ /**
38
+ * The ENABLED sign-in providers, or null when there are none. Readable BEFORE authenticating —
39
+ * a login page needs one button per entry. `key` is what `/api/auth/sso/start?provider=` takes;
40
+ * `preset` is the preset the config came from (`''` for a bare OIDC issuer), for an icon.
41
+ */
38
42
  sso?: {
39
- enabled: boolean;
40
- label: string;
43
+ providers: Array<{
44
+ key: string;
45
+ label: string;
46
+ preset: string;
47
+ }>;
41
48
  } | null;
42
49
  dataDir: string;
43
50
  version: string;
@@ -183,6 +190,8 @@ export type RuntimeContainer = {
183
190
  node?: string | null;
184
191
  /** A swarm task on ANOTHER node: listed, but out of reach of exec/stop from the manager. */
185
192
  remote?: boolean;
193
+ /** A one-shot swarm service's synthetic row (0.31.0+): container verbs have nothing to act on. */
194
+ job?: boolean;
186
195
  };
187
196
  export type RuntimeRoute = {
188
197
  router: string;
@@ -293,28 +302,63 @@ export type SsoConfig = {
293
302
  userInfoUrl: string;
294
303
  /** Consulted only when the profile carries no address (GitHub's default). */
295
304
  emailsUrl: string;
305
+ /** Where the provider lists this user's groups/orgs. Preset-filled; only read when `requiredGroups` is set. */
306
+ groupsUrl: string;
296
307
  scopes: string;
297
308
  claimMap: SsoClaimMap;
298
- /** Non-empty ⇒ a login outside these domains is refused, INCLUDING one with no address at all. */
309
+ /**
310
+ * The three sign-in rules. Each list is ANY-OF, and the three are ANDed with each other. An empty
311
+ * list is no constraint; a non-empty one FAILS CLOSED — a login the rule cannot be evaluated
312
+ * against is refused, not waved through.
313
+ */
299
314
  allowedEmailDomains: string[];
315
+ /**
316
+ * Glob patterns (`path.Match` semantics, so `*`, `?` and `[a-z]` all work), matched case-folded
317
+ * against the provider's username. Inert on a provider that supplies no username claim, which
318
+ * many bare OIDC providers do not — and inert here means every login is refused, not admitted.
319
+ */
320
+ allowedUsernames: string[];
321
+ /**
322
+ * Group/org names, matched exactly and case-folded. Setting this requires a provider whose preset
323
+ * knows a groups endpoint, and scopes that can read it — the server refuses the save otherwise
324
+ * rather than letting every later login fail.
325
+ */
326
+ requiredGroups: string[];
300
327
  defaultRole: string;
301
328
  };
302
329
  export type SsoPreset = {
303
330
  key: string;
304
331
  label: string;
332
+ /** How the provider is talked to; the config's mode defaults from it. */
333
+ mode: 'oidc' | 'oauth2';
334
+ /** Login-page button text ("Continue with GitHub"). */
335
+ buttonLabel: string;
336
+ /** Where the operator registers the OAuth app, and the walkthrough to show beside the form. */
337
+ setupUrl: string;
338
+ setupHint: string;
339
+ /**
340
+ * The issuer, for an oidc preset (`''` otherwise). One containing `<` is a TEMPLATE — render it
341
+ * as a field for the operator to fill in; the server refuses it verbatim.
342
+ */
343
+ discoveryUrl: string;
305
344
  authorizeUrl: string;
306
345
  tokenUrl: string;
307
- userInfoUrl: string | null;
346
+ userInfoUrl: string;
308
347
  scopes: string;
309
348
  claimMap: SsoClaimMap;
310
349
  };
350
+ /** One stored provider, under its operator-chosen slug. */
351
+ export type SsoProviderEntry = {
352
+ key: string;
353
+ config: SsoConfig;
354
+ /** All a read learns about the client secret — the value has no read path. */
355
+ secretSet: boolean;
356
+ updatedAt: number;
357
+ };
311
358
  export type SsoConfigResponse = {
312
- configured: boolean;
313
- /** Register THIS with the provider, byte for byte. Built server-side; never guess it. */
359
+ /** Every stored provider, in key order — disabled ones included. */
360
+ providers: SsoProviderEntry[];
361
+ /** Register THIS with every provider, byte for byte. Built server-side; never guess it. */
314
362
  callbackUrl: string;
315
363
  presets: SsoPreset[];
316
- config: SsoConfig | null;
317
- /** A mask when one is stored. Submit it back unchanged to keep the stored secret. */
318
- clientSecret: string;
319
- updatedAt: number | null;
320
364
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samyx/preview-stacks-client",
3
- "version": "0.29.0",
3
+ "version": "0.31.0",
4
4
  "description": "Typed API client for a pstack control plane: deployments, jobs, readiness, containers, logs, notifiers.",
5
5
  "repository": {
6
6
  "type": "git",