@ima-jin/config 0.8.27 → 0.8.28

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.cjs CHANGED
@@ -226,8 +226,8 @@ var SERVICES = [
226
226
  { name: "github", label: "GitHub", icon: "\u{1F419}", description: "Source code", devPort: 3e3, prodPort: 7e3, schema: "public", tier: "core", visibility: "public", category: "meta", externalUrl: "https://github.com/ima-jin/imajin-ai" },
227
227
  { name: "docs", label: "Docs", icon: "\u{1F4C4}", description: "API documentation", devPort: 3e3, prodPort: 7e3, schema: "public", tier: "core", visibility: "public", category: "meta", wwwPath: "/developer-guide" },
228
228
  // Daemon processes — not web apps, no HTTP port exposed
229
- { name: "broker-agent", label: "Broker Agent", icon: "\u{1F916}", description: "Telegram broker agent \u2014 conversational surface for social coordination (#1101)", devPort: 0, prodPort: 0, schema: null, tier: "core", visibility: "internal", category: "infrastructure" },
230
- { name: "corpus", label: "Corpus", icon: "\u{1F50E}", description: "Per-DID corpus indexing and BM25 search service (#1737)", devPort: 8013, prodPort: 8013, schema: null, tier: "core", visibility: "internal", category: "infrastructure" }
229
+ { name: "broker-agent", label: "Broker Agent", icon: "\u{1F916}", description: "Telegram broker agent \u2014 conversational surface for social coordination", devPort: 0, prodPort: 0, schema: null, tier: "core", visibility: "internal", category: "infrastructure" },
230
+ { name: "corpus", label: "Corpus", icon: "\u{1F50E}", description: "Per-DID corpus indexing and BM25 search service", devPort: 8013, prodPort: 8013, schema: null, tier: "core", visibility: "internal", category: "infrastructure" }
231
231
  // Connected apps (separate repos) will use the plugin architecture (#249).
232
232
  // Not included here — they authenticate via delegated sessions, not the monorepo manifest.
233
233
  ];
@@ -426,7 +426,7 @@ var lastGlobalCleanup = Date.now();
426
426
  function pruneStore(now) {
427
427
  if (now - lastGlobalCleanup < 6e4) return;
428
428
  store.forEach((entry, key) => {
429
- if (now - entry.lastSeen > 12e4) {
429
+ if (now >= entry.retainUntil) {
430
430
  store.delete(key);
431
431
  }
432
432
  });
@@ -436,9 +436,9 @@ function rateLimit(key, limit, windowMs) {
436
436
  const now = Date.now();
437
437
  pruneStore(now);
438
438
  const windowStart = now - windowMs;
439
- const entry = store.get(key) ?? { timestamps: [], lastSeen: now };
439
+ const entry = store.get(key) ?? { timestamps: [], retainUntil: now };
440
440
  entry.timestamps = entry.timestamps.filter((t) => t > windowStart);
441
- entry.lastSeen = now;
441
+ entry.retainUntil = Math.max(entry.retainUntil, now + Math.max(12e4, windowMs));
442
442
  if (entry.timestamps.length >= limit) {
443
443
  const oldest = entry.timestamps[0];
444
444
  const retryAfter = Math.ceil((oldest + windowMs - now) / 1e3);
package/dist/index.js CHANGED
@@ -66,8 +66,8 @@ var SERVICES = [
66
66
  { name: "github", label: "GitHub", icon: "\u{1F419}", description: "Source code", devPort: 3e3, prodPort: 7e3, schema: "public", tier: "core", visibility: "public", category: "meta", externalUrl: "https://github.com/ima-jin/imajin-ai" },
67
67
  { name: "docs", label: "Docs", icon: "\u{1F4C4}", description: "API documentation", devPort: 3e3, prodPort: 7e3, schema: "public", tier: "core", visibility: "public", category: "meta", wwwPath: "/developer-guide" },
68
68
  // Daemon processes — not web apps, no HTTP port exposed
69
- { name: "broker-agent", label: "Broker Agent", icon: "\u{1F916}", description: "Telegram broker agent \u2014 conversational surface for social coordination (#1101)", devPort: 0, prodPort: 0, schema: null, tier: "core", visibility: "internal", category: "infrastructure" },
70
- { name: "corpus", label: "Corpus", icon: "\u{1F50E}", description: "Per-DID corpus indexing and BM25 search service (#1737)", devPort: 8013, prodPort: 8013, schema: null, tier: "core", visibility: "internal", category: "infrastructure" }
69
+ { name: "broker-agent", label: "Broker Agent", icon: "\u{1F916}", description: "Telegram broker agent \u2014 conversational surface for social coordination", devPort: 0, prodPort: 0, schema: null, tier: "core", visibility: "internal", category: "infrastructure" },
70
+ { name: "corpus", label: "Corpus", icon: "\u{1F50E}", description: "Per-DID corpus indexing and BM25 search service", devPort: 8013, prodPort: 8013, schema: null, tier: "core", visibility: "internal", category: "infrastructure" }
71
71
  // Connected apps (separate repos) will use the plugin architecture (#249).
72
72
  // Not included here — they authenticate via delegated sessions, not the monorepo manifest.
73
73
  ];
@@ -266,7 +266,7 @@ var lastGlobalCleanup = Date.now();
266
266
  function pruneStore(now) {
267
267
  if (now - lastGlobalCleanup < 6e4) return;
268
268
  store.forEach((entry, key) => {
269
- if (now - entry.lastSeen > 12e4) {
269
+ if (now >= entry.retainUntil) {
270
270
  store.delete(key);
271
271
  }
272
272
  });
@@ -276,9 +276,9 @@ function rateLimit(key, limit, windowMs) {
276
276
  const now = Date.now();
277
277
  pruneStore(now);
278
278
  const windowStart = now - windowMs;
279
- const entry = store.get(key) ?? { timestamps: [], lastSeen: now };
279
+ const entry = store.get(key) ?? { timestamps: [], retainUntil: now };
280
280
  entry.timestamps = entry.timestamps.filter((t) => t > windowStart);
281
- entry.lastSeen = now;
281
+ entry.retainUntil = Math.max(entry.retainUntil, now + Math.max(12e4, windowMs));
282
282
  if (entry.timestamps.length >= limit) {
283
283
  const oldest = entry.timestamps[0];
284
284
  const retryAfter = Math.ceil((oldest + windowMs - now) / 1e3);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ima-jin/config",
3
- "version": "0.8.27",
3
+ "version": "0.8.28",
4
4
  "description": "Shared configuration for Imajin services — CORS, service routing, session config, handle validation, and route helpers",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/rate-limit.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  interface RateLimitEntry {
7
7
  timestamps: number[];
8
- lastSeen: number;
8
+ retainUntil: number;
9
9
  }
10
10
 
11
11
  const store = new Map<string, RateLimitEntry>();
@@ -14,7 +14,7 @@ let lastGlobalCleanup = Date.now();
14
14
  function pruneStore(now: number) {
15
15
  if (now - lastGlobalCleanup < 60_000) return;
16
16
  store.forEach((entry, key) => {
17
- if (now - entry.lastSeen > 120_000) {
17
+ if (now >= entry.retainUntil) {
18
18
  store.delete(key);
19
19
  }
20
20
  });
@@ -30,10 +30,11 @@ export function rateLimit(
30
30
  pruneStore(now);
31
31
 
32
32
  const windowStart = now - windowMs;
33
- const entry = store.get(key) ?? { timestamps: [], lastSeen: now };
33
+ const entry = store.get(key) ?? { timestamps: [], retainUntil: now };
34
34
 
35
35
  entry.timestamps = entry.timestamps.filter((t) => t > windowStart);
36
- entry.lastSeen = now;
36
+ // Cleanup must not erase a still-live long window (e.g. hourly warnings).
37
+ entry.retainUntil = Math.max(entry.retainUntil, now + Math.max(120_000, windowMs));
37
38
 
38
39
  if (entry.timestamps.length >= limit) {
39
40
  const oldest = entry.timestamps[0];
package/src/services.ts CHANGED
@@ -75,8 +75,8 @@ export const SERVICES: readonly ServiceDefinition[] = [
75
75
  { name: 'docs', label: 'Docs', icon: '📄', description: 'API documentation', devPort: 3000, prodPort: 7000, schema: "public", tier: 'core', visibility: 'public', category: 'meta', wwwPath: '/developer-guide' },
76
76
 
77
77
  // Daemon processes — not web apps, no HTTP port exposed
78
- { name: 'broker-agent', label: 'Broker Agent', icon: '🤖', description: 'Telegram broker agent — conversational surface for social coordination (#1101)', devPort: 0, prodPort: 0, schema: null, tier: 'core', visibility: 'internal', category: 'infrastructure' },
79
- { name: 'corpus', label: 'Corpus', icon: '🔎', description: 'Per-DID corpus indexing and BM25 search service (#1737)', devPort: 8013, prodPort: 8013, schema: null, tier: 'core', visibility: 'internal', category: 'infrastructure' },
78
+ { name: 'broker-agent', label: 'Broker Agent', icon: '🤖', description: 'Telegram broker agent — conversational surface for social coordination', devPort: 0, prodPort: 0, schema: null, tier: 'core', visibility: 'internal', category: 'infrastructure' },
79
+ { name: 'corpus', label: 'Corpus', icon: '🔎', description: 'Per-DID corpus indexing and BM25 search service', devPort: 8013, prodPort: 8013, schema: null, tier: 'core', visibility: 'internal', category: 'infrastructure' },
80
80
 
81
81
  // Connected apps (separate repos) will use the plugin architecture (#249).
82
82
  // Not included here — they authenticate via delegated sessions, not the monorepo manifest.