@camstack/core 0.1.20 → 0.1.22

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.
@@ -6161,7 +6161,6 @@ var noopLogger = {
6161
6161
  };
6162
6162
  var AuthManager = class {
6163
6163
  jwtSecret;
6164
- scopedTokenManager = null;
6165
6164
  logger;
6166
6165
  constructor(config, logger = noopLogger) {
6167
6166
  this.config = config;
@@ -6215,27 +6214,6 @@ var AuthManager = class {
6215
6214
  const expiresIn = opts.expiresIn ?? "24h";
6216
6215
  return import_jsonwebtoken.sign(payload, this.jwtSecret, { expiresIn });
6217
6216
  }
6218
- /**
6219
- * Set the scoped token manager for the auth chain.
6220
- */
6221
- setScopedTokenManager(manager) {
6222
- this.scopedTokenManager = manager;
6223
- }
6224
- /**
6225
- * Validate a scoped token string.
6226
- * Returns the token record if valid, null otherwise.
6227
- */
6228
- async validateScopedToken(rawToken) {
6229
- if (!this.scopedTokenManager) return null;
6230
- return this.scopedTokenManager.validate(rawToken);
6231
- }
6232
- /**
6233
- * Check whether a scoped token grants access to a given addon/route/capability.
6234
- */
6235
- matchesScopedTokenScope(token, addonId, routePath, capability) {
6236
- if (!this.scopedTokenManager) return false;
6237
- return this.scopedTokenManager.matchesScope(token, addonId, routePath, capability);
6238
- }
6239
6217
  };
6240
6218
  //#endregion
6241
6219
  //#region src/auth/parse-record.ts
@@ -6540,6 +6518,39 @@ var ScopedTokenManager = class {
6540
6518
  }
6541
6519
  });
6542
6520
  }
6521
+ /**
6522
+ * One-shot migration: drop tokens whose owner can't be resolved.
6523
+ *
6524
+ * Two ways a token can end up orphan:
6525
+ * • Pre-fix tokens minted via the CLI were owned by the literal
6526
+ * string `"system"` (provider hardcode, fixed 2026-05-11).
6527
+ * • A user gets deleted but their tokens were not cascade-revoked.
6528
+ *
6529
+ * Either way the UI's `listScopedTokens({ userId: u.id })` never
6530
+ * returns them, so the operator can't revoke through the normal flow.
6531
+ * We sweep both classes by passing the live user-id set in.
6532
+ *
6533
+ * Idempotent: if no orphans exist the method is a no-op.
6534
+ * Returns the number of tokens removed.
6535
+ */
6536
+ async cleanupOrphans(validUserIds) {
6537
+ const all = await this.store.query.query({
6538
+ collection: TOKENS_COLLECTION,
6539
+ filter: {}
6540
+ });
6541
+ let removed = 0;
6542
+ for (const entry of all) {
6543
+ const record = parseToken(entry.data);
6544
+ if (record.userId === "system" || !validUserIds.has(record.userId)) {
6545
+ await this.store.delete.mutate({
6546
+ collection: TOKENS_COLLECTION,
6547
+ key: record.id
6548
+ });
6549
+ removed++;
6550
+ }
6551
+ }
6552
+ return removed;
6553
+ }
6543
6554
  };
6544
6555
  //#endregion
6545
6556
  //#region src/builtins/local-auth/auth-schema.ts
@@ -6757,6 +6768,10 @@ var LocalAuthAddon = class extends BaseAddon {
6757
6768
  this.scopedTokenManager = new ScopedTokenManager(store);
6758
6769
  try {
6759
6770
  await this.userManager.ensureAdminExists();
6771
+ const liveUsers = await this.userManager.listAll();
6772
+ const liveIds = new Set(liveUsers.map((u) => u.id));
6773
+ const removed = await this.scopedTokenManager.cleanupOrphans(liveIds);
6774
+ if (removed > 0) this.ctx.logger.warn(`cleaned up ${removed} orphan scoped-token(s) on boot`);
6760
6775
  } catch (err) {
6761
6776
  const detail = err instanceof Error ? err.message : String(err);
6762
6777
  throw new Error(`local-auth bootstrap failed: ensureAdminExists threw before \`user-management\` could be registered. Most likely a \`users\` collection schema mismatch in the settings-store. Underlying: ${detail}`, { cause: err });
@@ -6843,7 +6858,7 @@ var LocalAuthAddon = class extends BaseAddon {
6843
6858
  },
6844
6859
  createScopedToken: async (input) => {
6845
6860
  if (!this.scopedTokenManager) throw new Error("Scoped token management not available");
6846
- const { token, record } = await this.scopedTokenManager.create("system", input.name, input.scopes, input.expiresAt);
6861
+ const { token, record } = await this.scopedTokenManager.create(input.userId, input.name, input.scopes, input.expiresAt);
6847
6862
  return {
6848
6863
  token,
6849
6864
  record