javi-forge 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 (500) hide show
  1. package/.gitignore.template +105 -0
  2. package/.releaserc +44 -0
  3. package/README.md +45 -0
  4. package/ai-config/.skillignore +15 -0
  5. package/ai-config/AUTO_INVOKE.md +300 -0
  6. package/ai-config/agents/_TEMPLATE.md +93 -0
  7. package/ai-config/agents/business/api-designer.md +1657 -0
  8. package/ai-config/agents/business/business-analyst.md +1331 -0
  9. package/ai-config/agents/business/product-strategist.md +206 -0
  10. package/ai-config/agents/business/project-manager.md +178 -0
  11. package/ai-config/agents/business/requirements-analyst.md +1277 -0
  12. package/ai-config/agents/business/technical-writer.md +1679 -0
  13. package/ai-config/agents/creative/ux-designer.md +205 -0
  14. package/ai-config/agents/data-ai/ai-engineer.md +487 -0
  15. package/ai-config/agents/data-ai/analytics-engineer.md +953 -0
  16. package/ai-config/agents/data-ai/data-engineer.md +173 -0
  17. package/ai-config/agents/data-ai/data-scientist.md +672 -0
  18. package/ai-config/agents/data-ai/mlops-engineer.md +814 -0
  19. package/ai-config/agents/data-ai/prompt-engineer.md +772 -0
  20. package/ai-config/agents/development/angular-expert.md +620 -0
  21. package/ai-config/agents/development/backend-architect.md +795 -0
  22. package/ai-config/agents/development/database-specialist.md +212 -0
  23. package/ai-config/agents/development/frontend-specialist.md +686 -0
  24. package/ai-config/agents/development/fullstack-engineer.md +668 -0
  25. package/ai-config/agents/development/golang-pro.md +338 -0
  26. package/ai-config/agents/development/java-enterprise.md +400 -0
  27. package/ai-config/agents/development/javascript-pro.md +422 -0
  28. package/ai-config/agents/development/nextjs-pro.md +474 -0
  29. package/ai-config/agents/development/python-pro.md +570 -0
  30. package/ai-config/agents/development/react-pro.md +487 -0
  31. package/ai-config/agents/development/rust-pro.md +246 -0
  32. package/ai-config/agents/development/spring-boot-4-expert.md +326 -0
  33. package/ai-config/agents/development/typescript-pro.md +336 -0
  34. package/ai-config/agents/development/vue-specialist.md +605 -0
  35. package/ai-config/agents/infrastructure/cloud-architect.md +472 -0
  36. package/ai-config/agents/infrastructure/deployment-manager.md +358 -0
  37. package/ai-config/agents/infrastructure/devops-engineer.md +455 -0
  38. package/ai-config/agents/infrastructure/incident-responder.md +519 -0
  39. package/ai-config/agents/infrastructure/kubernetes-expert.md +705 -0
  40. package/ai-config/agents/infrastructure/monitoring-specialist.md +674 -0
  41. package/ai-config/agents/infrastructure/performance-engineer.md +658 -0
  42. package/ai-config/agents/orchestrator.md +241 -0
  43. package/ai-config/agents/quality/accessibility-auditor.md +1204 -0
  44. package/ai-config/agents/quality/code-reviewer-compact.md +123 -0
  45. package/ai-config/agents/quality/code-reviewer.md +363 -0
  46. package/ai-config/agents/quality/dependency-manager.md +743 -0
  47. package/ai-config/agents/quality/e2e-test-specialist.md +1005 -0
  48. package/ai-config/agents/quality/performance-tester.md +1086 -0
  49. package/ai-config/agents/quality/security-auditor.md +133 -0
  50. package/ai-config/agents/quality/test-engineer.md +453 -0
  51. package/ai-config/agents/specialists/api-designer.md +87 -0
  52. package/ai-config/agents/specialists/backend-architect.md +73 -0
  53. package/ai-config/agents/specialists/code-reviewer.md +77 -0
  54. package/ai-config/agents/specialists/db-optimizer.md +75 -0
  55. package/ai-config/agents/specialists/devops-engineer.md +83 -0
  56. package/ai-config/agents/specialists/documentation-writer.md +78 -0
  57. package/ai-config/agents/specialists/frontend-developer.md +75 -0
  58. package/ai-config/agents/specialists/performance-analyst.md +82 -0
  59. package/ai-config/agents/specialists/refactor-specialist.md +74 -0
  60. package/ai-config/agents/specialists/security-auditor.md +74 -0
  61. package/ai-config/agents/specialists/test-engineer.md +81 -0
  62. package/ai-config/agents/specialists/ux-consultant.md +76 -0
  63. package/ai-config/agents/specialized/agent-generator.md +1190 -0
  64. package/ai-config/agents/specialized/blockchain-developer.md +149 -0
  65. package/ai-config/agents/specialized/code-migrator.md +892 -0
  66. package/ai-config/agents/specialized/context-manager.md +978 -0
  67. package/ai-config/agents/specialized/documentation-writer.md +1078 -0
  68. package/ai-config/agents/specialized/ecommerce-expert.md +1756 -0
  69. package/ai-config/agents/specialized/embedded-engineer.md +1714 -0
  70. package/ai-config/agents/specialized/error-detective.md +1034 -0
  71. package/ai-config/agents/specialized/fintech-specialist.md +1659 -0
  72. package/ai-config/agents/specialized/freelance-project-planner-v2.md +1988 -0
  73. package/ai-config/agents/specialized/freelance-project-planner-v3.md +2136 -0
  74. package/ai-config/agents/specialized/freelance-project-planner-v4.md +4503 -0
  75. package/ai-config/agents/specialized/freelance-project-planner.md +722 -0
  76. package/ai-config/agents/specialized/game-developer.md +1963 -0
  77. package/ai-config/agents/specialized/healthcare-dev.md +1620 -0
  78. package/ai-config/agents/specialized/mobile-developer.md +188 -0
  79. package/ai-config/agents/specialized/parallel-plan-executor.md +506 -0
  80. package/ai-config/agents/specialized/plan-executor.md +485 -0
  81. package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +485 -0
  82. package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +3493 -0
  83. package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +778 -0
  84. package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +918 -0
  85. package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +1537 -0
  86. package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +2633 -0
  87. package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +5610 -0
  88. package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +335 -0
  89. package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +215 -0
  90. package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +260 -0
  91. package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +379 -0
  92. package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +355 -0
  93. package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +279 -0
  94. package/ai-config/agents/specialized/template-writer.md +347 -0
  95. package/ai-config/agents/specialized/test-runner.md +99 -0
  96. package/ai-config/agents/specialized/vibekanban-smart-worker.md +244 -0
  97. package/ai-config/agents/specialized/wave-executor.md +138 -0
  98. package/ai-config/agents/specialized/workflow-optimizer.md +1114 -0
  99. package/ai-config/commands/git/changelog.md +32 -0
  100. package/ai-config/commands/git/ci-local.md +70 -0
  101. package/ai-config/commands/git/commit.md +35 -0
  102. package/ai-config/commands/git/fix-issue.md +23 -0
  103. package/ai-config/commands/git/pr-create.md +42 -0
  104. package/ai-config/commands/git/pr-review.md +50 -0
  105. package/ai-config/commands/git/worktree.md +39 -0
  106. package/ai-config/commands/refactoring/cleanup.md +24 -0
  107. package/ai-config/commands/refactoring/dead-code.md +40 -0
  108. package/ai-config/commands/refactoring/extract.md +31 -0
  109. package/ai-config/commands/testing/e2e.md +30 -0
  110. package/ai-config/commands/testing/tdd.md +36 -0
  111. package/ai-config/commands/testing/test-coverage.md +30 -0
  112. package/ai-config/commands/testing/test-fix.md +24 -0
  113. package/ai-config/commands/workflow/generate-agents-md.md +85 -0
  114. package/ai-config/commands/workflow/planning.md +47 -0
  115. package/ai-config/commands/workflows/compound.md +89 -0
  116. package/ai-config/commands/workflows/plan.md +77 -0
  117. package/ai-config/commands/workflows/review.md +78 -0
  118. package/ai-config/commands/workflows/work.md +75 -0
  119. package/ai-config/config.yaml +18 -0
  120. package/ai-config/hooks/_TEMPLATE.md +96 -0
  121. package/ai-config/hooks/block-dangerous-commands.md +75 -0
  122. package/ai-config/hooks/commit-guard.md +90 -0
  123. package/ai-config/hooks/context-loader.md +73 -0
  124. package/ai-config/hooks/improve-prompt.md +91 -0
  125. package/ai-config/hooks/learning-log.md +72 -0
  126. package/ai-config/hooks/model-router.md +86 -0
  127. package/ai-config/hooks/secret-scanner.md +64 -0
  128. package/ai-config/hooks/skill-validator.md +102 -0
  129. package/ai-config/hooks/task-artifact.md +114 -0
  130. package/ai-config/hooks/validate-workflow.md +100 -0
  131. package/ai-config/prompts/base.md +71 -0
  132. package/ai-config/prompts/modes/debug.md +34 -0
  133. package/ai-config/prompts/modes/deploy.md +40 -0
  134. package/ai-config/prompts/modes/research.md +32 -0
  135. package/ai-config/prompts/modes/review.md +33 -0
  136. package/ai-config/prompts/review-policy.md +79 -0
  137. package/ai-config/skills/_TEMPLATE.md +157 -0
  138. package/ai-config/skills/backend/api-gateway/SKILL.md +254 -0
  139. package/ai-config/skills/backend/bff-concepts/SKILL.md +239 -0
  140. package/ai-config/skills/backend/bff-spring/SKILL.md +364 -0
  141. package/ai-config/skills/backend/chi-router/SKILL.md +396 -0
  142. package/ai-config/skills/backend/error-handling/SKILL.md +255 -0
  143. package/ai-config/skills/backend/exceptions-spring/SKILL.md +323 -0
  144. package/ai-config/skills/backend/fastapi/SKILL.md +302 -0
  145. package/ai-config/skills/backend/gateway-spring/SKILL.md +390 -0
  146. package/ai-config/skills/backend/go-backend/SKILL.md +457 -0
  147. package/ai-config/skills/backend/gradle-multimodule/SKILL.md +274 -0
  148. package/ai-config/skills/backend/graphql-concepts/SKILL.md +352 -0
  149. package/ai-config/skills/backend/graphql-spring/SKILL.md +398 -0
  150. package/ai-config/skills/backend/grpc-concepts/SKILL.md +283 -0
  151. package/ai-config/skills/backend/grpc-spring/SKILL.md +445 -0
  152. package/ai-config/skills/backend/jwt-auth/SKILL.md +412 -0
  153. package/ai-config/skills/backend/notifications-concepts/SKILL.md +259 -0
  154. package/ai-config/skills/backend/recommendations-concepts/SKILL.md +261 -0
  155. package/ai-config/skills/backend/search-concepts/SKILL.md +263 -0
  156. package/ai-config/skills/backend/search-spring/SKILL.md +375 -0
  157. package/ai-config/skills/backend/spring-boot-4/SKILL.md +172 -0
  158. package/ai-config/skills/backend/websockets/SKILL.md +532 -0
  159. package/ai-config/skills/data-ai/ai-ml/SKILL.md +423 -0
  160. package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +195 -0
  161. package/ai-config/skills/data-ai/analytics-spring/SKILL.md +340 -0
  162. package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +440 -0
  163. package/ai-config/skills/data-ai/langchain/SKILL.md +238 -0
  164. package/ai-config/skills/data-ai/mlflow/SKILL.md +302 -0
  165. package/ai-config/skills/data-ai/onnx-inference/SKILL.md +290 -0
  166. package/ai-config/skills/data-ai/powerbi/SKILL.md +352 -0
  167. package/ai-config/skills/data-ai/pytorch/SKILL.md +274 -0
  168. package/ai-config/skills/data-ai/scikit-learn/SKILL.md +321 -0
  169. package/ai-config/skills/data-ai/vector-db/SKILL.md +301 -0
  170. package/ai-config/skills/database/graph-databases/SKILL.md +218 -0
  171. package/ai-config/skills/database/graph-spring/SKILL.md +361 -0
  172. package/ai-config/skills/database/pgx-postgres/SKILL.md +512 -0
  173. package/ai-config/skills/database/redis-cache/SKILL.md +343 -0
  174. package/ai-config/skills/database/sqlite-embedded/SKILL.md +388 -0
  175. package/ai-config/skills/database/timescaledb/SKILL.md +320 -0
  176. package/ai-config/skills/docs/api-documentation/SKILL.md +293 -0
  177. package/ai-config/skills/docs/docs-spring/SKILL.md +377 -0
  178. package/ai-config/skills/docs/mustache-templates/SKILL.md +190 -0
  179. package/ai-config/skills/docs/technical-docs/SKILL.md +447 -0
  180. package/ai-config/skills/frontend/astro-ssr/SKILL.md +441 -0
  181. package/ai-config/skills/frontend/frontend-design/SKILL.md +54 -0
  182. package/ai-config/skills/frontend/frontend-web/SKILL.md +368 -0
  183. package/ai-config/skills/frontend/mantine-ui/SKILL.md +396 -0
  184. package/ai-config/skills/frontend/tanstack-query/SKILL.md +439 -0
  185. package/ai-config/skills/frontend/zod-validation/SKILL.md +417 -0
  186. package/ai-config/skills/frontend/zustand-state/SKILL.md +350 -0
  187. package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +244 -0
  188. package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +378 -0
  189. package/ai-config/skills/infrastructure/devops-infra/SKILL.md +435 -0
  190. package/ai-config/skills/infrastructure/docker-containers/SKILL.md +420 -0
  191. package/ai-config/skills/infrastructure/kubernetes/SKILL.md +456 -0
  192. package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +546 -0
  193. package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +474 -0
  194. package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +315 -0
  195. package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +504 -0
  196. package/ai-config/skills/mobile/mobile-ionic/SKILL.md +448 -0
  197. package/ai-config/skills/prompt-improver/SKILL.md +125 -0
  198. package/ai-config/skills/quality/ghagga-review/SKILL.md +216 -0
  199. package/ai-config/skills/references/hooks-patterns/SKILL.md +238 -0
  200. package/ai-config/skills/references/mcp-servers/SKILL.md +275 -0
  201. package/ai-config/skills/references/plugins-reference/SKILL.md +110 -0
  202. package/ai-config/skills/references/skills-reference/SKILL.md +420 -0
  203. package/ai-config/skills/references/subagent-templates/SKILL.md +193 -0
  204. package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +410 -0
  205. package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +408 -0
  206. package/ai-config/skills/systems-iot/rust-systems/SKILL.md +386 -0
  207. package/ai-config/skills/systems-iot/tokio-async/SKILL.md +324 -0
  208. package/ai-config/skills/testing/playwright-e2e/SKILL.md +289 -0
  209. package/ai-config/skills/testing/testcontainers/SKILL.md +299 -0
  210. package/ai-config/skills/testing/vitest-testing/SKILL.md +381 -0
  211. package/ai-config/skills/workflow/ci-local-guide/SKILL.md +118 -0
  212. package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +299 -0
  213. package/ai-config/skills/workflow/claude-md-improver/SKILL.md +158 -0
  214. package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +117 -0
  215. package/ai-config/skills/workflow/git-github/SKILL.md +334 -0
  216. package/ai-config/skills/workflow/git-github/references/examples.md +160 -0
  217. package/ai-config/skills/workflow/git-workflow/SKILL.md +214 -0
  218. package/ai-config/skills/workflow/ide-plugins/SKILL.md +277 -0
  219. package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +401 -0
  220. package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +199 -0
  221. package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +100 -0
  222. package/ai-config/skills/workflow/verification-before-completion/SKILL.md +73 -0
  223. package/ai-config/skills/workflow/wave-workflow/SKILL.md +178 -0
  224. package/ci-local/README.md +170 -0
  225. package/ci-local/ci-local.sh +297 -0
  226. package/ci-local/hooks/commit-msg +74 -0
  227. package/ci-local/hooks/pre-commit +162 -0
  228. package/ci-local/hooks/pre-push +41 -0
  229. package/ci-local/install.sh +49 -0
  230. package/ci-local/semgrep.yml +214 -0
  231. package/dist/commands/analyze.d.ts +9 -0
  232. package/dist/commands/analyze.d.ts.map +1 -0
  233. package/dist/commands/analyze.js +55 -0
  234. package/dist/commands/analyze.js.map +1 -0
  235. package/dist/commands/analyze.test.d.ts +2 -0
  236. package/dist/commands/analyze.test.d.ts.map +1 -0
  237. package/dist/commands/analyze.test.js +145 -0
  238. package/dist/commands/analyze.test.js.map +1 -0
  239. package/dist/commands/doctor.d.ts +7 -0
  240. package/dist/commands/doctor.d.ts.map +1 -0
  241. package/dist/commands/doctor.js +158 -0
  242. package/dist/commands/doctor.js.map +1 -0
  243. package/dist/commands/doctor.test.d.ts +2 -0
  244. package/dist/commands/doctor.test.d.ts.map +1 -0
  245. package/dist/commands/doctor.test.js +200 -0
  246. package/dist/commands/doctor.test.js.map +1 -0
  247. package/dist/commands/init.d.ts +9 -0
  248. package/dist/commands/init.d.ts.map +1 -0
  249. package/dist/commands/init.js +283 -0
  250. package/dist/commands/init.js.map +1 -0
  251. package/dist/commands/init.test.d.ts +2 -0
  252. package/dist/commands/init.test.d.ts.map +1 -0
  253. package/dist/commands/init.test.js +271 -0
  254. package/dist/commands/init.test.js.map +1 -0
  255. package/dist/commands/sync.d.ts +8 -0
  256. package/dist/commands/sync.d.ts.map +1 -0
  257. package/dist/commands/sync.js +201 -0
  258. package/dist/commands/sync.js.map +1 -0
  259. package/dist/constants.d.ts +21 -0
  260. package/dist/constants.d.ts.map +1 -0
  261. package/dist/constants.js +57 -0
  262. package/dist/constants.js.map +1 -0
  263. package/dist/e2e/aggressive.e2e.test.d.ts +2 -0
  264. package/dist/e2e/aggressive.e2e.test.d.ts.map +1 -0
  265. package/dist/e2e/aggressive.e2e.test.js +350 -0
  266. package/dist/e2e/aggressive.e2e.test.js.map +1 -0
  267. package/dist/e2e/commands.e2e.test.d.ts +2 -0
  268. package/dist/e2e/commands.e2e.test.d.ts.map +1 -0
  269. package/dist/e2e/commands.e2e.test.js +213 -0
  270. package/dist/e2e/commands.e2e.test.js.map +1 -0
  271. package/dist/index.d.ts +3 -0
  272. package/dist/index.d.ts.map +1 -0
  273. package/dist/index.js +82 -0
  274. package/dist/index.js.map +1 -0
  275. package/dist/lib/common.d.ts +17 -0
  276. package/dist/lib/common.d.ts.map +1 -0
  277. package/dist/lib/common.js +111 -0
  278. package/dist/lib/common.js.map +1 -0
  279. package/dist/lib/common.test.d.ts +2 -0
  280. package/dist/lib/common.test.d.ts.map +1 -0
  281. package/dist/lib/common.test.js +316 -0
  282. package/dist/lib/common.test.js.map +1 -0
  283. package/dist/lib/frontmatter.d.ts +18 -0
  284. package/dist/lib/frontmatter.d.ts.map +1 -0
  285. package/dist/lib/frontmatter.js +61 -0
  286. package/dist/lib/frontmatter.js.map +1 -0
  287. package/dist/lib/frontmatter.test.d.ts +2 -0
  288. package/dist/lib/frontmatter.test.d.ts.map +1 -0
  289. package/dist/lib/frontmatter.test.js +257 -0
  290. package/dist/lib/frontmatter.test.js.map +1 -0
  291. package/dist/lib/template.d.ts +24 -0
  292. package/dist/lib/template.d.ts.map +1 -0
  293. package/dist/lib/template.js +78 -0
  294. package/dist/lib/template.js.map +1 -0
  295. package/dist/lib/template.test.d.ts +2 -0
  296. package/dist/lib/template.test.d.ts.map +1 -0
  297. package/dist/lib/template.test.js +201 -0
  298. package/dist/lib/template.test.js.map +1 -0
  299. package/dist/types/index.d.ts +48 -0
  300. package/dist/types/index.d.ts.map +1 -0
  301. package/dist/types/index.js +2 -0
  302. package/dist/types/index.js.map +1 -0
  303. package/dist/ui/AnalyzeUI.d.ts +7 -0
  304. package/dist/ui/AnalyzeUI.d.ts.map +1 -0
  305. package/dist/ui/AnalyzeUI.js +100 -0
  306. package/dist/ui/AnalyzeUI.js.map +1 -0
  307. package/dist/ui/App.d.ts +13 -0
  308. package/dist/ui/App.d.ts.map +1 -0
  309. package/dist/ui/App.js +100 -0
  310. package/dist/ui/App.js.map +1 -0
  311. package/dist/ui/CIContext.d.ts +9 -0
  312. package/dist/ui/CIContext.d.ts.map +1 -0
  313. package/dist/ui/CIContext.js +9 -0
  314. package/dist/ui/CIContext.js.map +1 -0
  315. package/dist/ui/CISelector.d.ts +8 -0
  316. package/dist/ui/CISelector.d.ts.map +1 -0
  317. package/dist/ui/CISelector.js +45 -0
  318. package/dist/ui/CISelector.js.map +1 -0
  319. package/dist/ui/Doctor.d.ts +3 -0
  320. package/dist/ui/Doctor.d.ts.map +1 -0
  321. package/dist/ui/Doctor.js +89 -0
  322. package/dist/ui/Doctor.js.map +1 -0
  323. package/dist/ui/Header.d.ts +8 -0
  324. package/dist/ui/Header.d.ts.map +1 -0
  325. package/dist/ui/Header.js +30 -0
  326. package/dist/ui/Header.js.map +1 -0
  327. package/dist/ui/MemorySelector.d.ts +8 -0
  328. package/dist/ui/MemorySelector.d.ts.map +1 -0
  329. package/dist/ui/MemorySelector.js +46 -0
  330. package/dist/ui/MemorySelector.js.map +1 -0
  331. package/dist/ui/NameInput.d.ts +8 -0
  332. package/dist/ui/NameInput.d.ts.map +1 -0
  333. package/dist/ui/NameInput.js +69 -0
  334. package/dist/ui/NameInput.js.map +1 -0
  335. package/dist/ui/OptionSelector.d.ts +12 -0
  336. package/dist/ui/OptionSelector.d.ts.map +1 -0
  337. package/dist/ui/OptionSelector.js +69 -0
  338. package/dist/ui/OptionSelector.js.map +1 -0
  339. package/dist/ui/Progress.d.ts +11 -0
  340. package/dist/ui/Progress.d.ts.map +1 -0
  341. package/dist/ui/Progress.js +58 -0
  342. package/dist/ui/Progress.js.map +1 -0
  343. package/dist/ui/StackSelector.d.ts +9 -0
  344. package/dist/ui/StackSelector.d.ts.map +1 -0
  345. package/dist/ui/StackSelector.js +65 -0
  346. package/dist/ui/StackSelector.js.map +1 -0
  347. package/dist/ui/Summary.d.ts +12 -0
  348. package/dist/ui/Summary.d.ts.map +1 -0
  349. package/dist/ui/Summary.js +114 -0
  350. package/dist/ui/Summary.js.map +1 -0
  351. package/dist/ui/SyncUI.d.ts +10 -0
  352. package/dist/ui/SyncUI.d.ts.map +1 -0
  353. package/dist/ui/SyncUI.js +64 -0
  354. package/dist/ui/SyncUI.js.map +1 -0
  355. package/dist/ui/Welcome.d.ts +7 -0
  356. package/dist/ui/Welcome.d.ts.map +1 -0
  357. package/dist/ui/Welcome.js +45 -0
  358. package/dist/ui/Welcome.js.map +1 -0
  359. package/dist/ui/theme.d.ts +10 -0
  360. package/dist/ui/theme.d.ts.map +1 -0
  361. package/dist/ui/theme.js +9 -0
  362. package/dist/ui/theme.js.map +1 -0
  363. package/modules/engram/.gitignore-snippet.txt +6 -0
  364. package/modules/engram/.mcp-config-snippet.json +11 -0
  365. package/modules/engram/README.md +146 -0
  366. package/modules/engram/install-engram.sh +216 -0
  367. package/modules/ghagga/.env.example +43 -0
  368. package/modules/ghagga/README.md +153 -0
  369. package/modules/ghagga/docker-compose.yml +80 -0
  370. package/modules/ghagga/setup-ghagga.sh +139 -0
  371. package/modules/memory-simple/.project/NOTES.md +22 -0
  372. package/modules/memory-simple/README.md +23 -0
  373. package/modules/obsidian-brain/.obsidian/app.json +23 -0
  374. package/modules/obsidian-brain/.obsidian/appearance.json +5 -0
  375. package/modules/obsidian-brain/.obsidian/bookmarks.json +34 -0
  376. package/modules/obsidian-brain/.obsidian/community-plugins.json +1 -0
  377. package/modules/obsidian-brain/.obsidian/core-plugins-migration.json +21 -0
  378. package/modules/obsidian-brain/.obsidian/core-plugins.json +18 -0
  379. package/modules/obsidian-brain/.obsidian/daily-notes.json +5 -0
  380. package/modules/obsidian-brain/.obsidian/graph.json +37 -0
  381. package/modules/obsidian-brain/.obsidian/hotkeys.json +14 -0
  382. package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +25 -0
  383. package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +29 -0
  384. package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +18 -0
  385. package/modules/obsidian-brain/.obsidian/snippets/project-memory.css +71 -0
  386. package/modules/obsidian-brain/.obsidian-gitignore-snippet.txt +8 -0
  387. package/modules/obsidian-brain/.project/Attachments/.gitkeep +0 -0
  388. package/modules/obsidian-brain/.project/Memory/BLOCKERS.md +78 -0
  389. package/modules/obsidian-brain/.project/Memory/CONTEXT.md +102 -0
  390. package/modules/obsidian-brain/.project/Memory/DASHBOARD.md +73 -0
  391. package/modules/obsidian-brain/.project/Memory/DECISIONS.md +87 -0
  392. package/modules/obsidian-brain/.project/Memory/KANBAN.md +15 -0
  393. package/modules/obsidian-brain/.project/Memory/README.md +61 -0
  394. package/modules/obsidian-brain/.project/Memory/WAVES.md +78 -0
  395. package/modules/obsidian-brain/.project/Sessions/TEMPLATE.md +99 -0
  396. package/modules/obsidian-brain/.project/Templates/ADR.md +33 -0
  397. package/modules/obsidian-brain/.project/Templates/Blocker.md +21 -0
  398. package/modules/obsidian-brain/.project/Templates/Session.md +88 -0
  399. package/modules/obsidian-brain/README.md +268 -0
  400. package/modules/obsidian-brain/new-wave.sh +182 -0
  401. package/package.json +51 -0
  402. package/schemas/agent.schema.json +34 -0
  403. package/schemas/ai-config.schema.json +28 -0
  404. package/schemas/skill.schema.json +44 -0
  405. package/src/commands/analyze.test.ts +145 -0
  406. package/src/commands/analyze.ts +69 -0
  407. package/src/commands/doctor.test.ts +208 -0
  408. package/src/commands/doctor.ts +163 -0
  409. package/src/commands/init.test.ts +298 -0
  410. package/src/commands/init.ts +285 -0
  411. package/src/constants.ts +69 -0
  412. package/src/e2e/aggressive.e2e.test.ts +557 -0
  413. package/src/e2e/commands.e2e.test.ts +298 -0
  414. package/src/index.tsx +106 -0
  415. package/src/lib/common.test.ts +318 -0
  416. package/src/lib/common.ts +127 -0
  417. package/src/lib/frontmatter.test.ts +291 -0
  418. package/src/lib/frontmatter.ts +77 -0
  419. package/src/lib/template.test.ts +226 -0
  420. package/src/lib/template.ts +99 -0
  421. package/src/types/index.ts +53 -0
  422. package/src/ui/AnalyzeUI.tsx +133 -0
  423. package/src/ui/App.tsx +175 -0
  424. package/src/ui/CIContext.tsx +25 -0
  425. package/src/ui/CISelector.tsx +72 -0
  426. package/src/ui/Doctor.tsx +122 -0
  427. package/src/ui/Header.tsx +48 -0
  428. package/src/ui/MemorySelector.tsx +73 -0
  429. package/src/ui/NameInput.tsx +82 -0
  430. package/src/ui/OptionSelector.tsx +100 -0
  431. package/src/ui/Progress.tsx +88 -0
  432. package/src/ui/StackSelector.tsx +101 -0
  433. package/src/ui/Summary.tsx +134 -0
  434. package/src/ui/Welcome.tsx +54 -0
  435. package/src/ui/theme.ts +10 -0
  436. package/stryker.config.json +19 -0
  437. package/tasks/_TEMPLATE/files-edited.md +3 -0
  438. package/tasks/_TEMPLATE/plan.md +3 -0
  439. package/tasks/_TEMPLATE/research.md +3 -0
  440. package/tasks/_TEMPLATE/verification.md +5 -0
  441. package/templates/common/dependabot/cargo.yml +11 -0
  442. package/templates/common/dependabot/github-actions.yml +16 -0
  443. package/templates/common/dependabot/gomod.yml +15 -0
  444. package/templates/common/dependabot/gradle.yml +15 -0
  445. package/templates/common/dependabot/header.yml +3 -0
  446. package/templates/common/dependabot/maven.yml +15 -0
  447. package/templates/common/dependabot/npm.yml +20 -0
  448. package/templates/common/dependabot/pip.yml +11 -0
  449. package/templates/dependabot.yml +162 -0
  450. package/templates/github/ci-go.yml +41 -0
  451. package/templates/github/ci-java.yml +45 -0
  452. package/templates/github/ci-monorepo.yml +150 -0
  453. package/templates/github/ci-node.yml +42 -0
  454. package/templates/github/ci-python.yml +42 -0
  455. package/templates/github/ci-rust.yml +42 -0
  456. package/templates/github/dependabot-automerge.yml +40 -0
  457. package/templates/gitlab/gitlab-ci-go.yml +88 -0
  458. package/templates/gitlab/gitlab-ci-java.yml +79 -0
  459. package/templates/gitlab/gitlab-ci-monorepo.yml +126 -0
  460. package/templates/gitlab/gitlab-ci-node.yml +63 -0
  461. package/templates/gitlab/gitlab-ci-python.yml +147 -0
  462. package/templates/gitlab/gitlab-ci-rust.yml +67 -0
  463. package/templates/global/claude-settings.json +98 -0
  464. package/templates/global/codex-config.toml +8 -0
  465. package/templates/global/copilot-instructions/base-rules.instructions.md +13 -0
  466. package/templates/global/copilot-instructions/sdd-orchestrator.instructions.md +37 -0
  467. package/templates/global/gemini-commands/cleanup.toml +20 -0
  468. package/templates/global/gemini-commands/commit.toml +15 -0
  469. package/templates/global/gemini-commands/dead-code.toml +22 -0
  470. package/templates/global/gemini-commands/plan.toml +30 -0
  471. package/templates/global/gemini-commands/review.toml +17 -0
  472. package/templates/global/gemini-commands/sdd-apply.toml +22 -0
  473. package/templates/global/gemini-commands/sdd-ff.toml +14 -0
  474. package/templates/global/gemini-commands/sdd-new.toml +21 -0
  475. package/templates/global/gemini-commands/sdd-verify.toml +21 -0
  476. package/templates/global/gemini-commands/tdd.toml +26 -0
  477. package/templates/global/gemini-settings.json +8 -0
  478. package/templates/global/opencode-config.json +44 -0
  479. package/templates/global/sdd-instructions.md +47 -0
  480. package/templates/global/sdd-orchestrator-claude.md +46 -0
  481. package/templates/global/sdd-orchestrator-copilot.md +34 -0
  482. package/templates/renovate.json +69 -0
  483. package/templates/woodpecker/monorepo/backend.yml +34 -0
  484. package/templates/woodpecker/monorepo/frontend.yml +34 -0
  485. package/templates/woodpecker/monorepo/summary.yml +25 -0
  486. package/templates/woodpecker/woodpecker-go.yml +51 -0
  487. package/templates/woodpecker/woodpecker-java.yml +67 -0
  488. package/templates/woodpecker/woodpecker-node.yml +47 -0
  489. package/templates/woodpecker/woodpecker-python.yml +108 -0
  490. package/templates/woodpecker/woodpecker-rust.yml +57 -0
  491. package/tsconfig.json +19 -0
  492. package/vitest.config.ts +16 -0
  493. package/workflows/reusable-build-go.yml +111 -0
  494. package/workflows/reusable-build-java.yml +120 -0
  495. package/workflows/reusable-build-node.yml +145 -0
  496. package/workflows/reusable-build-python.yml +159 -0
  497. package/workflows/reusable-build-rust.yml +135 -0
  498. package/workflows/reusable-docker.yml +120 -0
  499. package/workflows/reusable-ghagga-review.yml +165 -0
  500. package/workflows/reusable-release.yml +91 -0
@@ -0,0 +1,1620 @@
1
+ ---
2
+ name: healthcare-dev
3
+ description: Healthcare technology specialist, HIPAA compliance expert, HL7/FHIR standards, medical device integration, EHR/EMR systems
4
+ trigger: >
5
+ HIPAA, HL7, FHIR, EHR, EMR, healthcare API, medical device, telemedicine,
6
+ DICOM, patient data, clinical, PHI, health records, SNOMED, ICD-10
7
+ category: specialized
8
+ tools: Task, Bash, Grep, Glob, Read, Write, MultiEdit, TodoWrite
9
+ config:
10
+ model: sonnet
11
+ metadata:
12
+ version: "2.0"
13
+ updated: "2026-02"
14
+ ---
15
+
16
+ You are a healthcare technology specialist with deep expertise in medical software development, regulatory compliance, interoperability standards, and patient data security. Your knowledge spans electronic health records (EHR), medical device integration, telemedicine platforms, and healthcare analytics while maintaining strict compliance with HIPAA, GDPR, and other healthcare regulations.
17
+
18
+ ## Core Expertise
19
+
20
+ ### 1. Healthcare Standards & Interoperability
21
+ - **HL7 Standards**: HL7 v2.x messaging, HL7 v3 RIM, CDA (Clinical Document Architecture)
22
+ - **FHIR**: Fast Healthcare Interoperability Resources R4/R5, SMART on FHIR
23
+ - **DICOM**: Medical imaging standards, PACS integration, image processing
24
+ - **IHE Profiles**: XDS, PIX, PDQ, XCA for health information exchange
25
+ - **Terminology Standards**: SNOMED CT, LOINC, ICD-10, CPT, RxNorm
26
+
27
+ ### 2. Regulatory Compliance
28
+ - **HIPAA**: Privacy Rule, Security Rule, Breach Notification, Minimum Necessary
29
+ - **FDA Regulations**: 21 CFR Part 11, Medical Device Software (SaMD), 510(k) submissions
30
+ - **GDPR**: EU data protection for health data
31
+ - **Regional Compliance**: PIPEDA (Canada), HITECH Act (US), NHS standards (UK)
32
+ - **Audit Controls**: Access logs, data integrity, electronic signatures
33
+
34
+ ### 3. EHR/EMR Systems
35
+ - **Major Platforms**: Epic, Cerner, Allscripts, athenahealth integration
36
+ - **Clinical Workflows**: CPOE, e-prescribing, clinical decision support
37
+ - **Patient Portals**: Secure messaging, appointment scheduling, lab results
38
+ - **Interoperability**: Health Information Exchanges (HIE), Care Everywhere
39
+ - **Data Migration**: Legacy system transitions, data mapping, validation
40
+
41
+ ### 4. Medical Device Integration
42
+ - **Device Protocols**: IEEE 11073, Bluetooth LE for medical devices
43
+ - **Wearables**: Continuous monitoring, remote patient monitoring (RPM)
44
+ - **Medical IoT**: Device management, firmware updates, security
45
+ - **FDA Classes**: Class I, II, III device software requirements
46
+ - **Real-time Monitoring**: Vital signs, alerts, nurse call systems
47
+
48
+ ### 5. Healthcare Analytics & AI
49
+ - **Clinical Analytics**: Population health, risk stratification, quality measures
50
+ - **Medical Imaging AI**: Computer-aided diagnosis, image segmentation
51
+ - **NLP for Healthcare**: Clinical notes extraction, medical coding automation
52
+ - **Predictive Analytics**: Readmission risk, disease progression, treatment outcomes
53
+ - **Research Platforms**: Clinical trials management, REDCap integration
54
+
55
+ ## Implementation Examples
56
+
57
+ ### FHIR-Compliant EHR System (TypeScript/Node.js)
58
+ ```typescript
59
+ import express, { Request, Response, NextFunction } from 'express';
60
+ import { v4 as uuidv4 } from 'uuid';
61
+ import crypto from 'crypto';
62
+ import jwt from 'jsonwebtoken';
63
+ import { Pool } from 'pg';
64
+ import Redis from 'ioredis';
65
+ import winston from 'winston';
66
+ import { z } from 'zod';
67
+ import hl7 from 'hl7-standard';
68
+ import dicom from 'dicom-parser';
69
+
70
+ /**
71
+ * FHIR R4 Compliant Electronic Health Record System
72
+ * HIPAA-compliant implementation with comprehensive security and audit logging
73
+ */
74
+
75
+ // FHIR Resource Types
76
+ enum ResourceType {
77
+ Patient = 'Patient',
78
+ Practitioner = 'Practitioner',
79
+ Encounter = 'Encounter',
80
+ Observation = 'Observation',
81
+ Medication = 'Medication',
82
+ MedicationRequest = 'MedicationRequest',
83
+ Condition = 'Condition',
84
+ Procedure = 'Procedure',
85
+ DiagnosticReport = 'DiagnosticReport',
86
+ AllergyIntolerance = 'AllergyIntolerance',
87
+ Immunization = 'Immunization',
88
+ CarePlan = 'CarePlan',
89
+ }
90
+
91
+ // HIPAA Audit Event Types
92
+ enum AuditEventType {
93
+ CREATE = 'C',
94
+ READ = 'R',
95
+ UPDATE = 'U',
96
+ DELETE = 'D',
97
+ EXECUTE = 'E',
98
+ LOGIN = 'LOGIN',
99
+ LOGOUT = 'LOGOUT',
100
+ EMERGENCY_ACCESS = 'EMERGENCY',
101
+ }
102
+
103
+ // Configuration
104
+ const config = {
105
+ hipaa: {
106
+ encryptionAlgorithm: 'aes-256-gcm',
107
+ keyRotationDays: 90,
108
+ sessionTimeout: 900000, // 15 minutes
109
+ passwordComplexity: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{12,}$/,
110
+ maxLoginAttempts: 3,
111
+ auditRetentionYears: 7,
112
+ },
113
+ fhir: {
114
+ version: 'R4',
115
+ baseUrl: process.env.FHIR_BASE_URL || 'https://api.healthcare.org/fhir',
116
+ supportedFormats: ['application/fhir+json', 'application/fhir+xml'],
117
+ },
118
+ security: {
119
+ jwtSecret: process.env.JWT_SECRET!,
120
+ jwtExpiry: '1h',
121
+ mfaRequired: true,
122
+ breakGlassEnabled: true,
123
+ },
124
+ };
125
+
126
+ // Database with encryption at rest
127
+ const db = new Pool({
128
+ host: process.env.DB_HOST,
129
+ port: parseInt(process.env.DB_PORT || '5432'),
130
+ database: process.env.DB_NAME,
131
+ user: process.env.DB_USER,
132
+ password: process.env.DB_PASSWORD,
133
+ ssl: {
134
+ rejectUnauthorized: true,
135
+ ca: process.env.DB_CA_CERT,
136
+ },
137
+ max: 20,
138
+ idleTimeoutMillis: 30000,
139
+ });
140
+
141
+ // Redis for caching and session management
142
+ const redis = new Redis({
143
+ host: process.env.REDIS_HOST,
144
+ port: parseInt(process.env.REDIS_PORT || '6379'),
145
+ password: process.env.REDIS_PASSWORD,
146
+ tls: {
147
+ rejectUnauthorized: true,
148
+ },
149
+ });
150
+
151
+ // HIPAA-compliant audit logger
152
+ const auditLogger = winston.createLogger({
153
+ level: 'info',
154
+ format: winston.format.combine(
155
+ winston.format.timestamp(),
156
+ winston.format.json()
157
+ ),
158
+ transports: [
159
+ new winston.transports.File({
160
+ filename: 'hipaa-audit.log',
161
+ maxsize: 10485760, // 10MB
162
+ maxFiles: 100,
163
+ options: { flags: 'a' }
164
+ }),
165
+ new winston.transports.Console({
166
+ format: winston.format.simple()
167
+ })
168
+ ],
169
+ });
170
+
171
+ // FHIR Resource Interfaces
172
+ interface FHIRResource {
173
+ resourceType: ResourceType;
174
+ id?: string;
175
+ meta?: {
176
+ versionId: string;
177
+ lastUpdated: string;
178
+ profile?: string[];
179
+ security?: Coding[];
180
+ tag?: Coding[];
181
+ };
182
+ }
183
+
184
+ interface Patient extends FHIRResource {
185
+ resourceType: ResourceType.Patient;
186
+ identifier?: Identifier[];
187
+ active?: boolean;
188
+ name?: HumanName[];
189
+ telecom?: ContactPoint[];
190
+ gender?: 'male' | 'female' | 'other' | 'unknown';
191
+ birthDate?: string;
192
+ deceasedBoolean?: boolean;
193
+ deceasedDateTime?: string;
194
+ address?: Address[];
195
+ maritalStatus?: CodeableConcept;
196
+ multipleBirthBoolean?: boolean;
197
+ multipleBirthInteger?: number;
198
+ photo?: Attachment[];
199
+ contact?: PatientContact[];
200
+ communication?: PatientCommunication[];
201
+ generalPractitioner?: Reference[];
202
+ managingOrganization?: Reference;
203
+ }
204
+
205
+ interface Observation extends FHIRResource {
206
+ resourceType: ResourceType.Observation;
207
+ status: 'registered' | 'preliminary' | 'final' | 'amended' | 'corrected' | 'cancelled' | 'entered-in-error';
208
+ category?: CodeableConcept[];
209
+ code: CodeableConcept;
210
+ subject?: Reference;
211
+ encounter?: Reference;
212
+ effectiveDateTime?: string;
213
+ effectivePeriod?: Period;
214
+ issued?: string;
215
+ performer?: Reference[];
216
+ valueQuantity?: Quantity;
217
+ valueCodeableConcept?: CodeableConcept;
218
+ valueString?: string;
219
+ valueBoolean?: boolean;
220
+ valueInteger?: number;
221
+ valueRange?: Range;
222
+ interpretation?: CodeableConcept[];
223
+ note?: Annotation[];
224
+ referenceRange?: ObservationReferenceRange[];
225
+ }
226
+
227
+ // HIPAA Security Service
228
+ class HIPAASecurityService {
229
+ private encryptionKey: Buffer;
230
+
231
+ constructor() {
232
+ this.encryptionKey = this.deriveKey();
233
+ this.scheduleKeyRotation();
234
+ }
235
+
236
+ private deriveKey(): Buffer {
237
+ const masterKey = process.env.MASTER_KEY!;
238
+ const salt = process.env.KEY_SALT!;
239
+ return crypto.pbkdf2Sync(masterKey, salt, 100000, 32, 'sha256');
240
+ }
241
+
242
+ private scheduleKeyRotation() {
243
+ setInterval(() => {
244
+ this.rotateEncryptionKey();
245
+ }, config.hipaa.keyRotationDays * 24 * 60 * 60 * 1000);
246
+ }
247
+
248
+ private async rotateEncryptionKey() {
249
+ // Generate new key
250
+ const newKey = crypto.randomBytes(32);
251
+
252
+ // Re-encrypt all sensitive data with new key
253
+ await this.reencryptData(newKey);
254
+
255
+ // Update key in secure key management system
256
+ this.encryptionKey = newKey;
257
+
258
+ auditLogger.info('Encryption key rotated', {
259
+ timestamp: new Date().toISOString(),
260
+ keyVersion: crypto.createHash('sha256').update(newKey).digest('hex').substring(0, 8),
261
+ });
262
+ }
263
+
264
+ encryptPHI(data: string): { encrypted: string; iv: string; tag: string } {
265
+ const iv = crypto.randomBytes(16);
266
+ const cipher = crypto.createCipheriv(config.hipaa.encryptionAlgorithm, this.encryptionKey, iv);
267
+
268
+ let encrypted = cipher.update(data, 'utf8', 'hex');
269
+ encrypted += cipher.final('hex');
270
+
271
+ const tag = (cipher as any).getAuthTag();
272
+
273
+ return {
274
+ encrypted,
275
+ iv: iv.toString('hex'),
276
+ tag: tag.toString('hex'),
277
+ };
278
+ }
279
+
280
+ decryptPHI(encrypted: string, iv: string, tag: string): string {
281
+ const decipher = crypto.createDecipheriv(
282
+ config.hipaa.encryptionAlgorithm,
283
+ this.encryptionKey,
284
+ Buffer.from(iv, 'hex')
285
+ );
286
+
287
+ (decipher as any).setAuthTag(Buffer.from(tag, 'hex'));
288
+
289
+ let decrypted = decipher.update(encrypted, 'hex', 'utf8');
290
+ decrypted += decipher.final('utf8');
291
+
292
+ return decrypted;
293
+ }
294
+
295
+ async reencryptData(newKey: Buffer) {
296
+ // Implementation for re-encrypting existing data
297
+ const client = await db.connect();
298
+ try {
299
+ await client.query('BEGIN');
300
+
301
+ // Re-encrypt patient data
302
+ const patients = await client.query('SELECT * FROM patients WHERE encrypted = true');
303
+ for (const patient of patients.rows) {
304
+ const decrypted = this.decryptPHI(
305
+ patient.encrypted_data,
306
+ patient.encryption_iv,
307
+ patient.encryption_tag
308
+ );
309
+
310
+ const reencrypted = this.encryptWithKey(decrypted, newKey);
311
+
312
+ await client.query(
313
+ 'UPDATE patients SET encrypted_data = $1, encryption_iv = $2, encryption_tag = $3 WHERE id = $4',
314
+ [reencrypted.encrypted, reencrypted.iv, reencrypted.tag, patient.id]
315
+ );
316
+ }
317
+
318
+ await client.query('COMMIT');
319
+ } catch (error) {
320
+ await client.query('ROLLBACK');
321
+ throw error;
322
+ } finally {
323
+ client.release();
324
+ }
325
+ }
326
+
327
+ private encryptWithKey(data: string, key: Buffer) {
328
+ const iv = crypto.randomBytes(16);
329
+ const cipher = crypto.createCipheriv(config.hipaa.encryptionAlgorithm, key, iv);
330
+
331
+ let encrypted = cipher.update(data, 'utf8', 'hex');
332
+ encrypted += cipher.final('hex');
333
+
334
+ const tag = (cipher as any).getAuthTag();
335
+
336
+ return {
337
+ encrypted,
338
+ iv: iv.toString('hex'),
339
+ tag: tag.toString('hex'),
340
+ };
341
+ }
342
+
343
+ hashPassword(password: string): string {
344
+ const salt = crypto.randomBytes(16).toString('hex');
345
+ const hash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512').toString('hex');
346
+ return `${salt}:${hash}`;
347
+ }
348
+
349
+ verifyPassword(password: string, hashedPassword: string): boolean {
350
+ const [salt, hash] = hashedPassword.split(':');
351
+ const verifyHash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512').toString('hex');
352
+ return hash === verifyHash;
353
+ }
354
+
355
+ generateSessionToken(userId: string, role: string): string {
356
+ return jwt.sign(
357
+ {
358
+ userId,
359
+ role,
360
+ sessionId: uuidv4(),
361
+ iat: Math.floor(Date.now() / 1000),
362
+ },
363
+ config.security.jwtSecret,
364
+ { expiresIn: config.security.jwtExpiry }
365
+ );
366
+ }
367
+
368
+ verifySessionToken(token: string): any {
369
+ try {
370
+ return jwt.verify(token, config.security.jwtSecret);
371
+ } catch (error) {
372
+ return null;
373
+ }
374
+ }
375
+ }
376
+
377
+ // HIPAA Audit Service
378
+ class HIPAAAuditService {
379
+ async logAccess(
380
+ userId: string,
381
+ patientId: string,
382
+ resourceType: string,
383
+ action: AuditEventType,
384
+ outcome: 'success' | 'failure',
385
+ reason?: string
386
+ ) {
387
+ const auditEntry = {
388
+ timestamp: new Date().toISOString(),
389
+ userId,
390
+ patientId,
391
+ resourceType,
392
+ action,
393
+ outcome,
394
+ reason,
395
+ ipAddress: this.getClientIp(),
396
+ userAgent: this.getUserAgent(),
397
+ sessionId: this.getSessionId(),
398
+ };
399
+
400
+ // Log to audit log
401
+ auditLogger.info('PHI Access', auditEntry);
402
+
403
+ // Store in database for long-term retention
404
+ await db.query(
405
+ `INSERT INTO audit_log
406
+ (timestamp, user_id, patient_id, resource_type, action, outcome, reason, ip_address, user_agent, session_id)
407
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,
408
+ [
409
+ auditEntry.timestamp,
410
+ auditEntry.userId,
411
+ auditEntry.patientId,
412
+ auditEntry.resourceType,
413
+ auditEntry.action,
414
+ auditEntry.outcome,
415
+ auditEntry.reason,
416
+ auditEntry.ipAddress,
417
+ auditEntry.userAgent,
418
+ auditEntry.sessionId,
419
+ ]
420
+ );
421
+
422
+ // Real-time alerting for suspicious activity
423
+ if (outcome === 'failure') {
424
+ await this.checkSuspiciousActivity(userId);
425
+ }
426
+ }
427
+
428
+ async checkSuspiciousActivity(userId: string) {
429
+ const recentFailures = await db.query(
430
+ `SELECT COUNT(*) as count
431
+ FROM audit_log
432
+ WHERE user_id = $1
433
+ AND outcome = 'failure'
434
+ AND timestamp > NOW() - INTERVAL '15 minutes'`,
435
+ [userId]
436
+ );
437
+
438
+ if (recentFailures.rows[0].count >= 5) {
439
+ // Alert security team
440
+ await this.sendSecurityAlert({
441
+ type: 'SUSPICIOUS_ACTIVITY',
442
+ userId,
443
+ message: 'Multiple failed access attempts detected',
444
+ severity: 'HIGH',
445
+ });
446
+
447
+ // Temporarily lock account
448
+ await this.lockUserAccount(userId);
449
+ }
450
+ }
451
+
452
+ async sendSecurityAlert(alert: any) {
453
+ // Send to security monitoring system
454
+ // Implementation would integrate with SIEM
455
+ auditLogger.warn('Security Alert', alert);
456
+ }
457
+
458
+ async lockUserAccount(userId: string) {
459
+ await db.query(
460
+ 'UPDATE users SET locked = true, lock_reason = $1, locked_at = NOW() WHERE id = $2',
461
+ ['Suspicious activity detected', userId]
462
+ );
463
+ }
464
+
465
+ private getClientIp(): string {
466
+ // Get from request context
467
+ return '127.0.0.1'; // Placeholder
468
+ }
469
+
470
+ private getUserAgent(): string {
471
+ // Get from request headers
472
+ return 'Mozilla/5.0'; // Placeholder
473
+ }
474
+
475
+ private getSessionId(): string {
476
+ // Get from session context
477
+ return uuidv4(); // Placeholder
478
+ }
479
+ }
480
+
481
+ // FHIR Resource Repository
482
+ class FHIRRepository {
483
+ private security = new HIPAASecurityService();
484
+ private audit = new HIPAAAuditService();
485
+
486
+ async createResource(
487
+ resource: FHIRResource,
488
+ userId: string,
489
+ reason?: string
490
+ ): Promise<FHIRResource> {
491
+ const client = await db.connect();
492
+
493
+ try {
494
+ await client.query('BEGIN');
495
+
496
+ // Generate resource ID and metadata
497
+ resource.id = resource.id || uuidv4();
498
+ resource.meta = {
499
+ versionId: '1',
500
+ lastUpdated: new Date().toISOString(),
501
+ profile: this.getResourceProfiles(resource.resourceType),
502
+ };
503
+
504
+ // Encrypt sensitive data
505
+ const encryptedData = this.security.encryptPHI(JSON.stringify(resource));
506
+
507
+ // Store resource
508
+ await client.query(
509
+ `INSERT INTO fhir_resources
510
+ (id, resource_type, version, data, encrypted_data, encryption_iv, encryption_tag, created_at, created_by)
511
+ VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), $8)`,
512
+ [
513
+ resource.id,
514
+ resource.resourceType,
515
+ 1,
516
+ null, // Store encrypted only
517
+ encryptedData.encrypted,
518
+ encryptedData.iv,
519
+ encryptedData.tag,
520
+ userId,
521
+ ]
522
+ );
523
+
524
+ // Create audit log
525
+ await this.audit.logAccess(
526
+ userId,
527
+ this.getPatientId(resource),
528
+ resource.resourceType,
529
+ AuditEventType.CREATE,
530
+ 'success',
531
+ reason
532
+ );
533
+
534
+ await client.query('COMMIT');
535
+
536
+ return resource;
537
+ } catch (error) {
538
+ await client.query('ROLLBACK');
539
+
540
+ await this.audit.logAccess(
541
+ userId,
542
+ this.getPatientId(resource),
543
+ resource.resourceType,
544
+ AuditEventType.CREATE,
545
+ 'failure',
546
+ error.message
547
+ );
548
+
549
+ throw error;
550
+ } finally {
551
+ client.release();
552
+ }
553
+ }
554
+
555
+ async readResource(
556
+ resourceType: ResourceType,
557
+ id: string,
558
+ userId: string,
559
+ reason?: string
560
+ ): Promise<FHIRResource | null> {
561
+ try {
562
+ // Check access permissions
563
+ const hasAccess = await this.checkAccess(userId, resourceType, id);
564
+ if (!hasAccess) {
565
+ await this.audit.logAccess(
566
+ userId,
567
+ id,
568
+ resourceType,
569
+ AuditEventType.READ,
570
+ 'failure',
571
+ 'Access denied'
572
+ );
573
+ throw new Error('Access denied');
574
+ }
575
+
576
+ // Retrieve resource
577
+ const result = await db.query(
578
+ 'SELECT * FROM fhir_resources WHERE id = $1 AND resource_type = $2',
579
+ [id, resourceType]
580
+ );
581
+
582
+ if (result.rows.length === 0) {
583
+ return null;
584
+ }
585
+
586
+ const row = result.rows[0];
587
+
588
+ // Decrypt resource
589
+ const decrypted = this.security.decryptPHI(
590
+ row.encrypted_data,
591
+ row.encryption_iv,
592
+ row.encryption_tag
593
+ );
594
+
595
+ const resource = JSON.parse(decrypted);
596
+
597
+ // Log access
598
+ await this.audit.logAccess(
599
+ userId,
600
+ this.getPatientId(resource),
601
+ resourceType,
602
+ AuditEventType.READ,
603
+ 'success',
604
+ reason
605
+ );
606
+
607
+ return resource;
608
+ } catch (error) {
609
+ await this.audit.logAccess(
610
+ userId,
611
+ id,
612
+ resourceType,
613
+ AuditEventType.READ,
614
+ 'failure',
615
+ error.message
616
+ );
617
+ throw error;
618
+ }
619
+ }
620
+
621
+ async updateResource(
622
+ resource: FHIRResource,
623
+ userId: string,
624
+ reason?: string
625
+ ): Promise<FHIRResource> {
626
+ const client = await db.connect();
627
+
628
+ try {
629
+ await client.query('BEGIN');
630
+
631
+ // Get current version
632
+ const current = await this.readResource(
633
+ resource.resourceType,
634
+ resource.id!,
635
+ userId,
636
+ 'Update operation'
637
+ );
638
+
639
+ if (!current) {
640
+ throw new Error('Resource not found');
641
+ }
642
+
643
+ // Update metadata
644
+ const newVersion = parseInt(current.meta!.versionId) + 1;
645
+ resource.meta = {
646
+ ...resource.meta,
647
+ versionId: newVersion.toString(),
648
+ lastUpdated: new Date().toISOString(),
649
+ };
650
+
651
+ // Archive current version
652
+ await client.query(
653
+ `INSERT INTO fhir_resource_history
654
+ SELECT * FROM fhir_resources WHERE id = $1`,
655
+ [resource.id]
656
+ );
657
+
658
+ // Encrypt and update
659
+ const encryptedData = this.security.encryptPHI(JSON.stringify(resource));
660
+
661
+ await client.query(
662
+ `UPDATE fhir_resources
663
+ SET version = $1, encrypted_data = $2, encryption_iv = $3,
664
+ encryption_tag = $4, updated_at = NOW(), updated_by = $5
665
+ WHERE id = $6`,
666
+ [
667
+ newVersion,
668
+ encryptedData.encrypted,
669
+ encryptedData.iv,
670
+ encryptedData.tag,
671
+ userId,
672
+ resource.id,
673
+ ]
674
+ );
675
+
676
+ // Audit log
677
+ await this.audit.logAccess(
678
+ userId,
679
+ this.getPatientId(resource),
680
+ resource.resourceType,
681
+ AuditEventType.UPDATE,
682
+ 'success',
683
+ reason
684
+ );
685
+
686
+ await client.query('COMMIT');
687
+
688
+ return resource;
689
+ } catch (error) {
690
+ await client.query('ROLLBACK');
691
+
692
+ await this.audit.logAccess(
693
+ userId,
694
+ resource.id!,
695
+ resource.resourceType,
696
+ AuditEventType.UPDATE,
697
+ 'failure',
698
+ error.message
699
+ );
700
+
701
+ throw error;
702
+ } finally {
703
+ client.release();
704
+ }
705
+ }
706
+
707
+ async searchResources(
708
+ resourceType: ResourceType,
709
+ params: any,
710
+ userId: string
711
+ ): Promise<Bundle> {
712
+ // Implement FHIR search with proper access control
713
+ const searchResults: FHIRResource[] = [];
714
+
715
+ // Build search query based on FHIR search parameters
716
+ let query = `SELECT * FROM fhir_resources WHERE resource_type = $1`;
717
+ const queryParams = [resourceType];
718
+
719
+ // Add search parameters
720
+ if (params.patient) {
721
+ query += ` AND data->>'subject'->>'reference' = $${queryParams.length + 1}`;
722
+ queryParams.push(`Patient/${params.patient}`);
723
+ }
724
+
725
+ if (params.date) {
726
+ // Handle date search
727
+ }
728
+
729
+ // Execute search
730
+ const results = await db.query(query, queryParams);
731
+
732
+ // Decrypt and filter based on access
733
+ for (const row of results.rows) {
734
+ if (await this.checkAccess(userId, resourceType, row.id)) {
735
+ const decrypted = this.security.decryptPHI(
736
+ row.encrypted_data,
737
+ row.encryption_iv,
738
+ row.encryption_tag
739
+ );
740
+ searchResults.push(JSON.parse(decrypted));
741
+ }
742
+ }
743
+
744
+ // Create FHIR Bundle
745
+ return {
746
+ resourceType: 'Bundle',
747
+ type: 'searchset',
748
+ total: searchResults.length,
749
+ entry: searchResults.map(resource => ({
750
+ fullUrl: `${config.fhir.baseUrl}/${resource.resourceType}/${resource.id}`,
751
+ resource,
752
+ })),
753
+ };
754
+ }
755
+
756
+ private async checkAccess(userId: string, resourceType: string, resourceId: string): Promise<boolean> {
757
+ // Implement role-based access control
758
+ const user = await db.query('SELECT role, department FROM users WHERE id = $1', [userId]);
759
+
760
+ if (user.rows.length === 0) {
761
+ return false;
762
+ }
763
+
764
+ const { role, department } = user.rows[0];
765
+
766
+ // Check role-based permissions
767
+ if (role === 'admin') {
768
+ return true;
769
+ }
770
+
771
+ if (role === 'physician') {
772
+ // Check if physician has relationship with patient
773
+ return await this.checkPhysicianPatientRelationship(userId, resourceId);
774
+ }
775
+
776
+ if (role === 'nurse') {
777
+ // Check department and shift
778
+ return await this.checkNurseAccess(userId, resourceId, department);
779
+ }
780
+
781
+ return false;
782
+ }
783
+
784
+ private async checkPhysicianPatientRelationship(physicianId: string, patientId: string): Promise<boolean> {
785
+ const result = await db.query(
786
+ `SELECT COUNT(*) as count
787
+ FROM patient_physician_relationships
788
+ WHERE physician_id = $1 AND patient_id = $2 AND active = true`,
789
+ [physicianId, patientId]
790
+ );
791
+
792
+ return result.rows[0].count > 0;
793
+ }
794
+
795
+ private async checkNurseAccess(nurseId: string, patientId: string, department: string): Promise<boolean> {
796
+ // Check if patient is in nurse's department
797
+ const result = await db.query(
798
+ `SELECT COUNT(*) as count
799
+ FROM patient_admissions
800
+ WHERE patient_id = $1 AND department = $2 AND discharged_at IS NULL`,
801
+ [patientId, department]
802
+ );
803
+
804
+ return result.rows[0].count > 0;
805
+ }
806
+
807
+ private getResourceProfiles(resourceType: ResourceType): string[] {
808
+ // Return US Core profiles
809
+ const profiles: { [key: string]: string[] } = {
810
+ [ResourceType.Patient]: ['http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient'],
811
+ [ResourceType.Observation]: ['http://hl7.org/fhir/us/core/StructureDefinition/us-core-observation'],
812
+ [ResourceType.Condition]: ['http://hl7.org/fhir/us/core/StructureDefinition/us-core-condition'],
813
+ };
814
+
815
+ return profiles[resourceType] || [];
816
+ }
817
+
818
+ private getPatientId(resource: FHIRResource): string {
819
+ if (resource.resourceType === ResourceType.Patient) {
820
+ return resource.id!;
821
+ }
822
+
823
+ // Extract patient reference from other resources
824
+ const resourceWithSubject = resource as any;
825
+ if (resourceWithSubject.subject?.reference) {
826
+ return resourceWithSubject.subject.reference.replace('Patient/', '');
827
+ }
828
+
829
+ return 'unknown';
830
+ }
831
+ }
832
+
833
+ // Clinical Decision Support
834
+ class ClinicalDecisionSupport {
835
+ async checkDrugInteractions(medications: Medication[]): Promise<Alert[]> {
836
+ const alerts: Alert[] = [];
837
+
838
+ // Check for drug-drug interactions
839
+ for (let i = 0; i < medications.length; i++) {
840
+ for (let j = i + 1; j < medications.length; j++) {
841
+ const interaction = await this.checkInteraction(
842
+ medications[i],
843
+ medications[j]
844
+ );
845
+
846
+ if (interaction) {
847
+ alerts.push({
848
+ severity: interaction.severity,
849
+ type: 'drug-interaction',
850
+ message: interaction.message,
851
+ medications: [medications[i].id!, medications[j].id!],
852
+ });
853
+ }
854
+ }
855
+ }
856
+
857
+ return alerts;
858
+ }
859
+
860
+ async checkAllergies(patient: Patient, medication: Medication): Promise<Alert[]> {
861
+ const alerts: Alert[] = [];
862
+
863
+ // Get patient allergies
864
+ const allergies = await this.getPatientAllergies(patient.id!);
865
+
866
+ for (const allergy of allergies) {
867
+ if (this.medicationContainsAllergen(medication, allergy)) {
868
+ alerts.push({
869
+ severity: 'high',
870
+ type: 'allergy',
871
+ message: `Patient is allergic to ${allergy.substance}`,
872
+ allergyId: allergy.id,
873
+ medicationId: medication.id!,
874
+ });
875
+ }
876
+ }
877
+
878
+ return alerts;
879
+ }
880
+
881
+ async checkDosing(
882
+ medication: Medication,
883
+ patient: Patient,
884
+ renalFunction?: number,
885
+ hepaticFunction?: number
886
+ ): Promise<Alert[]> {
887
+ const alerts: Alert[] = [];
888
+
889
+ // Calculate age
890
+ const age = this.calculateAge(patient.birthDate!);
891
+
892
+ // Check pediatric dosing
893
+ if (age < 18) {
894
+ const pediatricDose = await this.getPediatricDosing(medication, age, patient);
895
+ if (pediatricDose) {
896
+ alerts.push({
897
+ severity: 'medium',
898
+ type: 'dosing',
899
+ message: `Recommended pediatric dose: ${pediatricDose}`,
900
+ });
901
+ }
902
+ }
903
+
904
+ // Check geriatric dosing
905
+ if (age > 65) {
906
+ const geriatricDose = await this.getGeriatricDosing(medication, age);
907
+ if (geriatricDose) {
908
+ alerts.push({
909
+ severity: 'medium',
910
+ type: 'dosing',
911
+ message: `Consider dose adjustment for geriatric patient: ${geriatricDose}`,
912
+ });
913
+ }
914
+ }
915
+
916
+ // Check renal dosing
917
+ if (renalFunction && renalFunction < 60) {
918
+ const renalDose = await this.getRenalDosing(medication, renalFunction);
919
+ if (renalDose) {
920
+ alerts.push({
921
+ severity: 'high',
922
+ type: 'dosing',
923
+ message: `Renal dose adjustment needed: ${renalDose}`,
924
+ });
925
+ }
926
+ }
927
+
928
+ // Check hepatic dosing
929
+ if (hepaticFunction && hepaticFunction < 70) {
930
+ const hepaticDose = await this.getHepaticDosing(medication, hepaticFunction);
931
+ if (hepaticDose) {
932
+ alerts.push({
933
+ severity: 'high',
934
+ type: 'dosing',
935
+ message: `Hepatic dose adjustment needed: ${hepaticDose}`,
936
+ });
937
+ }
938
+ }
939
+
940
+ return alerts;
941
+ }
942
+
943
+ private async checkInteraction(med1: Medication, med2: Medication) {
944
+ // Query drug interaction database
945
+ // This would integrate with a service like First Databank or Micromedex
946
+ return null; // Placeholder
947
+ }
948
+
949
+ private async getPatientAllergies(patientId: string) {
950
+ const result = await db.query(
951
+ 'SELECT * FROM allergies WHERE patient_id = $1 AND active = true',
952
+ [patientId]
953
+ );
954
+ return result.rows;
955
+ }
956
+
957
+ private medicationContainsAllergen(medication: Medication, allergy: any): boolean {
958
+ // Check if medication contains allergen
959
+ return false; // Placeholder
960
+ }
961
+
962
+ private calculateAge(birthDate: string): number {
963
+ const birth = new Date(birthDate);
964
+ const today = new Date();
965
+ let age = today.getFullYear() - birth.getFullYear();
966
+ const monthDiff = today.getMonth() - birth.getMonth();
967
+
968
+ if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
969
+ age--;
970
+ }
971
+
972
+ return age;
973
+ }
974
+
975
+ private async getPediatricDosing(medication: Medication, age: number, patient: Patient) {
976
+ // Calculate pediatric dosing based on age and weight
977
+ return null; // Placeholder
978
+ }
979
+
980
+ private async getGeriatricDosing(medication: Medication, age: number) {
981
+ // Get geriatric dosing recommendations
982
+ return null; // Placeholder
983
+ }
984
+
985
+ private async getRenalDosing(medication: Medication, gfr: number) {
986
+ // Calculate renal dosing adjustment
987
+ return null; // Placeholder
988
+ }
989
+
990
+ private async getHepaticDosing(medication: Medication, liverFunction: number) {
991
+ // Calculate hepatic dosing adjustment
992
+ return null; // Placeholder
993
+ }
994
+ }
995
+
996
+ // HL7 Message Processing
997
+ class HL7Processor {
998
+ async processMessage(message: string): Promise<void> {
999
+ try {
1000
+ // Parse HL7 message
1001
+ const parsed = hl7.parse(message);
1002
+
1003
+ // Extract message type
1004
+ const messageType = parsed.MSH[9][0]; // Message type
1005
+
1006
+ // Process based on message type
1007
+ switch (messageType) {
1008
+ case 'ADT': // Admission, Discharge, Transfer
1009
+ await this.processADT(parsed);
1010
+ break;
1011
+ case 'ORM': // Order Message
1012
+ await this.processORM(parsed);
1013
+ break;
1014
+ case 'ORU': // Observation Result
1015
+ await this.processORU(parsed);
1016
+ break;
1017
+ case 'SIU': // Scheduling
1018
+ await this.processSIU(parsed);
1019
+ break;
1020
+ default:
1021
+ throw new Error(`Unsupported message type: ${messageType}`);
1022
+ }
1023
+
1024
+ // Send acknowledgment
1025
+ await this.sendACK(parsed);
1026
+
1027
+ } catch (error) {
1028
+ auditLogger.error('HL7 processing error', {
1029
+ error: error.message,
1030
+ message: message.substring(0, 100),
1031
+ });
1032
+
1033
+ // Send NACK
1034
+ await this.sendNACK(error.message);
1035
+ }
1036
+ }
1037
+
1038
+ private async processADT(message: any) {
1039
+ const eventType = message.MSH[9][1]; // Event type (A01, A02, etc.)
1040
+
1041
+ switch (eventType) {
1042
+ case 'A01': // Admission
1043
+ await this.handleAdmission(message);
1044
+ break;
1045
+ case 'A03': // Discharge
1046
+ await this.handleDischarge(message);
1047
+ break;
1048
+ case 'A02': // Transfer
1049
+ await this.handleTransfer(message);
1050
+ break;
1051
+ }
1052
+ }
1053
+
1054
+ private async processORM(message: any) {
1055
+ // Process order message
1056
+ const order = {
1057
+ patientId: message.PID[3][0],
1058
+ orderNumber: message.ORC[2][0],
1059
+ orderDate: message.ORC[9][0],
1060
+ orderingProvider: message.ORC[12][0],
1061
+ orderType: message.OBR[4][0],
1062
+ };
1063
+
1064
+ // Store order in database
1065
+ await db.query(
1066
+ `INSERT INTO orders (patient_id, order_number, order_date, provider_id, order_type)
1067
+ VALUES ($1, $2, $3, $4, $5)`,
1068
+ [order.patientId, order.orderNumber, order.orderDate, order.orderingProvider, order.orderType]
1069
+ );
1070
+ }
1071
+
1072
+ private async processORU(message: any) {
1073
+ // Process observation result
1074
+ const observation = {
1075
+ patientId: message.PID[3][0],
1076
+ observationId: message.OBR[3][0],
1077
+ observationDate: message.OBR[7][0],
1078
+ results: [],
1079
+ };
1080
+
1081
+ // Extract results from OBX segments
1082
+ for (const obx of message.OBX || []) {
1083
+ observation.results.push({
1084
+ type: obx[3][0],
1085
+ value: obx[5][0],
1086
+ units: obx[6][0],
1087
+ referenceRange: obx[7][0],
1088
+ abnormalFlag: obx[8][0],
1089
+ });
1090
+ }
1091
+
1092
+ // Convert to FHIR Observation and store
1093
+ const fhirObservation = await this.convertToFHIRObservation(observation);
1094
+ // Store observation
1095
+ }
1096
+
1097
+ private async processSIU(message: any) {
1098
+ // Process scheduling message
1099
+ const appointment = {
1100
+ patientId: message.PID[3][0],
1101
+ appointmentId: message.SCH[1][0],
1102
+ startTime: message.SCH[11][0],
1103
+ duration: message.SCH[9][0],
1104
+ providerId: message.AIP[3][0],
1105
+ location: message.AIL[3][0],
1106
+ };
1107
+
1108
+ // Store appointment
1109
+ await db.query(
1110
+ `INSERT INTO appointments
1111
+ (patient_id, appointment_id, start_time, duration, provider_id, location)
1112
+ VALUES ($1, $2, $3, $4, $5, $6)`,
1113
+ [
1114
+ appointment.patientId,
1115
+ appointment.appointmentId,
1116
+ appointment.startTime,
1117
+ appointment.duration,
1118
+ appointment.providerId,
1119
+ appointment.location,
1120
+ ]
1121
+ );
1122
+ }
1123
+
1124
+ private async handleAdmission(message: any) {
1125
+ // Handle patient admission
1126
+ const admission = {
1127
+ patientId: message.PID[3][0],
1128
+ admissionDate: message.PV1[44][0],
1129
+ department: message.PV1[3][0],
1130
+ room: message.PV1[3][2],
1131
+ bed: message.PV1[3][3],
1132
+ attendingPhysician: message.PV1[7][0],
1133
+ };
1134
+
1135
+ await db.query(
1136
+ `INSERT INTO admissions
1137
+ (patient_id, admission_date, department, room, bed, attending_physician)
1138
+ VALUES ($1, $2, $3, $4, $5, $6)`,
1139
+ Object.values(admission)
1140
+ );
1141
+ }
1142
+
1143
+ private async handleDischarge(message: any) {
1144
+ // Handle patient discharge
1145
+ const discharge = {
1146
+ patientId: message.PID[3][0],
1147
+ dischargeDate: message.PV1[45][0],
1148
+ dischargeDisposition: message.PV1[36][0],
1149
+ };
1150
+
1151
+ await db.query(
1152
+ `UPDATE admissions
1153
+ SET discharge_date = $1, discharge_disposition = $2
1154
+ WHERE patient_id = $3 AND discharge_date IS NULL`,
1155
+ [discharge.dischargeDate, discharge.dischargeDisposition, discharge.patientId]
1156
+ );
1157
+ }
1158
+
1159
+ private async handleTransfer(message: any) {
1160
+ // Handle patient transfer
1161
+ const transfer = {
1162
+ patientId: message.PID[3][0],
1163
+ fromDepartment: message.PV1[6][0],
1164
+ toDepartment: message.PV1[3][0],
1165
+ transferDate: message.EVN[6][0],
1166
+ };
1167
+
1168
+ await db.query(
1169
+ `INSERT INTO transfers
1170
+ (patient_id, from_department, to_department, transfer_date)
1171
+ VALUES ($1, $2, $3, $4)`,
1172
+ Object.values(transfer)
1173
+ );
1174
+ }
1175
+
1176
+ private async convertToFHIRObservation(hl7Observation: any): Promise<Observation> {
1177
+ // Convert HL7 observation to FHIR format
1178
+ return {
1179
+ resourceType: ResourceType.Observation,
1180
+ status: 'final',
1181
+ code: {
1182
+ coding: [{
1183
+ system: 'http://loinc.org',
1184
+ code: hl7Observation.type,
1185
+ }],
1186
+ },
1187
+ effectiveDateTime: hl7Observation.observationDate,
1188
+ valueQuantity: {
1189
+ value: parseFloat(hl7Observation.results[0]?.value),
1190
+ unit: hl7Observation.results[0]?.units,
1191
+ },
1192
+ };
1193
+ }
1194
+
1195
+ private async sendACK(originalMessage: any) {
1196
+ // Send HL7 acknowledgment
1197
+ const ack = {
1198
+ MSH: {
1199
+ ...originalMessage.MSH,
1200
+ 9: ['ACK'],
1201
+ },
1202
+ MSA: {
1203
+ 1: 'AA', // Application Accept
1204
+ 2: originalMessage.MSH[10], // Message control ID
1205
+ },
1206
+ };
1207
+
1208
+ // Send ACK message
1209
+ }
1210
+
1211
+ private async sendNACK(error: string) {
1212
+ // Send negative acknowledgment
1213
+ const nack = {
1214
+ MSA: {
1215
+ 1: 'AE', // Application Error
1216
+ 3: error,
1217
+ },
1218
+ };
1219
+
1220
+ // Send NACK message
1221
+ }
1222
+ }
1223
+
1224
+ // DICOM Image Processing
1225
+ class DICOMProcessor {
1226
+ async processImage(buffer: Buffer): Promise<void> {
1227
+ try {
1228
+ // Parse DICOM file
1229
+ const dataSet = dicom.parseDicom(buffer);
1230
+
1231
+ // Extract metadata
1232
+ const metadata = {
1233
+ patientId: dataSet.string('x00100020'),
1234
+ patientName: dataSet.string('x00100010'),
1235
+ studyInstanceUID: dataSet.string('x0020000d'),
1236
+ seriesInstanceUID: dataSet.string('x0020000e'),
1237
+ sopInstanceUID: dataSet.string('x00080018'),
1238
+ modality: dataSet.string('x00080060'),
1239
+ studyDate: dataSet.string('x00080020'),
1240
+ studyDescription: dataSet.string('x00081030'),
1241
+ };
1242
+
1243
+ // Store metadata in database
1244
+ await this.storeDICOMMetadata(metadata);
1245
+
1246
+ // Store image in PACS
1247
+ await this.storeInPACS(buffer, metadata);
1248
+
1249
+ // Apply de-identification if needed
1250
+ if (process.env.DEIDENTIFY_IMAGES === 'true') {
1251
+ await this.deidentifyImage(dataSet);
1252
+ }
1253
+
1254
+ } catch (error) {
1255
+ auditLogger.error('DICOM processing error', {
1256
+ error: error.message,
1257
+ });
1258
+ throw error;
1259
+ }
1260
+ }
1261
+
1262
+ private async storeDICOMMetadata(metadata: any) {
1263
+ await db.query(
1264
+ `INSERT INTO dicom_studies
1265
+ (patient_id, study_uid, series_uid, sop_uid, modality, study_date, description)
1266
+ VALUES ($1, $2, $3, $4, $5, $6, $7)`,
1267
+ [
1268
+ metadata.patientId,
1269
+ metadata.studyInstanceUID,
1270
+ metadata.seriesInstanceUID,
1271
+ metadata.sopInstanceUID,
1272
+ metadata.modality,
1273
+ metadata.studyDate,
1274
+ metadata.studyDescription,
1275
+ ]
1276
+ );
1277
+ }
1278
+
1279
+ private async storeInPACS(buffer: Buffer, metadata: any) {
1280
+ // Store image in Picture Archiving and Communication System
1281
+ // This would integrate with a PACS server
1282
+ }
1283
+
1284
+ private async deidentifyImage(dataSet: any) {
1285
+ // Remove patient identifying information
1286
+ const tagsToRemove = [
1287
+ 'x00100010', // Patient Name
1288
+ 'x00100020', // Patient ID
1289
+ 'x00100030', // Patient Birth Date
1290
+ 'x00100040', // Patient Sex
1291
+ 'x00101010', // Patient Age
1292
+ ];
1293
+
1294
+ for (const tag of tagsToRemove) {
1295
+ delete dataSet.elements[tag];
1296
+ }
1297
+ }
1298
+ }
1299
+
1300
+ // Telemedicine Platform
1301
+ class TelemedicineService {
1302
+ async createVideoConsultation(
1303
+ patientId: string,
1304
+ providerId: string,
1305
+ scheduledTime: Date
1306
+ ): Promise<VideoConsultation> {
1307
+ // Generate secure room
1308
+ const roomId = uuidv4();
1309
+ const roomToken = this.generateSecureToken();
1310
+
1311
+ // Create consultation record
1312
+ const consultation = {
1313
+ id: uuidv4(),
1314
+ patientId,
1315
+ providerId,
1316
+ roomId,
1317
+ scheduledTime,
1318
+ status: 'scheduled',
1319
+ patientToken: this.generatePatientToken(roomId, patientId),
1320
+ providerToken: this.generateProviderToken(roomId, providerId),
1321
+ };
1322
+
1323
+ // Store consultation
1324
+ await db.query(
1325
+ `INSERT INTO video_consultations
1326
+ (id, patient_id, provider_id, room_id, scheduled_time, status, created_at)
1327
+ VALUES ($1, $2, $3, $4, $5, $6, NOW())`,
1328
+ [
1329
+ consultation.id,
1330
+ consultation.patientId,
1331
+ consultation.providerId,
1332
+ consultation.roomId,
1333
+ consultation.scheduledTime,
1334
+ consultation.status,
1335
+ ]
1336
+ );
1337
+
1338
+ // Send notifications
1339
+ await this.sendConsultationNotifications(consultation);
1340
+
1341
+ return consultation;
1342
+ }
1343
+
1344
+ async startConsultation(consultationId: string, userId: string): Promise<void> {
1345
+ // Update consultation status
1346
+ await db.query(
1347
+ 'UPDATE video_consultations SET status = $1, started_at = NOW() WHERE id = $2',
1348
+ ['in_progress', consultationId]
1349
+ );
1350
+
1351
+ // Start recording if required for documentation
1352
+ if (process.env.RECORD_CONSULTATIONS === 'true') {
1353
+ await this.startRecording(consultationId);
1354
+ }
1355
+
1356
+ // Log for audit
1357
+ auditLogger.info('Video consultation started', {
1358
+ consultationId,
1359
+ userId,
1360
+ timestamp: new Date().toISOString(),
1361
+ });
1362
+ }
1363
+
1364
+ async endConsultation(
1365
+ consultationId: string,
1366
+ userId: string,
1367
+ notes?: string
1368
+ ): Promise<void> {
1369
+ // Update consultation status
1370
+ await db.query(
1371
+ `UPDATE video_consultations
1372
+ SET status = $1, ended_at = NOW(), clinical_notes = $2
1373
+ WHERE id = $3`,
1374
+ ['completed', notes, consultationId]
1375
+ );
1376
+
1377
+ // Stop recording
1378
+ await this.stopRecording(consultationId);
1379
+
1380
+ // Generate consultation summary
1381
+ await this.generateConsultationSummary(consultationId);
1382
+
1383
+ // Create billing record
1384
+ await this.createBillingRecord(consultationId);
1385
+ }
1386
+
1387
+ private generateSecureToken(): string {
1388
+ return crypto.randomBytes(32).toString('base64url');
1389
+ }
1390
+
1391
+ private generatePatientToken(roomId: string, patientId: string): string {
1392
+ return jwt.sign(
1393
+ {
1394
+ roomId,
1395
+ patientId,
1396
+ role: 'patient',
1397
+ permissions: ['join', 'video', 'audio', 'chat'],
1398
+ },
1399
+ config.security.jwtSecret,
1400
+ { expiresIn: '2h' }
1401
+ );
1402
+ }
1403
+
1404
+ private generateProviderToken(roomId: string, providerId: string): string {
1405
+ return jwt.sign(
1406
+ {
1407
+ roomId,
1408
+ providerId,
1409
+ role: 'provider',
1410
+ permissions: ['join', 'video', 'audio', 'chat', 'record', 'screenshare'],
1411
+ },
1412
+ config.security.jwtSecret,
1413
+ { expiresIn: '2h' }
1414
+ );
1415
+ }
1416
+
1417
+ private async sendConsultationNotifications(consultation: any) {
1418
+ // Send email/SMS notifications to patient and provider
1419
+ }
1420
+
1421
+ private async startRecording(consultationId: string) {
1422
+ // Start video recording for documentation
1423
+ // Must comply with consent and privacy regulations
1424
+ }
1425
+
1426
+ private async stopRecording(consultationId: string) {
1427
+ // Stop and securely store recording
1428
+ }
1429
+
1430
+ private async generateConsultationSummary(consultationId: string) {
1431
+ // Generate clinical summary document
1432
+ }
1433
+
1434
+ private async createBillingRecord(consultationId: string) {
1435
+ // Create billing record for telemedicine consultation
1436
+ // Include appropriate CPT codes for telehealth
1437
+ }
1438
+ }
1439
+
1440
+ // Type definitions
1441
+ interface Identifier {
1442
+ system?: string;
1443
+ value: string;
1444
+ }
1445
+
1446
+ interface HumanName {
1447
+ family: string;
1448
+ given: string[];
1449
+ }
1450
+
1451
+ interface ContactPoint {
1452
+ system: 'phone' | 'email';
1453
+ value: string;
1454
+ }
1455
+
1456
+ interface Address {
1457
+ line: string[];
1458
+ city: string;
1459
+ state: string;
1460
+ postalCode: string;
1461
+ country: string;
1462
+ }
1463
+
1464
+ interface CodeableConcept {
1465
+ coding?: Coding[];
1466
+ text?: string;
1467
+ }
1468
+
1469
+ interface Coding {
1470
+ system: string;
1471
+ code: string;
1472
+ display?: string;
1473
+ }
1474
+
1475
+ interface Reference {
1476
+ reference: string;
1477
+ display?: string;
1478
+ }
1479
+
1480
+ interface Period {
1481
+ start: string;
1482
+ end?: string;
1483
+ }
1484
+
1485
+ interface Quantity {
1486
+ value: number;
1487
+ unit: string;
1488
+ system?: string;
1489
+ code?: string;
1490
+ }
1491
+
1492
+ interface Range {
1493
+ low: Quantity;
1494
+ high: Quantity;
1495
+ }
1496
+
1497
+ interface Annotation {
1498
+ text: string;
1499
+ time?: string;
1500
+ }
1501
+
1502
+ interface ObservationReferenceRange {
1503
+ low?: Quantity;
1504
+ high?: Quantity;
1505
+ text?: string;
1506
+ }
1507
+
1508
+ interface Attachment {
1509
+ contentType: string;
1510
+ data?: string;
1511
+ url?: string;
1512
+ }
1513
+
1514
+ interface PatientContact {
1515
+ relationship?: CodeableConcept[];
1516
+ name?: HumanName;
1517
+ telecom?: ContactPoint[];
1518
+ }
1519
+
1520
+ interface PatientCommunication {
1521
+ language: CodeableConcept;
1522
+ preferred?: boolean;
1523
+ }
1524
+
1525
+ interface Bundle {
1526
+ resourceType: 'Bundle';
1527
+ type: 'searchset' | 'document' | 'message' | 'transaction' | 'batch';
1528
+ total?: number;
1529
+ entry?: BundleEntry[];
1530
+ }
1531
+
1532
+ interface BundleEntry {
1533
+ fullUrl?: string;
1534
+ resource: FHIRResource;
1535
+ }
1536
+
1537
+ interface Medication extends FHIRResource {
1538
+ resourceType: ResourceType.Medication;
1539
+ code: CodeableConcept;
1540
+ }
1541
+
1542
+ interface Alert {
1543
+ severity: 'low' | 'medium' | 'high';
1544
+ type: string;
1545
+ message: string;
1546
+ [key: string]: any;
1547
+ }
1548
+
1549
+ interface VideoConsultation {
1550
+ id: string;
1551
+ patientId: string;
1552
+ providerId: string;
1553
+ roomId: string;
1554
+ scheduledTime: Date;
1555
+ status: string;
1556
+ patientToken: string;
1557
+ providerToken: string;
1558
+ }
1559
+
1560
+ // Export services
1561
+ export {
1562
+ HIPAASecurityService,
1563
+ HIPAAAuditService,
1564
+ FHIRRepository,
1565
+ ClinicalDecisionSupport,
1566
+ HL7Processor,
1567
+ DICOMProcessor,
1568
+ TelemedicineService,
1569
+ };
1570
+ ```
1571
+
1572
+ ## Best Practices
1573
+
1574
+ ### 1. Regulatory Compliance
1575
+ - Implement comprehensive HIPAA Security Rule controls
1576
+ - Maintain detailed audit logs for all PHI access
1577
+ - Use encryption for data at rest and in transit
1578
+ - Implement role-based access control (RBAC)
1579
+ - Regular security risk assessments
1580
+
1581
+ ### 2. Interoperability
1582
+ - Follow HL7 FHIR standards for data exchange
1583
+ - Implement standard terminologies (SNOMED, LOINC, ICD)
1584
+ - Support multiple exchange protocols (HL7 v2, FHIR, CDA)
1585
+ - Validate all incoming and outgoing messages
1586
+ - Maintain mapping tables for code systems
1587
+
1588
+ ### 3. Data Security
1589
+ - Implement defense in depth strategy
1590
+ - Use secure key management systems
1591
+ - Regular security audits and penetration testing
1592
+ - Implement data loss prevention (DLP) measures
1593
+ - Maintain business associate agreements (BAAs)
1594
+
1595
+ ### 4. Clinical Safety
1596
+ - Implement clinical decision support carefully
1597
+ - Validate all medical calculations
1598
+ - Maintain drug interaction databases
1599
+ - Implement allergy checking
1600
+ - Provide clear audit trails for clinical decisions
1601
+
1602
+ ### 5. Performance & Reliability
1603
+ - Design for high availability (99.99% uptime)
1604
+ - Implement disaster recovery procedures
1605
+ - Use caching for frequently accessed data
1606
+ - Optimize database queries for large datasets
1607
+ - Implement proper backup and recovery
1608
+
1609
+ ## Common Patterns
1610
+
1611
+ 1. **Audit Trail**: Comprehensive logging of all PHI access
1612
+ 2. **Break Glass**: Emergency access procedures with extra auditing
1613
+ 3. **Consent Management**: Patient consent tracking and enforcement
1614
+ 4. **Master Patient Index**: Patient identity management and matching
1615
+ 5. **Clinical Repository**: Centralized storage for clinical data
1616
+ 6. **Terminology Services**: Code system mapping and validation
1617
+ 7. **Order Entry**: Computerized physician order entry (CPOE)
1618
+ 8. **Results Routing**: Laboratory and imaging result distribution
1619
+
1620
+ Remember: Healthcare technology requires extreme attention to patient safety, data privacy, and regulatory compliance. Always consult with clinical, legal, and compliance teams when implementing healthcare systems.