@camstack/addon-auth 1.2.171 → 1.2.172

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.
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-BCzztoSM.js");
5
+ const require_dist = require("../dist-xyaDmv1T.js");
6
6
  let node_crypto = require("node:crypto");
7
7
  node_crypto = require_dist.__toESM(node_crypto);
8
8
  //#region ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
@@ -867,16 +867,6 @@ function updateOidcConnection(config, id, patch) {
867
867
  clearClientSecret: patch.clearClientSecret === true
868
868
  };
869
869
  }
870
- function deleteOidcConnection(config, id) {
871
- if (!config.providers.some((p) => p.id === id)) return {
872
- ok: false,
873
- reason: "not-found"
874
- };
875
- return {
876
- ok: true,
877
- config: { providers: config.providers.filter((p) => p.id !== id) }
878
- };
879
- }
880
870
  /** Map a wire `clientSecret` field into an update patch fragment. */
881
871
  function clientSecretPatchOf(value) {
882
872
  if (value === void 0) return {};
@@ -897,7 +887,7 @@ var OidcProviderBodySchema = require_dist.object({
897
887
  icon: require_dist.string(),
898
888
  issuerUrl: require_dist.string(),
899
889
  clientId: require_dist.string(),
900
- clientSecret: require_dist.string().meta({ secret: true }),
890
+ clientSecret: require_dist.string().optional().meta({ secret: true }),
901
891
  redirectUri: require_dist.string(),
902
892
  scopes: require_dist.string(),
903
893
  usernameClaim: usernameClaimSchema
@@ -917,6 +907,14 @@ function rowToProvider(id, data) {
917
907
  id
918
908
  };
919
909
  }
910
+ /** The stored body of a row; an empty or non-text secret is left out. */
911
+ function bodyOf(row) {
912
+ const { id: _id, clientSecret, ...rest } = row;
913
+ return typeof clientSecret === "string" && clientSecret !== "" ? {
914
+ ...rest,
915
+ clientSecret
916
+ } : rest;
917
+ }
920
918
  var OidcProviderStore = class OidcProviderStore {
921
919
  kind;
922
920
  constructor(kind) {
@@ -929,46 +927,60 @@ var OidcProviderStore = class OidcProviderStore {
929
927
  const page = await this.kind.query({ limit: 1e3 });
930
928
  const out = [];
931
929
  for (const record of page.records) {
932
- let data = record.data;
933
- try {
934
- const resolved = await this.kind.getResolved(record.id);
935
- if (resolved !== null) data = resolved.data;
936
- } catch (err) {
937
- if (!(err instanceof require_dist.RecordSecretUnavailableError)) throw err;
938
- }
939
- const parsed = OidcProviderBodySchema.safeParse(data);
940
- if (!parsed.success) continue;
941
- out.push(rowToProvider(record.id, parsed.data));
930
+ const row = await this.getResolved(record.id);
931
+ if (row !== null) out.push(row);
942
932
  }
943
933
  return out;
944
934
  }
935
+ /** One row with its secret resolved for the runtime token call; null when absent. */
936
+ async getResolved(id) {
937
+ let record;
938
+ try {
939
+ record = await this.kind.getResolved(id);
940
+ } catch (err) {
941
+ if (!(err instanceof require_dist.RecordSecretUnavailableError)) throw err;
942
+ const stored = await this.kind.get(id);
943
+ if (stored === null) return null;
944
+ const { clientSecret: _unreadable, ...rest } = stored.data;
945
+ record = {
946
+ ...stored,
947
+ data: rest
948
+ };
949
+ }
950
+ if (record === null) return null;
951
+ const parsed = OidcProviderBodySchema.safeParse(record.data);
952
+ return parsed.success ? rowToProvider(id, parsed.data) : null;
953
+ }
954
+ /**
955
+ * Insert ONE new row (`ifRev: 0`: an existing id is refused). A plaintext
956
+ * `clientSecret` is stored by the records facade under the row's own ref.
957
+ */
958
+ async create(row) {
959
+ const body = bodyOf(row);
960
+ const parsed = OidcProviderBodySchema.safeParse(body);
961
+ if (!parsed.success) throw new Error(`invalid OIDC provider '${row.id}': ${parsed.error.message}`);
962
+ await this.kind.put({
963
+ id: row.id,
964
+ data: parsed.data
965
+ }, { ifRev: 0 });
966
+ return this.requireRow(row.id);
967
+ }
968
+ /**
969
+ * Merge a partial into ONE row. `clientSecret`: a plaintext sets it, `undefined`
970
+ * keeps the stored one, `null` clears it.
971
+ */
972
+ async update(id, partial) {
973
+ await this.kind.patch(id, partial);
974
+ return this.requireRow(id);
975
+ }
945
976
  /** Delete one provider record; no other row (nor its secrets) is touched. */
946
977
  async remove(id) {
947
978
  await this.kind.delete(id);
948
979
  }
949
- async replaceAll(providers) {
950
- const page = await this.kind.query({ limit: 1e3 });
951
- const nextIds = new Set(providers.map((p) => p.id));
952
- for (const row of page.records) if (!nextIds.has(row.id)) await this.kind.delete(row.id);
953
- for (const row of providers) {
954
- const { id, displayName, icon, issuerUrl, clientId, clientSecret, redirectUri, scopes, usernameClaim } = row;
955
- const body = {
956
- displayName,
957
- icon,
958
- issuerUrl,
959
- clientId,
960
- clientSecret,
961
- redirectUri,
962
- scopes,
963
- usernameClaim
964
- };
965
- const parsed = oidcProviderEntryKind.schema.safeParse(body);
966
- if (!parsed.success) throw new Error(`invalid OIDC provider '${id}': ${parsed.error.message}`);
967
- await this.kind.put({
968
- id,
969
- data: parsed.data
970
- });
971
- }
980
+ async requireRow(id) {
981
+ const row = await this.getResolved(id);
982
+ if (row === null) throw new Error(`OIDC provider '${id}' is not readable after the write`);
983
+ return row;
972
984
  }
973
985
  };
974
986
  //#endregion
@@ -1073,7 +1085,7 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
1073
1085
  super({ ...DEFAULT_CONFIG });
1074
1086
  }
1075
1087
  async onConfigChanged() {
1076
- this.activeProviders = await this.loadPersistedProviders();
1088
+ if (this.providerStore !== null) this.activeProviders = await this.providerStore.listResolved();
1077
1089
  this.rebuildInstances();
1078
1090
  }
1079
1091
  async onInitialize() {
@@ -1081,16 +1093,7 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
1081
1093
  if (records === void 0) throw new Error("auth-oidc: ctx.records is required (hub-only addon)");
1082
1094
  await records.declare({ "oidc-provider": oidcProviderEntryKind });
1083
1095
  this.providerStore = OidcProviderStore.of(records);
1084
- this.activeProviders = await this.loadPersistedProviders();
1085
- if ((await this.providerStore.listResolved()).length === 0 && this.config.providers.length > 0) try {
1086
- await this.providerStore.replaceAll(await this.adoptSecrets(this.config.providers));
1087
- this.activeProviders = await this.loadPersistedProviders();
1088
- } catch (err) {
1089
- const msg = err instanceof Error ? err.message : String(err);
1090
- if (!msg.startsWith("records/foreign-marker:")) throw err;
1091
- this.ctx.logger.warn("OIDC: deferred config→records copy (a secret marker is bound to another row)", { meta: { error: msg } });
1092
- this.activeProviders = [...this.config.providers];
1093
- }
1096
+ this.activeProviders = await this.providerStore.listResolved();
1094
1097
  this.rebuildInstances();
1095
1098
  const authProvider = {
1096
1099
  validateCredentials: async () => null,
@@ -1176,7 +1179,10 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
1176
1179
  createConnection: async (input) => {
1177
1180
  const result = createOidcConnection(this.providersConfig(), input);
1178
1181
  if (!result.ok) throw new Error(result.reason === "duplicate-id" ? `An OIDC connection with id "${input.id}" already exists` : `Invalid connection id "${input.id}" — use a lowercase slug`);
1179
- await this.persistProviders(result.config.providers);
1182
+ const row = result.config.providers.find((p) => p.id === result.id);
1183
+ if (row === void 0) throw new Error(`Invalid connection id "${input.id}"`);
1184
+ const stored = await this.requireStore().create(row);
1185
+ this.activeProviders = [...this.activeProviders, stored];
1180
1186
  this.rebuildInstances();
1181
1187
  return { id: result.id };
1182
1188
  },
@@ -1193,21 +1199,21 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
1193
1199
  ...input.usernameClaim !== void 0 ? { usernameClaim: input.usernameClaim } : {}
1194
1200
  });
1195
1201
  if (!result.ok) throw new Error(`Unknown OIDC connection "${input.id}"`);
1196
- if (result.clearClientSecret) {
1197
- const cleared = result.config.providers.map((p) => p.id === input.id ? {
1198
- ...p,
1199
- clientSecret: ""
1200
- } : p);
1201
- await this.persistProviders(cleared);
1202
- } else await this.persistProviders(result.config.providers);
1202
+ const next = result.config.providers.find((p) => p.id === input.id);
1203
+ if (next === void 0) throw new Error(`Unknown OIDC connection "${input.id}"`);
1204
+ const { id: _id, clientSecret: _carried, ...fields } = next;
1205
+ const stored = await this.requireStore().update(input.id, {
1206
+ ...fields,
1207
+ ...result.clearClientSecret ? { clientSecret: null } : secretPatch.clientSecret !== void 0 ? { clientSecret: secretPatch.clientSecret } : {}
1208
+ });
1209
+ this.activeProviders = this.activeProviders.map((p) => p.id === input.id ? stored : p);
1203
1210
  this.rebuildInstances();
1204
1211
  return { ok: true };
1205
1212
  },
1206
1213
  deleteConnection: async (input) => {
1207
1214
  if (findOidcProvider(this.providersConfig(), input.id) === null) throw new Error(`Unknown OIDC connection "${input.id}"`);
1208
- const result = deleteOidcConnection(this.providersConfig(), input.id);
1209
- if (!result.ok) throw new Error(`Unknown OIDC connection "${input.id}"`);
1210
- await this.removeProvider(input.id, result.config.providers);
1215
+ await this.requireStore().remove(input.id);
1216
+ this.activeProviders = this.activeProviders.filter((p) => p.id !== input.id);
1211
1217
  this.rebuildInstances();
1212
1218
  return { ok: true };
1213
1219
  }
@@ -1249,69 +1255,9 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
1249
1255
  providersConfig() {
1250
1256
  return { providers: this.activeProviders };
1251
1257
  }
1252
- async loadPersistedProviders() {
1253
- const store = this.providerStore;
1254
- if (store !== null) {
1255
- const fromRecords = await store.listResolved();
1256
- if (fromRecords.length > 0) return fromRecords;
1257
- }
1258
- return this.config.providers;
1259
- }
1260
- async persistProviders(providers) {
1261
- const adopted = await this.adoptSecrets(providers);
1262
- this.activeProviders = [...adopted];
1263
- const store = this.providerStore;
1264
- if (store !== null) {
1265
- await store.replaceAll(adopted);
1266
- return;
1267
- }
1268
- await this.updateGlobalSettings({ providers: [...adopted] });
1269
- }
1270
- async removeProvider(id, remaining) {
1271
- this.activeProviders = [...remaining];
1272
- const store = this.providerStore;
1273
- if (store !== null) {
1274
- await store.remove(id);
1275
- return;
1276
- }
1277
- await this.updateGlobalSettings({ providers: [...remaining] });
1278
- }
1279
- /**
1280
- * A row can still carry a keychain marker bound to the old settings array
1281
- * (`providers[<id>].clientSecret`, owner auth-oidc) — config rows that never
1282
- * moved into records. Records refuse a marker that is not the row's own ref, so
1283
- * every such row is resolved to its value here (re-bound to the record's own ref
1284
- * on write); a marker that no longer resolves becomes an empty secret the
1285
- * operator can retype. The value is never logged.
1286
- */
1287
- async adoptSecrets(providers) {
1288
- const out = [];
1289
- for (const row of providers) {
1290
- const secret = row.clientSecret;
1291
- if (typeof secret === "string") {
1292
- out.push(row);
1293
- continue;
1294
- }
1295
- if (!require_dist.isSecretMarker(secret)) {
1296
- out.push({
1297
- ...row,
1298
- clientSecret: ""
1299
- });
1300
- continue;
1301
- }
1302
- let plain = "";
1303
- const secrets = this.ctx.secrets;
1304
- if (secrets !== void 0) try {
1305
- const entry = (await secrets.resolve([secret.$secret]))[secret.$secret];
1306
- if (entry?.kind === "value") plain = entry.value;
1307
- } catch {}
1308
- if (plain === "") this.ctx.logger.warn(`OIDC: the client secret of connection "${row.id}" could not be read from the keychain; retype it in its settings`);
1309
- out.push({
1310
- ...row,
1311
- clientSecret: plain
1312
- });
1313
- }
1314
- return out;
1258
+ requireStore() {
1259
+ if (this.providerStore === null) throw new Error("auth-oidc: the records store is not ready");
1260
+ return this.providerStore;
1315
1261
  }
1316
1262
  rebuildInstances() {
1317
1263
  this.instances.clear();
@@ -1,4 +1,4 @@
1
- import { A as _enum, C as arrayItemFieldPath, D as isSecretClear, E as globalSecretScope, F as string, O as isSecretMarker, P as object, S as RecordSecretUnavailableError, _ as requestMountPrefix, b as errMsg, c as authProviderCapability, d as loginMethodCapability, f as normalizeOrigin, g as pickRequestOrigin, h as parseAppPageLang, i as addonRoutesCapability, k as toSecretFieldView, l as buildAddonRouteProvider, m as parseAppFlowRequest, n as APP_REFUSED_PATH, o as advertisedHubOrigins, p as oidcConnectionsCapability, r as SSO_STATE_COOKIE, s as appFlowLocation, t as APP_FLOW_DEFAULT_REDIRECT, u as claimedRequestOrigins, v as resolveIconKey, w as defineEntryKind, x as BaseAddon } from "../dist-CAPIgbvM.mjs";
1
+ import { A as _enum, C as arrayItemFieldPath, D as isSecretClear, E as globalSecretScope, F as string, O as isSecretMarker, P as object, S as RecordSecretUnavailableError, _ as requestMountPrefix, b as errMsg, c as authProviderCapability, d as loginMethodCapability, f as normalizeOrigin, g as pickRequestOrigin, h as parseAppPageLang, i as addonRoutesCapability, k as toSecretFieldView, l as buildAddonRouteProvider, m as parseAppFlowRequest, n as APP_REFUSED_PATH, o as advertisedHubOrigins, p as oidcConnectionsCapability, r as SSO_STATE_COOKIE, s as appFlowLocation, t as APP_FLOW_DEFAULT_REDIRECT, u as claimedRequestOrigins, v as resolveIconKey, w as defineEntryKind, x as BaseAddon } from "../dist-Dvcuof5S.mjs";
2
2
  import * as crypto$1 from "node:crypto";
3
3
  //#region ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
4
4
  var encoder = new TextEncoder(), decoder = new TextDecoder(), strictDecoder = new TextDecoder("utf-8", { fatal: !0 });
@@ -862,16 +862,6 @@ function updateOidcConnection(config, id, patch) {
862
862
  clearClientSecret: patch.clearClientSecret === true
863
863
  };
864
864
  }
865
- function deleteOidcConnection(config, id) {
866
- if (!config.providers.some((p) => p.id === id)) return {
867
- ok: false,
868
- reason: "not-found"
869
- };
870
- return {
871
- ok: true,
872
- config: { providers: config.providers.filter((p) => p.id !== id) }
873
- };
874
- }
875
865
  /** Map a wire `clientSecret` field into an update patch fragment. */
876
866
  function clientSecretPatchOf(value) {
877
867
  if (value === void 0) return {};
@@ -892,7 +882,7 @@ var OidcProviderBodySchema = object({
892
882
  icon: string(),
893
883
  issuerUrl: string(),
894
884
  clientId: string(),
895
- clientSecret: string().meta({ secret: true }),
885
+ clientSecret: string().optional().meta({ secret: true }),
896
886
  redirectUri: string(),
897
887
  scopes: string(),
898
888
  usernameClaim: usernameClaimSchema
@@ -912,6 +902,14 @@ function rowToProvider(id, data) {
912
902
  id
913
903
  };
914
904
  }
905
+ /** The stored body of a row; an empty or non-text secret is left out. */
906
+ function bodyOf(row) {
907
+ const { id: _id, clientSecret, ...rest } = row;
908
+ return typeof clientSecret === "string" && clientSecret !== "" ? {
909
+ ...rest,
910
+ clientSecret
911
+ } : rest;
912
+ }
915
913
  var OidcProviderStore = class OidcProviderStore {
916
914
  kind;
917
915
  constructor(kind) {
@@ -924,46 +922,60 @@ var OidcProviderStore = class OidcProviderStore {
924
922
  const page = await this.kind.query({ limit: 1e3 });
925
923
  const out = [];
926
924
  for (const record of page.records) {
927
- let data = record.data;
928
- try {
929
- const resolved = await this.kind.getResolved(record.id);
930
- if (resolved !== null) data = resolved.data;
931
- } catch (err) {
932
- if (!(err instanceof RecordSecretUnavailableError)) throw err;
933
- }
934
- const parsed = OidcProviderBodySchema.safeParse(data);
935
- if (!parsed.success) continue;
936
- out.push(rowToProvider(record.id, parsed.data));
925
+ const row = await this.getResolved(record.id);
926
+ if (row !== null) out.push(row);
937
927
  }
938
928
  return out;
939
929
  }
930
+ /** One row with its secret resolved for the runtime token call; null when absent. */
931
+ async getResolved(id) {
932
+ let record;
933
+ try {
934
+ record = await this.kind.getResolved(id);
935
+ } catch (err) {
936
+ if (!(err instanceof RecordSecretUnavailableError)) throw err;
937
+ const stored = await this.kind.get(id);
938
+ if (stored === null) return null;
939
+ const { clientSecret: _unreadable, ...rest } = stored.data;
940
+ record = {
941
+ ...stored,
942
+ data: rest
943
+ };
944
+ }
945
+ if (record === null) return null;
946
+ const parsed = OidcProviderBodySchema.safeParse(record.data);
947
+ return parsed.success ? rowToProvider(id, parsed.data) : null;
948
+ }
949
+ /**
950
+ * Insert ONE new row (`ifRev: 0`: an existing id is refused). A plaintext
951
+ * `clientSecret` is stored by the records facade under the row's own ref.
952
+ */
953
+ async create(row) {
954
+ const body = bodyOf(row);
955
+ const parsed = OidcProviderBodySchema.safeParse(body);
956
+ if (!parsed.success) throw new Error(`invalid OIDC provider '${row.id}': ${parsed.error.message}`);
957
+ await this.kind.put({
958
+ id: row.id,
959
+ data: parsed.data
960
+ }, { ifRev: 0 });
961
+ return this.requireRow(row.id);
962
+ }
963
+ /**
964
+ * Merge a partial into ONE row. `clientSecret`: a plaintext sets it, `undefined`
965
+ * keeps the stored one, `null` clears it.
966
+ */
967
+ async update(id, partial) {
968
+ await this.kind.patch(id, partial);
969
+ return this.requireRow(id);
970
+ }
940
971
  /** Delete one provider record; no other row (nor its secrets) is touched. */
941
972
  async remove(id) {
942
973
  await this.kind.delete(id);
943
974
  }
944
- async replaceAll(providers) {
945
- const page = await this.kind.query({ limit: 1e3 });
946
- const nextIds = new Set(providers.map((p) => p.id));
947
- for (const row of page.records) if (!nextIds.has(row.id)) await this.kind.delete(row.id);
948
- for (const row of providers) {
949
- const { id, displayName, icon, issuerUrl, clientId, clientSecret, redirectUri, scopes, usernameClaim } = row;
950
- const body = {
951
- displayName,
952
- icon,
953
- issuerUrl,
954
- clientId,
955
- clientSecret,
956
- redirectUri,
957
- scopes,
958
- usernameClaim
959
- };
960
- const parsed = oidcProviderEntryKind.schema.safeParse(body);
961
- if (!parsed.success) throw new Error(`invalid OIDC provider '${id}': ${parsed.error.message}`);
962
- await this.kind.put({
963
- id,
964
- data: parsed.data
965
- });
966
- }
975
+ async requireRow(id) {
976
+ const row = await this.getResolved(id);
977
+ if (row === null) throw new Error(`OIDC provider '${id}' is not readable after the write`);
978
+ return row;
967
979
  }
968
980
  };
969
981
  //#endregion
@@ -1068,7 +1080,7 @@ var AuthOidcAddon = class extends BaseAddon {
1068
1080
  super({ ...DEFAULT_CONFIG });
1069
1081
  }
1070
1082
  async onConfigChanged() {
1071
- this.activeProviders = await this.loadPersistedProviders();
1083
+ if (this.providerStore !== null) this.activeProviders = await this.providerStore.listResolved();
1072
1084
  this.rebuildInstances();
1073
1085
  }
1074
1086
  async onInitialize() {
@@ -1076,16 +1088,7 @@ var AuthOidcAddon = class extends BaseAddon {
1076
1088
  if (records === void 0) throw new Error("auth-oidc: ctx.records is required (hub-only addon)");
1077
1089
  await records.declare({ "oidc-provider": oidcProviderEntryKind });
1078
1090
  this.providerStore = OidcProviderStore.of(records);
1079
- this.activeProviders = await this.loadPersistedProviders();
1080
- if ((await this.providerStore.listResolved()).length === 0 && this.config.providers.length > 0) try {
1081
- await this.providerStore.replaceAll(await this.adoptSecrets(this.config.providers));
1082
- this.activeProviders = await this.loadPersistedProviders();
1083
- } catch (err) {
1084
- const msg = err instanceof Error ? err.message : String(err);
1085
- if (!msg.startsWith("records/foreign-marker:")) throw err;
1086
- this.ctx.logger.warn("OIDC: deferred config→records copy (a secret marker is bound to another row)", { meta: { error: msg } });
1087
- this.activeProviders = [...this.config.providers];
1088
- }
1091
+ this.activeProviders = await this.providerStore.listResolved();
1089
1092
  this.rebuildInstances();
1090
1093
  const authProvider = {
1091
1094
  validateCredentials: async () => null,
@@ -1171,7 +1174,10 @@ var AuthOidcAddon = class extends BaseAddon {
1171
1174
  createConnection: async (input) => {
1172
1175
  const result = createOidcConnection(this.providersConfig(), input);
1173
1176
  if (!result.ok) throw new Error(result.reason === "duplicate-id" ? `An OIDC connection with id "${input.id}" already exists` : `Invalid connection id "${input.id}" — use a lowercase slug`);
1174
- await this.persistProviders(result.config.providers);
1177
+ const row = result.config.providers.find((p) => p.id === result.id);
1178
+ if (row === void 0) throw new Error(`Invalid connection id "${input.id}"`);
1179
+ const stored = await this.requireStore().create(row);
1180
+ this.activeProviders = [...this.activeProviders, stored];
1175
1181
  this.rebuildInstances();
1176
1182
  return { id: result.id };
1177
1183
  },
@@ -1188,21 +1194,21 @@ var AuthOidcAddon = class extends BaseAddon {
1188
1194
  ...input.usernameClaim !== void 0 ? { usernameClaim: input.usernameClaim } : {}
1189
1195
  });
1190
1196
  if (!result.ok) throw new Error(`Unknown OIDC connection "${input.id}"`);
1191
- if (result.clearClientSecret) {
1192
- const cleared = result.config.providers.map((p) => p.id === input.id ? {
1193
- ...p,
1194
- clientSecret: ""
1195
- } : p);
1196
- await this.persistProviders(cleared);
1197
- } else await this.persistProviders(result.config.providers);
1197
+ const next = result.config.providers.find((p) => p.id === input.id);
1198
+ if (next === void 0) throw new Error(`Unknown OIDC connection "${input.id}"`);
1199
+ const { id: _id, clientSecret: _carried, ...fields } = next;
1200
+ const stored = await this.requireStore().update(input.id, {
1201
+ ...fields,
1202
+ ...result.clearClientSecret ? { clientSecret: null } : secretPatch.clientSecret !== void 0 ? { clientSecret: secretPatch.clientSecret } : {}
1203
+ });
1204
+ this.activeProviders = this.activeProviders.map((p) => p.id === input.id ? stored : p);
1198
1205
  this.rebuildInstances();
1199
1206
  return { ok: true };
1200
1207
  },
1201
1208
  deleteConnection: async (input) => {
1202
1209
  if (findOidcProvider(this.providersConfig(), input.id) === null) throw new Error(`Unknown OIDC connection "${input.id}"`);
1203
- const result = deleteOidcConnection(this.providersConfig(), input.id);
1204
- if (!result.ok) throw new Error(`Unknown OIDC connection "${input.id}"`);
1205
- await this.removeProvider(input.id, result.config.providers);
1210
+ await this.requireStore().remove(input.id);
1211
+ this.activeProviders = this.activeProviders.filter((p) => p.id !== input.id);
1206
1212
  this.rebuildInstances();
1207
1213
  return { ok: true };
1208
1214
  }
@@ -1244,69 +1250,9 @@ var AuthOidcAddon = class extends BaseAddon {
1244
1250
  providersConfig() {
1245
1251
  return { providers: this.activeProviders };
1246
1252
  }
1247
- async loadPersistedProviders() {
1248
- const store = this.providerStore;
1249
- if (store !== null) {
1250
- const fromRecords = await store.listResolved();
1251
- if (fromRecords.length > 0) return fromRecords;
1252
- }
1253
- return this.config.providers;
1254
- }
1255
- async persistProviders(providers) {
1256
- const adopted = await this.adoptSecrets(providers);
1257
- this.activeProviders = [...adopted];
1258
- const store = this.providerStore;
1259
- if (store !== null) {
1260
- await store.replaceAll(adopted);
1261
- return;
1262
- }
1263
- await this.updateGlobalSettings({ providers: [...adopted] });
1264
- }
1265
- async removeProvider(id, remaining) {
1266
- this.activeProviders = [...remaining];
1267
- const store = this.providerStore;
1268
- if (store !== null) {
1269
- await store.remove(id);
1270
- return;
1271
- }
1272
- await this.updateGlobalSettings({ providers: [...remaining] });
1273
- }
1274
- /**
1275
- * A row can still carry a keychain marker bound to the old settings array
1276
- * (`providers[<id>].clientSecret`, owner auth-oidc) — config rows that never
1277
- * moved into records. Records refuse a marker that is not the row's own ref, so
1278
- * every such row is resolved to its value here (re-bound to the record's own ref
1279
- * on write); a marker that no longer resolves becomes an empty secret the
1280
- * operator can retype. The value is never logged.
1281
- */
1282
- async adoptSecrets(providers) {
1283
- const out = [];
1284
- for (const row of providers) {
1285
- const secret = row.clientSecret;
1286
- if (typeof secret === "string") {
1287
- out.push(row);
1288
- continue;
1289
- }
1290
- if (!isSecretMarker(secret)) {
1291
- out.push({
1292
- ...row,
1293
- clientSecret: ""
1294
- });
1295
- continue;
1296
- }
1297
- let plain = "";
1298
- const secrets = this.ctx.secrets;
1299
- if (secrets !== void 0) try {
1300
- const entry = (await secrets.resolve([secret.$secret]))[secret.$secret];
1301
- if (entry?.kind === "value") plain = entry.value;
1302
- } catch {}
1303
- if (plain === "") this.ctx.logger.warn(`OIDC: the client secret of connection "${row.id}" could not be read from the keychain; retype it in its settings`);
1304
- out.push({
1305
- ...row,
1306
- clientSecret: plain
1307
- });
1308
- }
1309
- return out;
1253
+ requireStore() {
1254
+ if (this.providerStore === null) throw new Error("auth-oidc: the records store is not ready");
1255
+ return this.providerStore;
1310
1256
  }
1311
1257
  rebuildInstances() {
1312
1258
  this.instances.clear();
@@ -1,6 +1,6 @@
1
1
  import { n as e, r as t, t as n } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare__react__loadShare__.js-BIIa6vDX.mjs";
2
2
  import { n as r, t as i } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-CQ-aEQ9b.mjs";
3
- import { n as a, t as o } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Di6YsQxe.mjs";
3
+ import { n as a, t as o } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CQJ6wKXR.mjs";
4
4
  import { n as s, r as c, t as l } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-BL2etuqg.mjs";
5
5
  //#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
6
6
  var u = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), d = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), f = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), p = (e) => {
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.451",
21
+ version: "1.2.452",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_auth_webauthn_widgets",
@@ -33,7 +33,7 @@ var e = {
33
33
  },
34
34
  "@camstack/ui-library": {
35
35
  name: "@camstack/ui-library",
36
- version: "1.2.356",
36
+ version: "1.2.357",
37
37
  scope: ["default"],
38
38
  loaded: !1,
39
39
  from: "addon_auth_webauthn_widgets",