iranti 0.1.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 (255) hide show
  1. package/.env.example +63 -0
  2. package/LICENSE +12 -0
  3. package/README.md +520 -0
  4. package/bin/iranti.js +24 -0
  5. package/dist/scripts/api-key-create.js +57 -0
  6. package/dist/scripts/api-key-list.js +42 -0
  7. package/dist/scripts/api-key-revoke.js +42 -0
  8. package/dist/scripts/iranti-cli.js +387 -0
  9. package/dist/scripts/seed-codebase.js +138 -0
  10. package/dist/scripts/seed.js +121 -0
  11. package/dist/scripts/setup.js +86 -0
  12. package/dist/src/api/archivistScheduler.d.ts +8 -0
  13. package/dist/src/api/archivistScheduler.d.ts.map +1 -0
  14. package/dist/src/api/archivistScheduler.js +100 -0
  15. package/dist/src/api/archivistScheduler.js.map +1 -0
  16. package/dist/src/api/diag.d.ts +2 -0
  17. package/dist/src/api/diag.d.ts.map +1 -0
  18. package/dist/src/api/diag.js +54 -0
  19. package/dist/src/api/diag.js.map +1 -0
  20. package/dist/src/api/middleware/auth.d.ts +3 -0
  21. package/dist/src/api/middleware/auth.d.ts.map +1 -0
  22. package/dist/src/api/middleware/auth.js +36 -0
  23. package/dist/src/api/middleware/auth.js.map +1 -0
  24. package/dist/src/api/middleware/authorization.d.ts +4 -0
  25. package/dist/src/api/middleware/authorization.d.ts.map +1 -0
  26. package/dist/src/api/middleware/authorization.js +54 -0
  27. package/dist/src/api/middleware/authorization.js.map +1 -0
  28. package/dist/src/api/middleware/rateLimit.d.ts +23 -0
  29. package/dist/src/api/middleware/rateLimit.d.ts.map +1 -0
  30. package/dist/src/api/middleware/rateLimit.js +70 -0
  31. package/dist/src/api/middleware/rateLimit.js.map +1 -0
  32. package/dist/src/api/middleware/validation.d.ts +128 -0
  33. package/dist/src/api/middleware/validation.d.ts.map +1 -0
  34. package/dist/src/api/middleware/validation.js +137 -0
  35. package/dist/src/api/middleware/validation.js.map +1 -0
  36. package/dist/src/api/repro.d.ts +2 -0
  37. package/dist/src/api/repro.d.ts.map +1 -0
  38. package/dist/src/api/repro.js +25 -0
  39. package/dist/src/api/repro.js.map +1 -0
  40. package/dist/src/api/routes/agents.d.ts +4 -0
  41. package/dist/src/api/routes/agents.d.ts.map +1 -0
  42. package/dist/src/api/routes/agents.js +56 -0
  43. package/dist/src/api/routes/agents.js.map +1 -0
  44. package/dist/src/api/routes/batch.d.ts +2 -0
  45. package/dist/src/api/routes/batch.d.ts.map +1 -0
  46. package/dist/src/api/routes/batch.js +63 -0
  47. package/dist/src/api/routes/batch.js.map +1 -0
  48. package/dist/src/api/routes/dev.d.ts +2 -0
  49. package/dist/src/api/routes/dev.d.ts.map +1 -0
  50. package/dist/src/api/routes/dev.js +29 -0
  51. package/dist/src/api/routes/dev.js.map +1 -0
  52. package/dist/src/api/routes/knowledge.d.ts +4 -0
  53. package/dist/src/api/routes/knowledge.d.ts.map +1 -0
  54. package/dist/src/api/routes/knowledge.js +184 -0
  55. package/dist/src/api/routes/knowledge.js.map +1 -0
  56. package/dist/src/api/routes/memory.d.ts +4 -0
  57. package/dist/src/api/routes/memory.d.ts.map +1 -0
  58. package/dist/src/api/routes/memory.js +150 -0
  59. package/dist/src/api/routes/memory.js.map +1 -0
  60. package/dist/src/api/server.d.ts +2 -0
  61. package/dist/src/api/server.d.ts.map +1 -0
  62. package/dist/src/api/server.js +191 -0
  63. package/dist/src/api/server.js.map +1 -0
  64. package/dist/src/archivist/index.d.ts +10 -0
  65. package/dist/src/archivist/index.d.ts.map +1 -0
  66. package/dist/src/archivist/index.js +232 -0
  67. package/dist/src/archivist/index.js.map +1 -0
  68. package/dist/src/attendant/AttendantInstance.d.ts +96 -0
  69. package/dist/src/attendant/AttendantInstance.d.ts.map +1 -0
  70. package/dist/src/attendant/AttendantInstance.js +808 -0
  71. package/dist/src/attendant/AttendantInstance.js.map +1 -0
  72. package/dist/src/attendant/index.d.ts +12 -0
  73. package/dist/src/attendant/index.d.ts.map +1 -0
  74. package/dist/src/attendant/index.js +39 -0
  75. package/dist/src/attendant/index.js.map +1 -0
  76. package/dist/src/attendant/registry.d.ts +6 -0
  77. package/dist/src/attendant/registry.d.ts.map +1 -0
  78. package/dist/src/attendant/registry.js +27 -0
  79. package/dist/src/attendant/registry.js.map +1 -0
  80. package/dist/src/generated/prisma/browser.d.ts +35 -0
  81. package/dist/src/generated/prisma/browser.d.ts.map +1 -0
  82. package/dist/src/generated/prisma/browser.js +57 -0
  83. package/dist/src/generated/prisma/browser.js.map +1 -0
  84. package/dist/src/generated/prisma/client.d.ts +54 -0
  85. package/dist/src/generated/prisma/client.d.ts.map +1 -0
  86. package/dist/src/generated/prisma/client.js +71 -0
  87. package/dist/src/generated/prisma/client.js.map +1 -0
  88. package/dist/src/generated/prisma/commonInputTypes.d.ts +415 -0
  89. package/dist/src/generated/prisma/commonInputTypes.d.ts.map +1 -0
  90. package/dist/src/generated/prisma/commonInputTypes.js +12 -0
  91. package/dist/src/generated/prisma/commonInputTypes.js.map +1 -0
  92. package/dist/src/generated/prisma/enums.d.ts +2 -0
  93. package/dist/src/generated/prisma/enums.d.ts.map +1 -0
  94. package/dist/src/generated/prisma/enums.js +12 -0
  95. package/dist/src/generated/prisma/enums.js.map +1 -0
  96. package/dist/src/generated/prisma/internal/class.d.ts +186 -0
  97. package/dist/src/generated/prisma/internal/class.d.ts.map +1 -0
  98. package/dist/src/generated/prisma/internal/class.js +86 -0
  99. package/dist/src/generated/prisma/internal/class.js.map +1 -0
  100. package/dist/src/generated/prisma/internal/prismaNamespace.d.ts +1015 -0
  101. package/dist/src/generated/prisma/internal/prismaNamespace.d.ts.map +1 -0
  102. package/dist/src/generated/prisma/internal/prismaNamespace.js +220 -0
  103. package/dist/src/generated/prisma/internal/prismaNamespace.js.map +1 -0
  104. package/dist/src/generated/prisma/internal/prismaNamespaceBrowser.d.ts +152 -0
  105. package/dist/src/generated/prisma/internal/prismaNamespaceBrowser.d.ts.map +1 -0
  106. package/dist/src/generated/prisma/internal/prismaNamespaceBrowser.js +191 -0
  107. package/dist/src/generated/prisma/internal/prismaNamespaceBrowser.js.map +1 -0
  108. package/dist/src/generated/prisma/models/Archive.d.ts +1425 -0
  109. package/dist/src/generated/prisma/models/Archive.d.ts.map +1 -0
  110. package/dist/src/generated/prisma/models/Archive.js +3 -0
  111. package/dist/src/generated/prisma/models/Archive.js.map +1 -0
  112. package/dist/src/generated/prisma/models/Entity.d.ts +1129 -0
  113. package/dist/src/generated/prisma/models/Entity.d.ts.map +1 -0
  114. package/dist/src/generated/prisma/models/Entity.js +3 -0
  115. package/dist/src/generated/prisma/models/Entity.js.map +1 -0
  116. package/dist/src/generated/prisma/models/EntityAlias.d.ts +1347 -0
  117. package/dist/src/generated/prisma/models/EntityAlias.d.ts.map +1 -0
  118. package/dist/src/generated/prisma/models/EntityAlias.js +3 -0
  119. package/dist/src/generated/prisma/models/EntityAlias.js.map +1 -0
  120. package/dist/src/generated/prisma/models/EntityRelationship.d.ts +1143 -0
  121. package/dist/src/generated/prisma/models/EntityRelationship.d.ts.map +1 -0
  122. package/dist/src/generated/prisma/models/EntityRelationship.js +3 -0
  123. package/dist/src/generated/prisma/models/EntityRelationship.js.map +1 -0
  124. package/dist/src/generated/prisma/models/KnowledgeEntry.d.ts +1322 -0
  125. package/dist/src/generated/prisma/models/KnowledgeEntry.d.ts.map +1 -0
  126. package/dist/src/generated/prisma/models/KnowledgeEntry.js +3 -0
  127. package/dist/src/generated/prisma/models/KnowledgeEntry.js.map +1 -0
  128. package/dist/src/generated/prisma/models/WriteReceipt.d.ts +1147 -0
  129. package/dist/src/generated/prisma/models/WriteReceipt.d.ts.map +1 -0
  130. package/dist/src/generated/prisma/models/WriteReceipt.js +3 -0
  131. package/dist/src/generated/prisma/models/WriteReceipt.js.map +1 -0
  132. package/dist/src/generated/prisma/models.d.ts +8 -0
  133. package/dist/src/generated/prisma/models.d.ts.map +1 -0
  134. package/dist/src/generated/prisma/models.js +3 -0
  135. package/dist/src/generated/prisma/models.js.map +1 -0
  136. package/dist/src/lib/escalationPaths.d.ts +9 -0
  137. package/dist/src/lib/escalationPaths.d.ts.map +1 -0
  138. package/dist/src/lib/escalationPaths.js +38 -0
  139. package/dist/src/lib/escalationPaths.js.map +1 -0
  140. package/dist/src/lib/llm.d.ts +32 -0
  141. package/dist/src/lib/llm.d.ts.map +1 -0
  142. package/dist/src/lib/llm.js +161 -0
  143. package/dist/src/lib/llm.js.map +1 -0
  144. package/dist/src/lib/metrics.d.ts +21 -0
  145. package/dist/src/lib/metrics.d.ts.map +1 -0
  146. package/dist/src/lib/metrics.js +46 -0
  147. package/dist/src/lib/metrics.js.map +1 -0
  148. package/dist/src/lib/providers/claude.d.ts +7 -0
  149. package/dist/src/lib/providers/claude.d.ts.map +1 -0
  150. package/dist/src/lib/providers/claude.js +9 -0
  151. package/dist/src/lib/providers/claude.js.map +1 -0
  152. package/dist/src/lib/providers/gemini.d.ts +10 -0
  153. package/dist/src/lib/providers/gemini.d.ts.map +1 -0
  154. package/dist/src/lib/providers/gemini.js +40 -0
  155. package/dist/src/lib/providers/gemini.js.map +1 -0
  156. package/dist/src/lib/providers/groq.d.ts +10 -0
  157. package/dist/src/lib/providers/groq.d.ts.map +1 -0
  158. package/dist/src/lib/providers/groq.js +39 -0
  159. package/dist/src/lib/providers/groq.js.map +1 -0
  160. package/dist/src/lib/providers/mistral.d.ts +10 -0
  161. package/dist/src/lib/providers/mistral.d.ts.map +1 -0
  162. package/dist/src/lib/providers/mistral.js +39 -0
  163. package/dist/src/lib/providers/mistral.js.map +1 -0
  164. package/dist/src/lib/providers/mock.d.ts +24 -0
  165. package/dist/src/lib/providers/mock.d.ts.map +1 -0
  166. package/dist/src/lib/providers/mock.js +129 -0
  167. package/dist/src/lib/providers/mock.js.map +1 -0
  168. package/dist/src/lib/providers/ollama.d.ts +10 -0
  169. package/dist/src/lib/providers/ollama.d.ts.map +1 -0
  170. package/dist/src/lib/providers/ollama.js +39 -0
  171. package/dist/src/lib/providers/ollama.js.map +1 -0
  172. package/dist/src/lib/providers/openai.d.ts +11 -0
  173. package/dist/src/lib/providers/openai.d.ts.map +1 -0
  174. package/dist/src/lib/providers/openai.js +38 -0
  175. package/dist/src/lib/providers/openai.js.map +1 -0
  176. package/dist/src/lib/requestContext.d.ts +8 -0
  177. package/dist/src/lib/requestContext.d.ts.map +1 -0
  178. package/dist/src/lib/requestContext.js +10 -0
  179. package/dist/src/lib/requestContext.js.map +1 -0
  180. package/dist/src/lib/router.d.ts +16 -0
  181. package/dist/src/lib/router.d.ts.map +1 -0
  182. package/dist/src/lib/router.js +63 -0
  183. package/dist/src/lib/router.js.map +1 -0
  184. package/dist/src/librarian/chunker.d.ts +16 -0
  185. package/dist/src/librarian/chunker.d.ts.map +1 -0
  186. package/dist/src/librarian/chunker.js +67 -0
  187. package/dist/src/librarian/chunker.js.map +1 -0
  188. package/dist/src/librarian/getPolicy.d.ts +3 -0
  189. package/dist/src/librarian/getPolicy.d.ts.map +1 -0
  190. package/dist/src/librarian/getPolicy.js +22 -0
  191. package/dist/src/librarian/getPolicy.js.map +1 -0
  192. package/dist/src/librarian/guards.d.ts +9 -0
  193. package/dist/src/librarian/guards.d.ts.map +1 -0
  194. package/dist/src/librarian/guards.js +52 -0
  195. package/dist/src/librarian/guards.js.map +1 -0
  196. package/dist/src/librarian/index.d.ts +20 -0
  197. package/dist/src/librarian/index.d.ts.map +1 -0
  198. package/dist/src/librarian/index.js +512 -0
  199. package/dist/src/librarian/index.js.map +1 -0
  200. package/dist/src/librarian/policy.d.ts +13 -0
  201. package/dist/src/librarian/policy.d.ts.map +1 -0
  202. package/dist/src/librarian/policy.js +20 -0
  203. package/dist/src/librarian/policy.js.map +1 -0
  204. package/dist/src/librarian/scoring.d.ts +8 -0
  205. package/dist/src/librarian/scoring.d.ts.map +1 -0
  206. package/dist/src/librarian/scoring.js +10 -0
  207. package/dist/src/librarian/scoring.js.map +1 -0
  208. package/dist/src/librarian/source-reliability.d.ts +8 -0
  209. package/dist/src/librarian/source-reliability.d.ts.map +1 -0
  210. package/dist/src/librarian/source-reliability.js +105 -0
  211. package/dist/src/librarian/source-reliability.js.map +1 -0
  212. package/dist/src/library/agent-registry.d.ts +31 -0
  213. package/dist/src/library/agent-registry.d.ts.map +1 -0
  214. package/dist/src/library/agent-registry.js +197 -0
  215. package/dist/src/library/agent-registry.js.map +1 -0
  216. package/dist/src/library/client.d.ts +5 -0
  217. package/dist/src/library/client.d.ts.map +1 -0
  218. package/dist/src/library/client.js +39 -0
  219. package/dist/src/library/client.js.map +1 -0
  220. package/dist/src/library/entity-resolution.d.ts +47 -0
  221. package/dist/src/library/entity-resolution.d.ts.map +1 -0
  222. package/dist/src/library/entity-resolution.js +344 -0
  223. package/dist/src/library/entity-resolution.js.map +1 -0
  224. package/dist/src/library/locks.d.ts +9 -0
  225. package/dist/src/library/locks.d.ts.map +1 -0
  226. package/dist/src/library/locks.js +38 -0
  227. package/dist/src/library/locks.js.map +1 -0
  228. package/dist/src/library/queries.d.ts +66 -0
  229. package/dist/src/library/queries.d.ts.map +1 -0
  230. package/dist/src/library/queries.js +169 -0
  231. package/dist/src/library/queries.js.map +1 -0
  232. package/dist/src/library/relationships.d.ts +30 -0
  233. package/dist/src/library/relationships.d.ts.map +1 -0
  234. package/dist/src/library/relationships.js +97 -0
  235. package/dist/src/library/relationships.js.map +1 -0
  236. package/dist/src/sdk/index.d.ts +108 -0
  237. package/dist/src/sdk/index.d.ts.map +1 -0
  238. package/dist/src/sdk/index.js +323 -0
  239. package/dist/src/sdk/index.js.map +1 -0
  240. package/dist/src/security/apiKeys.d.ts +48 -0
  241. package/dist/src/security/apiKeys.d.ts.map +1 -0
  242. package/dist/src/security/apiKeys.js +279 -0
  243. package/dist/src/security/apiKeys.js.map +1 -0
  244. package/dist/src/types.d.ts +54 -0
  245. package/dist/src/types.d.ts.map +1 -0
  246. package/dist/src/types.js +4 -0
  247. package/dist/src/types.js.map +1 -0
  248. package/package.json +86 -0
  249. package/prisma/migrations/20260228090200_init/migration.sql +49 -0
  250. package/prisma/migrations/20260228121746_add_properties_and_relationships/migration.sql +29 -0
  251. package/prisma/migrations/20260301223834_add_superseded_by_pointer/migration.sql +4 -0
  252. package/prisma/migrations/20260301225152_add_write_receipts/migration.sql +20 -0
  253. package/prisma/migrations/20260302135650_entity_resolution/migration.sql +33 -0
  254. package/prisma/migrations/migration_lock.toml +3 -0
  255. package/prisma/schema.prisma +118 -0
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require("dotenv/config");
4
+ const client_1 = require("../src/library/client");
5
+ const queries_1 = require("../src/library/queries");
6
+ // Initialize DB
7
+ if (!process.env.DATABASE_URL) {
8
+ throw new Error('DATABASE_URL environment variable is required');
9
+ }
10
+ (0, client_1.initDb)(process.env.DATABASE_URL);
11
+ // ─── Staff Operating Rules ───────────────────────────────────────────────────
12
+ const STAFF_ENTRIES = [
13
+ {
14
+ entityType: 'system',
15
+ entityId: 'librarian',
16
+ key: 'operating_rules',
17
+ valueRaw: {
18
+ version: '0.1.0',
19
+ rules: [
20
+ 'All writes from external agents go through the Librarian — never directly to the database',
21
+ 'Check for existing entries before every write',
22
+ 'Log every decision with a reason — nothing is silently overwritten',
23
+ 'Deterministic resolution for exact duplicates — keep the higher confidence entry',
24
+ 'Model-assisted resolution for ambiguous conflicts',
25
+ 'Write to escalation/active/ when confidence in resolution is below threshold',
26
+ 'Never modify entries where isProtected = true',
27
+ 'Run initialization pass on blank Library before any agent is allowed to write',
28
+ ],
29
+ conflictThreshold: 10,
30
+ },
31
+ valueSummary: 'Librarian manages all Library writes, detects and resolves conflicts, escalates when uncertain.',
32
+ confidence: 100,
33
+ source: 'seed',
34
+ createdBy: 'Seed',
35
+ isProtected: true,
36
+ },
37
+ {
38
+ entityType: 'system',
39
+ entityId: 'attendant',
40
+ key: 'operating_rules',
41
+ valueRaw: {
42
+ version: '0.1.0',
43
+ rules: [
44
+ 'Assigned one-per-external-agent — serve the agent, not the user',
45
+ 'On handshake: read AGENTS.md and MCP config, query Librarian for relevant rules and task context',
46
+ 'Deliver a compressed working memory brief — not the full KB',
47
+ 'Infer task context by observing the agent\'s recent messages',
48
+ 'Load only what is relevant to the current task',
49
+ 'Reconvene periodically to update working memory as task context shifts',
50
+ 'If context window runs low, re-read operating rules from Staff Namespace',
51
+ ],
52
+ },
53
+ valueSummary: 'Attendant manages per-agent working memory via handshake, relevance filtering, and periodic reconvene.',
54
+ confidence: 100,
55
+ source: 'seed',
56
+ createdBy: 'Seed',
57
+ isProtected: true,
58
+ },
59
+ {
60
+ entityType: 'system',
61
+ entityId: 'archivist',
62
+ key: 'operating_rules',
63
+ valueRaw: {
64
+ version: '0.1.0',
65
+ rules: [
66
+ 'Run on schedule or when conflict flags exceed threshold — not on every write',
67
+ 'Scan for expired, low-confidence, flagged, and duplicate entries',
68
+ 'Merge duplicates into single canonical entries',
69
+ 'Move challenged entries to Archive with full provenance — never delete',
70
+ 'Watch escalation/active/ for RESOLVED files',
71
+ 'Write human-resolved entries to KB as source = HumanReview, confidence = 100',
72
+ 'Move processed escalation files to escalation/resolved/',
73
+ ],
74
+ },
75
+ valueSummary: 'Archivist runs periodic cleanup, archives challenged entries, and processes human-resolved escalations.',
76
+ confidence: 100,
77
+ source: 'seed',
78
+ createdBy: 'Seed',
79
+ isProtected: true,
80
+ },
81
+ {
82
+ entityType: 'system',
83
+ entityId: 'library',
84
+ key: 'schema_version',
85
+ valueRaw: { version: '0.1.0' },
86
+ valueSummary: 'Current Library schema version.',
87
+ confidence: 100,
88
+ source: 'seed',
89
+ createdBy: 'Seed',
90
+ isProtected: true,
91
+ },
92
+ {
93
+ entityType: 'system',
94
+ entityId: 'library',
95
+ key: 'initialization_log',
96
+ valueRaw: {
97
+ initializedAt: new Date().toISOString(),
98
+ seedVersion: '0.1.0',
99
+ },
100
+ valueSummary: 'Record of when and how this Library was initialized.',
101
+ confidence: 100,
102
+ source: 'seed',
103
+ createdBy: 'Seed',
104
+ isProtected: true,
105
+ },
106
+ ];
107
+ // ─── Seed ────────────────────────────────────────────────────────────────────
108
+ async function seed() {
109
+ console.log('Seeding Staff Namespace...');
110
+ for (const entry of STAFF_ENTRIES) {
111
+ await (0, queries_1.createEntry)(entry);
112
+ console.log(` ✓ system / ${entry.entityId} / ${entry.key}`);
113
+ }
114
+ console.log('Staff Namespace seeded successfully.');
115
+ process.exit(0);
116
+ }
117
+ seed().catch((err) => {
118
+ console.error('Seed failed:', err);
119
+ process.exit(1);
120
+ });
121
+ //# sourceMappingURL=seed.js.map
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const child_process_1 = require("child_process");
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const client_1 = require("../src/library/client");
10
+ const escalationPaths_1 = require("../src/lib/escalationPaths");
11
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
12
+ function run(command, label) {
13
+ console.log(` Running: ${label}...`);
14
+ try {
15
+ (0, child_process_1.execSync)(command, { stdio: 'inherit' });
16
+ }
17
+ catch {
18
+ console.error(` Failed: ${label}`);
19
+ process.exit(1);
20
+ }
21
+ }
22
+ function scriptCommand(distScriptName, sourceScriptPath) {
23
+ const distScriptPath = path_1.default.resolve(__dirname, '..', 'dist', 'scripts', distScriptName);
24
+ if (fs_1.default.existsSync(distScriptPath)) {
25
+ return `node ${JSON.stringify(distScriptPath)}`;
26
+ }
27
+ return `npx ts-node ${sourceScriptPath}`;
28
+ }
29
+ async function isSeeded() {
30
+ try {
31
+ const entry = await (0, client_1.getDb)().knowledgeEntry.findUnique({
32
+ where: {
33
+ entityType_entityId_key: {
34
+ entityType: 'system',
35
+ entityId: 'library',
36
+ key: 'initialization_log',
37
+ },
38
+ },
39
+ });
40
+ return entry !== null;
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ }
46
+ // ─── Setup ───────────────────────────────────────────────────────────────────
47
+ async function setup() {
48
+ console.log('\n🔧 Iranti Setup\n');
49
+ // 1. Run migrations
50
+ console.log('Step 1 — Running database migrations...');
51
+ run('npx prisma migrate deploy', 'prisma migrate deploy');
52
+ console.log(' ✓ Migrations complete\n');
53
+ // 2. Generate Prisma client
54
+ console.log('Step 2 — Generating Prisma client...');
55
+ run('npx prisma generate', 'prisma generate');
56
+ console.log(' ✓ Client generated\n');
57
+ // 3. Seed Staff Namespace if not already seeded
58
+ console.log('Step 3 — Seeding Staff Namespace...');
59
+ const seeded = await isSeeded();
60
+ if (seeded) {
61
+ console.log(' ✓ Already seeded, skipping\n');
62
+ }
63
+ else {
64
+ run(scriptCommand('seed.js', 'scripts/seed.ts'), 'seed Staff Namespace');
65
+ console.log(' ✓ Staff Namespace seeded\n');
66
+ }
67
+ // 4. Pre-populate codebase knowledge
68
+ console.log('Step 4 — Pre-populating codebase knowledge...');
69
+ run(scriptCommand('seed-codebase.js', 'scripts/seed-codebase.ts'), 'seed codebase knowledge');
70
+ console.log(' ✓ Codebase knowledge seeded\n');
71
+ // 5. Ensure escalation folders exist
72
+ console.log('Step 5 — Ensuring escalation folders...');
73
+ const escalationPaths = await (0, escalationPaths_1.ensureEscalationFolders)();
74
+ console.log(` ✓ Escalation folders ready at: ${escalationPaths.root}\n`);
75
+ console.log('✅ Iranti setup complete.\n');
76
+ console.log('Next steps:');
77
+ console.log(' npm run test:integration — verify everything works');
78
+ console.log(' npm run dev — start development\n');
79
+ await (0, client_1.getDb)().$disconnect();
80
+ process.exit(0);
81
+ }
82
+ setup().catch((err) => {
83
+ console.error('Setup failed:', err);
84
+ process.exit(1);
85
+ });
86
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1,8 @@
1
+ import { Iranti } from '../sdk';
2
+ type SchedulerHandle = {
3
+ stop: () => void;
4
+ started: boolean;
5
+ };
6
+ export declare function startArchivistScheduler(iranti: Iranti): Promise<SchedulerHandle>;
7
+ export {};
8
+ //# sourceMappingURL=archivistScheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archivistScheduler.d.ts","sourceRoot":"","sources":["../../../src/api/archivistScheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAgBF,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA4EtF"}
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startArchivistScheduler = startArchivistScheduler;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const escalationPaths_1 = require("../lib/escalationPaths");
9
+ function parsePositiveInt(value, fallback) {
10
+ if (!value)
11
+ return fallback;
12
+ const parsed = Number.parseInt(value, 10);
13
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
14
+ }
15
+ function parseBoolean(value, fallback) {
16
+ if (value === undefined)
17
+ return fallback;
18
+ const normalized = value.trim().toLowerCase();
19
+ if (['1', 'true', 'yes', 'on'].includes(normalized))
20
+ return true;
21
+ if (['0', 'false', 'no', 'off'].includes(normalized))
22
+ return false;
23
+ return fallback;
24
+ }
25
+ async function startArchivistScheduler(iranti) {
26
+ const intervalMs = parsePositiveInt(process.env.IRANTI_ARCHIVIST_INTERVAL_MS, 0);
27
+ const debounceMs = parsePositiveInt(process.env.IRANTI_ARCHIVIST_DEBOUNCE_MS, 60000);
28
+ const watchEscalations = parseBoolean(process.env.IRANTI_ARCHIVIST_WATCH, true);
29
+ if (intervalMs <= 0 && !watchEscalations) {
30
+ return { started: false, stop: () => { } };
31
+ }
32
+ const escalationPaths = await (0, escalationPaths_1.ensureEscalationFolders)();
33
+ let running = false;
34
+ let pendingRun = false;
35
+ let disposed = false;
36
+ let intervalHandle = null;
37
+ let debounceHandle = null;
38
+ let watcher = null;
39
+ const runMaintenance = async (reason) => {
40
+ if (disposed)
41
+ return;
42
+ if (running) {
43
+ pendingRun = true;
44
+ return;
45
+ }
46
+ running = true;
47
+ try {
48
+ const report = await iranti.runMaintenance();
49
+ console.log(`[archivist] run=${reason} processed=${report.escalationsProcessed} ` +
50
+ `expired=${report.expiredArchived} low_conf=${report.lowConfidenceArchived} errors=${report.errors.length}`);
51
+ }
52
+ catch (err) {
53
+ console.error('[archivist] scheduled maintenance failed:', err);
54
+ }
55
+ finally {
56
+ running = false;
57
+ if (pendingRun && !disposed) {
58
+ pendingRun = false;
59
+ setImmediate(() => {
60
+ void runMaintenance('pending');
61
+ });
62
+ }
63
+ }
64
+ };
65
+ const scheduleDebouncedRun = () => {
66
+ if (disposed)
67
+ return;
68
+ if (debounceHandle)
69
+ clearTimeout(debounceHandle);
70
+ debounceHandle = setTimeout(() => {
71
+ debounceHandle = null;
72
+ void runMaintenance('escalation_change');
73
+ }, debounceMs);
74
+ };
75
+ if (intervalMs > 0) {
76
+ intervalHandle = setInterval(() => {
77
+ void runMaintenance('interval');
78
+ }, intervalMs);
79
+ }
80
+ if (watchEscalations) {
81
+ watcher = fs_1.default.watch(escalationPaths.active, (_eventType, filename) => {
82
+ if (!filename || !filename.endsWith('.md'))
83
+ return;
84
+ scheduleDebouncedRun();
85
+ });
86
+ }
87
+ return {
88
+ started: true,
89
+ stop: () => {
90
+ disposed = true;
91
+ if (intervalHandle)
92
+ clearInterval(intervalHandle);
93
+ if (debounceHandle)
94
+ clearTimeout(debounceHandle);
95
+ if (watcher)
96
+ watcher.close();
97
+ },
98
+ };
99
+ }
100
+ //# sourceMappingURL=archivistScheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archivistScheduler.js","sourceRoot":"","sources":["../../../src/api/archivistScheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=diag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diag.d.ts","sourceRoot":"","sources":["../../../src/api/diag.ts"],"names":[],"mappings":""}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const express_1 = __importDefault(require("express"));
7
+ const http_1 = __importDefault(require("http"));
8
+ function logHandles(label) {
9
+ console.log(`--- ${label} ---`);
10
+ const handles = process._getActiveHandles();
11
+ const requests = process._getActiveRequests();
12
+ console.log(`Active Handles: ${handles.length}`);
13
+ handles.forEach((h, i) => {
14
+ console.log(` Handle ${i}: ${h.constructor.name} ${h.fd ? `(fd: ${h.fd})` : ''}`);
15
+ });
16
+ console.log(`Active Requests: ${requests.length}`);
17
+ console.log(`------------------\n`);
18
+ }
19
+ async function testExpress() {
20
+ console.log('Testing Express 5 app.listen...');
21
+ const app = (0, express_1.default)();
22
+ const server = app.listen(3001, () => {
23
+ console.log('Express listening on 3001');
24
+ logHandles('After Express listen');
25
+ // Check if server handle is ref'd
26
+ if (server._handle && typeof server._handle.hasRef === 'function') {
27
+ console.log(`Server handle hasRef: ${server._handle.hasRef()}`);
28
+ }
29
+ // Wait a bit and check again
30
+ setTimeout(() => {
31
+ logHandles('After 1s (Express)');
32
+ server.close();
33
+ testRawHttp();
34
+ }, 1000);
35
+ });
36
+ }
37
+ function testRawHttp() {
38
+ console.log('Testing Raw http.createServer listen...');
39
+ const server = http_1.default.createServer((req, res) => {
40
+ res.end('ok');
41
+ });
42
+ server.listen(3002, () => {
43
+ console.log('Raw HTTP listening on 3002');
44
+ logHandles('After Raw HTTP listen');
45
+ setTimeout(() => {
46
+ logHandles('After 1s (Raw HTTP)');
47
+ server.close();
48
+ console.log('Diagnosis complete.');
49
+ }, 1000);
50
+ });
51
+ }
52
+ logHandles('Startup');
53
+ testExpress();
54
+ //# sourceMappingURL=diag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diag.js","sourceRoot":"","sources":["../../../src/api/diag.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,gDAAwB;AAExB,SAAS,UAAU,CAAC,KAAa;IAC7B,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC;IAChC,MAAM,OAAO,GAAI,OAAe,CAAC,iBAAiB,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAI,OAAe,CAAC,kBAAkB,EAAE,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,OAAO,CAAC,CAAC,CAAM,EAAE,CAAS,EAAE,EAAE;QAClC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,oBAAoB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,WAAW;IACtB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IACtB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACjC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,UAAU,CAAC,sBAAsB,CAAC,CAAC;QAEnC,kCAAkC;QAClC,IAAK,MAAc,CAAC,OAAO,IAAI,OAAQ,MAAc,CAAC,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAClF,OAAO,CAAC,GAAG,CAAC,yBAA0B,MAAc,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7E,CAAC;QAED,6BAA6B;QAC7B,UAAU,CAAC,GAAG,EAAE;YACZ,UAAU,CAAC,oBAAoB,CAAC,CAAC;YACjC,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,WAAW,EAAE,CAAC;QAClB,CAAC,EAAE,IAAI,CAAC,CAAC;IACb,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,WAAW;IAChB,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,cAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC1C,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACrB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,UAAU,CAAC,uBAAuB,CAAC,CAAC;QAEpC,UAAU,CAAC,GAAG,EAAE;YACZ,UAAU,CAAC,qBAAqB,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACvC,CAAC,EAAE,IAAI,CAAC,CAAC;IACb,CAAC,CAAC,CAAC;AACP,CAAC;AAED,UAAU,CAAC,SAAS,CAAC,CAAC;AACtB,WAAW,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ export declare function authenticate(req: Request, res: Response, next: NextFunction): Promise<void>;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../src/api/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAoB1D,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBjG"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authenticate = authenticate;
4
+ const apiKeys_1 = require("../../security/apiKeys");
5
+ function extractApiKey(req) {
6
+ const fromHeader = req.headers['x-iranti-key'];
7
+ const keyHeader = Array.isArray(fromHeader) ? fromHeader[0] : fromHeader;
8
+ if (typeof keyHeader === 'string' && keyHeader.trim().length > 0) {
9
+ return keyHeader.trim();
10
+ }
11
+ const authHeader = req.headers['authorization'];
12
+ const auth = Array.isArray(authHeader) ? authHeader[0] : authHeader;
13
+ if (!auth)
14
+ return undefined;
15
+ const match = auth.match(/^Bearer\s+(.+)$/i);
16
+ if (!match)
17
+ return undefined;
18
+ const token = match[1].trim();
19
+ return token.length > 0 ? token : undefined;
20
+ }
21
+ async function authenticate(req, res, next) {
22
+ const providedStr = extractApiKey(req);
23
+ const result = await (0, apiKeys_1.validateApiKey)(providedStr);
24
+ if (!result.ok) {
25
+ res.status(result.status ?? 401).json({ error: result.error ?? 'Unauthorized. Provide a valid X-Iranti-Key header.' });
26
+ return;
27
+ }
28
+ req.irantiAuth = {
29
+ mode: result.mode ?? 'registry',
30
+ keyId: result.keyId ?? 'unknown',
31
+ owner: result.owner ?? 'unknown',
32
+ scopes: result.scopes ?? ['*'],
33
+ };
34
+ next();
35
+ }
36
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../../src/api/middleware/auth.ts"],"names":[],"mappings":";;AAoBA,oCAiBC;AApCD,oDAAwD;AAExD,SAAS,aAAa,CAAC,GAAY;IAC/B,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACzE,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/D,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACpE,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAE5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9B,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC9E,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAc,EAAC,WAAW,CAAC,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,oDAAoD,EAAE,CAAC,CAAC;QACvH,OAAO;IACX,CAAC;IAEA,GAAW,CAAC,UAAU,GAAG;QACtB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,UAAU;QAC/B,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;QAChC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;QAChC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC;KACjC,CAAC;IAEF,IAAI,EAAE,CAAC;AACX,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { NextFunction, Request, Response } from 'express';
2
+ export declare function requireAnyScope(requiredScopes: string[]): (req: Request, res: Response, next: NextFunction) => void;
3
+ export declare function requireScopeByMethod(readScope: string, writeScope: string): (req: Request, res: Response, next: NextFunction) => void;
4
+ //# sourceMappingURL=authorization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../../../../src/api/middleware/authorization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAuB1D,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,IAG5C,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAkBjE;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,IAC9D,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAKjE"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireAnyScope = requireAnyScope;
4
+ exports.requireScopeByMethod = requireScopeByMethod;
5
+ function normalizeScopes(scopes) {
6
+ if (!Array.isArray(scopes))
7
+ return ['*'];
8
+ const normalized = scopes
9
+ .map((scope) => String(scope).trim().toLowerCase())
10
+ .filter(Boolean);
11
+ return normalized.length > 0 ? normalized : ['*'];
12
+ }
13
+ function hasScope(grantedScopes, requiredScope) {
14
+ const required = requiredScope.toLowerCase();
15
+ if (grantedScopes.includes('*'))
16
+ return true;
17
+ if (grantedScopes.includes(required))
18
+ return true;
19
+ for (const granted of grantedScopes) {
20
+ if (!granted.endsWith(':*'))
21
+ continue;
22
+ const prefix = granted.slice(0, -1); // keep trailing ":"
23
+ if (required.startsWith(prefix))
24
+ return true;
25
+ }
26
+ return false;
27
+ }
28
+ function requireAnyScope(requiredScopes) {
29
+ const required = requiredScopes.map((scope) => scope.trim().toLowerCase()).filter(Boolean);
30
+ return (req, res, next) => {
31
+ const auth = req.irantiAuth;
32
+ if (!auth) {
33
+ res.status(401).json({ error: 'Unauthorized. Authentication is required.' });
34
+ return;
35
+ }
36
+ const granted = normalizeScopes(auth.scopes);
37
+ const allowed = required.length === 0 || required.some((scope) => hasScope(granted, scope));
38
+ if (!allowed) {
39
+ res.status(403).json({
40
+ error: `Forbidden. Missing required scope. Need one of: ${required.join(', ')}`,
41
+ });
42
+ return;
43
+ }
44
+ next();
45
+ };
46
+ }
47
+ function requireScopeByMethod(readScope, writeScope) {
48
+ return (req, res, next) => {
49
+ const isRead = req.method === 'GET' || req.method === 'HEAD' || req.method === 'OPTIONS';
50
+ const middleware = requireAnyScope([isRead ? readScope : writeScope]);
51
+ middleware(req, res, next);
52
+ };
53
+ }
54
+ //# sourceMappingURL=authorization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../../../src/api/middleware/authorization.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Rate Limiting Middleware
3
+ * Prevents API abuse by limiting requests per identity.
4
+ * Uses authenticated keyId when available, otherwise request IP.
5
+ */
6
+ import { NextFunction, Request, Response } from 'express';
7
+ declare class RateLimiter {
8
+ private limits;
9
+ private readonly windowMs;
10
+ private readonly maxRequests;
11
+ constructor(windowMs?: number, maxRequests?: number);
12
+ check(apiKey: string): {
13
+ allowed: boolean;
14
+ remaining: number;
15
+ resetAt: number;
16
+ };
17
+ private cleanup;
18
+ get limit(): number;
19
+ }
20
+ export declare const rateLimiter: RateLimiter;
21
+ export declare function rateLimitMiddleware(req: Request, res: Response, next: NextFunction): Response<any, Record<string, any>> | undefined;
22
+ export {};
23
+ //# sourceMappingURL=rateLimit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.d.ts","sourceRoot":"","sources":["../../../../src/api/middleware/rateLimit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAO1D,cAAM,WAAW;IACf,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,QAAQ,GAAE,MAAc,EAAE,WAAW,GAAE,MAAY;IAQ/D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAsB/E,OAAO,CAAC,OAAO;IASf,IAAI,KAAK,IAAI,MAAM,CAElB;CACF;AAGD,eAAO,MAAM,WAAW,aAGvB,CAAC;AAaF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,kDAkBlF"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rateLimiter = void 0;
4
+ exports.rateLimitMiddleware = rateLimitMiddleware;
5
+ class RateLimiter {
6
+ constructor(windowMs = 60000, maxRequests = 100) {
7
+ this.limits = new Map();
8
+ this.windowMs = windowMs;
9
+ this.maxRequests = maxRequests;
10
+ // Cleanup old entries every minute
11
+ setInterval(() => this.cleanup(), 60000);
12
+ }
13
+ check(apiKey) {
14
+ const now = Date.now();
15
+ const entry = this.limits.get(apiKey);
16
+ if (!entry || now > entry.resetAt) {
17
+ // New window
18
+ const resetAt = now + this.windowMs;
19
+ this.limits.set(apiKey, { count: 1, resetAt });
20
+ return { allowed: true, remaining: this.maxRequests - 1, resetAt };
21
+ }
22
+ if (entry.count >= this.maxRequests) {
23
+ // Rate limit exceeded
24
+ return { allowed: false, remaining: 0, resetAt: entry.resetAt };
25
+ }
26
+ // Increment count
27
+ entry.count++;
28
+ this.limits.set(apiKey, entry);
29
+ return { allowed: true, remaining: this.maxRequests - entry.count, resetAt: entry.resetAt };
30
+ }
31
+ cleanup() {
32
+ const now = Date.now();
33
+ for (const [key, entry] of this.limits.entries()) {
34
+ if (now > entry.resetAt) {
35
+ this.limits.delete(key);
36
+ }
37
+ }
38
+ }
39
+ get limit() {
40
+ return this.maxRequests;
41
+ }
42
+ }
43
+ // Export singleton instance
44
+ exports.rateLimiter = new RateLimiter(parseInt(process.env.RATE_LIMIT_WINDOW_MS || '60000'), parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100'));
45
+ function getRequestIdentity(req) {
46
+ const auth = req.irantiAuth;
47
+ if (auth?.keyId) {
48
+ return `key:${String(auth.keyId).toLowerCase()}`;
49
+ }
50
+ const ip = req.ip || req.socket?.remoteAddress || 'unknown';
51
+ return `ip:${ip}`;
52
+ }
53
+ // Express middleware
54
+ function rateLimitMiddleware(req, res, next) {
55
+ const identity = getRequestIdentity(req);
56
+ const result = exports.rateLimiter.check(identity);
57
+ // Add rate limit headers
58
+ res.setHeader('X-RateLimit-Limit', exports.rateLimiter.limit);
59
+ res.setHeader('X-RateLimit-Remaining', result.remaining);
60
+ res.setHeader('X-RateLimit-Reset', new Date(result.resetAt).toISOString());
61
+ if (!result.allowed) {
62
+ return res.status(429).json({
63
+ error: 'Rate limit exceeded',
64
+ code: 'RATE_LIMIT_EXCEEDED',
65
+ retryAfter: Math.ceil((result.resetAt - Date.now()) / 1000)
66
+ });
67
+ }
68
+ next();
69
+ }
70
+ //# sourceMappingURL=rateLimit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../../../src/api/middleware/rateLimit.ts"],"names":[],"mappings":"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"}