@basaltkit/ai 0.10.0 → 0.11.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.
Files changed (2) hide show
  1. package/dist/index.js +36 -2
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -364,7 +364,16 @@ function detectAppFile(reader) {
364
364
  (factory) => new RegExp(`\\b${factory}\\s*\\(`).test(found.content)
365
365
  );
366
366
  const fastifyLoggerConfigured = /fastify\s*:\s*\{[^}]*\blogger\b/.test(found.content);
367
- const memorySources = ["MemoryTenantSource", "MemoryUserSource"].filter(
367
+ const memorySources = [
368
+ "MemoryTenantSource",
369
+ "MemoryUserSource",
370
+ // Security-critical in-memory stores: auth/authorization/domain state that
371
+ // must survive restarts and be shared across instances in production.
372
+ "MemoryPasskeyStore",
373
+ "MemoryWebAuthnChallengeStore",
374
+ "MemoryAccessStore",
375
+ "MemoryDomainStore"
376
+ ].filter(
368
377
  (source) => found.content.includes(source)
369
378
  );
370
379
  const pluginCalls = [
@@ -631,6 +640,31 @@ var DEFAULT_RULES = [
631
640
  docs: "/guide/configuration"
632
641
  };
633
642
  }
643
+ }),
644
+ defineRule({
645
+ id: "in-memory-security-store",
646
+ category: "security",
647
+ check(ctx) {
648
+ const SECURITY_STORES = {
649
+ MemoryPasskeyStore: "WebAuthn passkeys",
650
+ MemoryWebAuthnChallengeStore: "WebAuthn challenges",
651
+ MemoryAccessStore: "roles & permissions",
652
+ MemoryDomainStore: "verified custom domains"
653
+ };
654
+ const hit = (ctx.app?.memorySources ?? []).find((source) => source in SECURITY_STORES);
655
+ if (!hit) return null;
656
+ return {
657
+ id: "in-memory-security-store",
658
+ title: "Security state is kept in an in-memory store",
659
+ severity: "warning",
660
+ category: "security",
661
+ detected: `${hit} holds ${SECURITY_STORES[hit]} in memory.`,
662
+ recommended: "Back it with a durable store (database/Redis) in production.",
663
+ reason: "In-memory security stores are wiped on restart and are not shared across instances \u2014 passkeys/permissions/verified domains would silently reset or diverge per replica, which can lock users out or bypass authorization.",
664
+ fix: `// swap ${hit} for a durable implementation of the same interface`,
665
+ docs: "/guide/security"
666
+ };
667
+ }
634
668
  })
635
669
  ];
636
670
  var GLOBAL_MODELS = /* @__PURE__ */ new Set(["Tenant", "User", "Plan", "WebhookEvent", "Migration"]);
@@ -2050,7 +2084,7 @@ function renderDoctor(diagnostics, io) {
2050
2084
  }
2051
2085
  if (d.docs) {
2052
2086
  io.log("");
2053
- io.log(` Docs: https://basalt.dev${d.docs}`);
2087
+ io.log(` Docs: https://basaltkit.dev${d.docs}`);
2054
2088
  }
2055
2089
  io.log("");
2056
2090
  io.log(" " + "\u2500".repeat(60));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basaltkit/ai",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "AI-native developer experience for Basalt: a provider-agnostic engine plus `basalt ai` CLI that understands the project's stack, analyzes it, and diagnoses issues — following the framework's own conventions, not inventing new ones.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,7 +14,7 @@
14
14
  "dist"
15
15
  ],
16
16
  "dependencies": {
17
- "@basaltkit/cli": "^1.0.0",
17
+ "@basaltkit/cli": "^1.2.0",
18
18
  "@basaltkit/generator": "^1.1.1"
19
19
  },
20
20
  "devDependencies": {