{"locator":"npm:@fullstackhouse/open-mercato-health","path":"@fullstackhouse/open-mercato-health","npm":"@fullstackhouse/open-mercato-health","github":"fullstackhouse/open-mercato-health","repoPath":null,"kind":"module","type":"community","enterprise":false,"title":"Health Checks","summary":"Liveness and readiness endpoints that check the database, cache, queue, search, KMS, email and AI providers.","whenToUse":"Use when Kubernetes or a load balancer must know whether the app is up and ready to take traffic.","whenNotToUse":null,"category":"storage-infrastructure","tags":["health-check","kubernetes","probes"],"providers":[],"moduleIds":["health"],"requires":[],"replaces":[],"slotConflicts":[],"renamedFrom":[],"supersededBy":null,"alternatives":[],"status":"active","listed":true,"featured":false,"license":{"spdx":"MIT","kind":"osi","mismatch":false},"version":{"latest":"0.3.0","preview":null,"publishedAt":"2026-05-19","integrity":"sha512-ShX1+ajgxf4huku+RkCclf6ieI5fMrliABr6C4bXs46GoHRqZylTvaE/9Bovu74PhINl9GlxHwWVX1VCZx2gxQ==","installableFrom":"2026-05-24","gitRef":"9e37b05f23dba3882d814a1a3df7cc9ec0c42a91","recommended":{"0.9":null,"0.8":null,"next":null}},"identity":{"builtFrom":"verified","claimed":false,"source":"npm"},"compat":{"builtFor":{"range":"*","kind":"star","lines":["0.8","0.9","next"]},"lines":{"0.9":{"status":"broken","step":"typecheck","omVersion":"0.9.0","moduleVersion":"0.3.0","at":"2026-10-29T09:03:43Z","receipt":"r_20261029_9591e1e2ee09","since":"2026-10-29","precheck":null,"patches":[],"finding":"Typecheck failed: TS2339 Property 'path' does not exist on type '{ GET: { requireAuth: boolean; }; }'."}},"verifiedOn":[]},"anatomy":{"version":"0.3.0","coverage":"partial","counts":{"entities":0,"tables":0,"migrations":0,"routes":2,"publicRoutes":2,"aclFeatures":0,"eventsEmitted":0,"eventsConsumed":0,"backendPages":0,"frontendPages":0,"widgets":0,"workers":0,"cli":0,"aiTools":0,"aiAgents":0,"extends":0},"lists":{"aclFeatures":[],"eventsEmitted":[],"eventsConsumed":[],"env":["SMTP_HOST","SENDGRID_API_KEY","POSTMARK_API_TOKEN","RESEND_API_KEY","OPENAI_API_KEY","ANTHROPIC_API_KEY","AZURE_OPENAI_API_KEY","TENANT_DATA_ENCRYPTION_ENABLED","VAULT_ADDR","VAULT_TOKEN","QUEUE_STRATEGY","REDIS_URL","QUEUE_REDIS_URL","MEILISEARCH_HOST","SEARCH_FULLTEXT_URL","SEARCH_VECTOR_URL","QDRANT_URL","PINECONE_API_KEY"],"hosts":[],"tables":[],"publicRoutes":["GET /api/health/live","GET /api/health/ready"],"credentials":[]},"callout":"ADDS 2 ROUTES (2 PUBLIC)","diff":{"from":"0.2.3","added":{"tables":0,"routes":0,"publicRoutes":0,"aclFeatures":0,"env":[],"hosts":[]},"removed":{"tables":0,"routes":0,"aclFeatures":0}}},"signals":{"receipt":{"0.9":"broken","0.8":"untested","next":"untested"},"fit":{"0.9":"ok","0.8":"ok","next":"ok"},"anatomy":"partial","supplyChain":{"status":"ok","reasons":[]},"hygiene":{"status":"ok","failing":[]},"maintenance":{"status":"current","lastRelease":"2026-05-19","catchUpDays":null},"declaredVsObserved":{"status":"mismatch","notes":["Built for 0.8, 0.9, next; verified on no line."]}},"tier":"listed","quality":null,"agentPolicy":{"0.9":{"decision":"refuse","reasons":[{"code":"BROKEN","text":"Broken at typecheck on 0.9 since 29 Oct."},{"code":"THIRD_PARTY","text":"Third-party code runs with access to all tenants' data."}]},"0.8":{"decision":"ask","reasons":[{"code":"THIRD_PARTY","text":"Third-party code runs with access to all tenants' data."},{"code":"NOT_VERIFIED","text":"Not yet tested in a new app on 0.8."}],"consentText":"Install @fullstackhouse/open-mercato-health@0.3.0"},"next":{"decision":"ask","reasons":[{"code":"THIRD_PARTY","text":"Third-party code runs with access to all tenants' data."},{"code":"NOT_VERIFIED","text":"Not yet tested in a new app on next."}],"consentText":"Install @fullstackhouse/open-mercato-health@0.3.0"}},"install":{"cli":"yarn mercato module add @fullstackhouse/open-mercato-health@0.3.0 --allow-third-party","cmm":"npx create-mercato-module install @fullstackhouse/open-mercato-health@0.3.0","needsAllowThirdParty":true,"moduleFlag":null},"stats":{"downloads30d":4958,"stars":0},"sigil":{"glyph":"0200000","phase":315,"publicRoutes":true},"links":{"page":"https://modules.openmercato.com/m/@fullstackhouse/open-mercato-health","md":"https://modules.openmercato.com/m/@fullstackhouse/open-mercato-health.md","json":"https://modules.openmercato.com/m/@fullstackhouse/open-mercato-health.json","facts":"https://modules.openmercato.com/m/@fullstackhouse/open-mercato-health/v/0.3.0/facts.json","npm":"https://www.npmjs.com/package/@fullstackhouse/open-mercato-health","repo":"https://github.com/fullstackhouse/open-mercato-health","docs":null},"addedAt":"2026-10-23","updatedAt":"2026-10-29T09:22:28Z","_meta":{"com.openmercato.modules/installable":{"0.9":"0.3.0","0.8":"0.3.0","next":"0.3.0"}},"facts":{"factsVersion":1,"extractor":{"engine":"@open-mercato/cli@0.9.0 extractModuleFacts","factsContractVersion":2,"catalog":"om-modules rentgen 1","durationMs":19},"package":{"locator":"npm:@fullstackhouse/open-mercato-health","name":"@fullstackhouse/open-mercato-health","version":"0.3.0","integrity":"sha512-ShX1+ajgxf4huku+RkCclf6ieI5fMrliABr6C4bXs46GoHRqZylTvaE/9Bovu74PhINl9GlxHwWVX1VCZx2gxQ==","source":"npm-tarball","gitRef":"9e37b05f23dba3882d814a1a3df7cc9ec0c42a91"},"gate":{"installable":true,"needsModuleFlag":false,"reason":null,"modules":[{"id":"health","src":true,"dist":true}]},"kind":"module","license":{"value":"MIT","kind":"osi","mismatch":false,"sources":{"packageJson":"MIT","licenseFile":null,"moduleInfo":"MIT","integrationTs":null}},"omPeers":{"@open-mercato/cache":"*","@open-mercato/shared":"*"},"dependencies":{},"agentsMd":false,"readmeExcerpt":"# @fullstackhouse/open-mercato-health\n\nHealth check endpoints for Open Mercato applications. Provides Kubernetes-style liveness and readiness probes with configurable service checks.\n\n## Installation\n\n```bash\nnpm install @fullstackhouse/open-mercato-health\n```\n\n## Quick Start\n\n### Next.js App Router\n\n```typescript\n// app/api/health/live/route.ts\nimport { createNextHealthHandlers } from '@fullstackhouse/open-mercato-health/integrations/nextjs'\n\nconst handlers = createNextHealthHandlers(async () => {\n  const { createRequestContainer } = await import('@open-mercato/shared/lib/di/container')\n  return createRequestContainer()\n})\nexport const GET = handlers.live\n\n// app/api/health/ready/route.ts\nexport const GET = handlers.ready\nexport const dynamic = 'force-dynamic'\n```\n\n> **Why the lazy loader?** Under Turbopack production builds, a static top-level\n> `import { createRequestContainer }` can be captured as `undefined` inside the\n> handler closure, causing `getContainer is not a function` at runtime. Passing\n> a `() => import(...)` loader defers module resolution until request time and\n> sidesteps the bug. The same pattern applies to `createNextReadyHandler`.\n\n## Endpoints\n\n### Liveness (`GET /api/health/live`)\n\nReturns `ok` with HTTP 200. No dependencies are checked - this indicates the process is running.\n\n```\nHTTP/1.1 200 OK\nContent-Type: text/plain\n\nok\n```\n\n### Readiness (`GET /api/health/ready`)\n\nReturns JSON with check results. HTTP 200 when all required checks pass, 503 when any required check fails.\n\n```json\n{\n  \"status\": \"ok\",\n  \"timestamp\": \"2026-02-23T12:00:00.000Z\",\n  \"durationMs\": 18,\n  \"checks\": [\n    { \"name\": \"Database\", \"required\": true, \"status\": \"ok\", \"latencyMs\": 7, \"message\": null },\n    { \"name\": \"Cache\", \"required\": true, \"status\": \"ok\", \"latencyMs\": 2, \"message\": null },\n    { \"name\": \"Search (Fulltext)\", \"required\": false, \"status\": \"skip\", \"latencyMs\": 0, \"message\": \"Check disabled or not configured\" }\n  ]\n}\n```\n\n## Status Values\n\n| Overall Status | Description | HTTP Code |\n|----------------|-------------|-----------|\n| `ok` | All required checks pass, optional checks pass or skip | 200 |\n| `degraded` | All required checks pass, at least one optional check fails | 200 |\n| `fail` | Any required check fails | 503 |\n\n| Check Status | Description |\n|--------------|-------------|\n| `ok` | Check passed |\n| `fail` | Check failed |\n| `skip` | Check disabled or not configured |\n\n## Built-in Checks\n\n| Check | Required | Description |\n|-------|----------|-------------|\n| Database | Yes | Executes `SELECT 1` via EntityManager |\n| Cache | Yes | Performs set/get/delete cycle |\n| Queue (Redis) | No | Verifies BullMQ queue connectivity |\n| Search (Fulltext) | No | Checks Meilisearch availability |\n| Search (Vector) | No | Checks vector search provider |\n| KMS (Vault) | No | Verifies encryption service health |\n| Email Delivery | No | Checks email provider configuration |\n| AI Providers | No | Verifies AI service connectivity |\n\n## Configuration\n\nControl which checks run via environment variables:\n\n```bash\n# Enable/disable individual checks (true, false, or auto)\nHEALTH_READY_CHECK_DATABASE_ENABLED=true\nHEALTH_READY_CHECK_CACHE_ENABLED=true\nHEALTH_READY_CHECK_QUEUE_REDIS_ENABLED=auto\nHEALTH_READY_CHECK_SEARCH_FULLTEXT_ENABLED=auto\nHEALTH_READY_CHECK_SEARCH_VECTOR_ENABLED=auto\nHEALTH_READY_CHECK_KMS_ENABLED=auto\nHEALTH_READY_CHECK_EMAIL_DELIVERY_ENABLED=auto\nHEALTH_READY_CHECK_EXTERNAL_AI_PROVIDERS_ENABLED=auto\n```\n\n- `true`: Always run the check\n- `false`: Never run the check\n- `auto` (default): Run if the service is configured\n\n## Custom Checks\n\nCreate custom health check strategies by extending `BaseReadyCheckStrategy`:\n\n```typescript\nimport { BaseReadyCheckStrategy } from '@fullstackhouse/open-mercato-health'\nimport type { CheckKey, HealthContainer } from '@fullstackhouse/open-mercato-health'\n\nclass StripeReadyCheckStrategy extends BaseReadyCheckStrategy {\n  readonly id = 'STRIPE' as CheckKey\n  readonly name = 'Stripe A","modules":[{"id":"health","title":"Health","description":"Health check endpoints for liveness and readiness probes.","requires":[],"ejectable":null,"data":{"entities":[],"migrations":{"count":0,"first":null,"last":null},"customEntities":0},"http":{"routes":[{"method":"GET","path":"/api/health/live","requireAuth":false,"requireFeatures":[],"hasOpenApi":true,"src":{"file":"src/modules/health/api/get/live.ts","line":17}},{"method":"GET","path":"/api/health/ready","requireAuth":false,"requireFeatures":[],"hasOpenApi":true,"src":{"file":"src/modules/health/api/get/ready.ts","line":24}}],"legacyRouteFiles":2,"authResolved":1},"security":{"aclFeatures":[],"setupDefaultRoleFeatures":false},"events":{"emits":[],"subscribes":[]},"ui":{"backendPages":[],"frontendPages":[],"widgets":0,"extensionHosts":0},"background":{"workers":[],"cli":[]},"ai":{"tools":[],"agents":[]},"config":{"credentials":[],"env":[{"name":"SMTP_HOST","src":{"file":"src/strategies/email-delivery.ts","line":19}},{"name":"SENDGRID_API_KEY","src":{"file":"src/strategies/email-delivery.ts","line":20}},{"name":"POSTMARK_API_TOKEN","src":{"file":"src/strategies/email-delivery.ts","line":21}},{"name":"RESEND_API_KEY","src":{"file":"src/strategies/email-delivery.ts","line":22}},{"name":"OPENAI_API_KEY","src":{"file":"src/strategies/external-ai.ts","line":19}},{"name":"ANTHROPIC_API_KEY","src":{"file":"src/strategies/external-ai.ts","line":20}},{"name":"AZURE_OPENAI_API_KEY","src":{"file":"src/strategies/external-ai.ts","line":21}},{"name":"TENANT_DATA_ENCRYPTION_ENABLED","src":{"file":"src/strategies/kms.ts","line":18}},{"name":"VAULT_ADDR","src":{"file":"src/strategies/kms.ts","line":20}},{"name":"VAULT_TOKEN","src":{"file":"src/strategies/kms.ts","line":20}},{"name":"QUEUE_STRATEGY","src":{"file":"src/strategies/queue-redis.ts","line":18}},{"name":"REDIS_URL","src":{"file":"src/strategies/queue-redis.ts","line":21}},{"name":"QUEUE_REDIS_URL","src":{"file":"src/strategies/queue-redis.ts","line":21}},{"name":"MEILISEARCH_HOST","src":{"file":"src/strategies/search-fulltext.ts","line":18}},{"name":"SEARCH_FULLTEXT_URL","src":{"file":"src/strategies/search-fulltext.ts","line":18}},{"name":"SEARCH_VECTOR_URL","src":{"file":"src/strategies/search-vector.ts","line":19}},{"name":"QDRANT_URL","src":{"file":"src/strategies/search-vector.ts","line":20}},{"name":"PINECONE_API_KEY","src":{"file":"src/strategies/search-vector.ts","line":21}}]},"network":{"hosts":[],"undeclared":[]},"extends":[],"omImports":{"@open-mercato/shared":{"lib/di/container":["createRequestContainer"],"lib/openapi":["OpenApiMethodDoc","OpenApiRouteDoc"],"modules/registry":["ModuleInfo"]}},"collisionKeys":{"moduleId":"health","tables":[],"aclFeatures":[],"eventIds":[],"backendRoutes":[]},"publicRoutes":2,"glyph":"0200000","lint":[{"code":"no-agents-md","severity":"info","message":"No AGENTS.md in the package.","anchor":"g3 §3","src":null},{"code":"public-routes","severity":"info","message":"2 of 2 routes do not require authentication.","anchor":null,"src":{"file":"src/modules/health/api/get/live.ts","line":17}},{"code":"ships-tests","severity":"info","message":"The tarball ships test files.","anchor":null,"src":null},{"code":"version-drift","severity":"info","message":"ModuleInfo says 0.1.0, package.json says 0.3.0.","anchor":null,"src":{"file":"src/modules/health/index.ts","line":3}}]}],"coverage":{"routesAuthResolved":1,"integrationTs":"absent"},"diagnostics":[]},"receipts":[{"schema":1,"id":"r_20261029_9591e1e2ee09","cellKey":"9591e1e2ee09ad0c6d7a6bcc1cef601b8d3e838ce854168c9d8985cefebad00f","module":{"locator":"npm:@fullstackhouse/open-mercato-health","version":"0.3.0","integrity":"sha512-ShX1+ajgxf4huku+RkCclf6ieI5fMrliABr6C4bXs46GoHRqZylTvaE/9Bovu74PhINl9GlxHwWVX1VCZx2gxQ=="},"om":{"line":"0.9","version":"0.9.0","createApp":"create-mercato-app@0.9.0","preset":"classic"},"harness":{"version":"c349007c2b5b","node":"24.21.0","yarn":"4.17.1","runner":"ubuntu-latest","mode":"realistic","patches":[]},"baseline":{"status":"verified","receipt":"r_20261029_e5f612bd10e0"},"requiresInstalled":[],"steps":[{"name":"scaffold","status":"pass","sec":4,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"install","status":"pass","sec":67,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"add","status":"pass","sec":33,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"generate","status":"pass","sec":21,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"typecheck","status":"fail","sec":96,"signature":"5107624dd69113e88460c8714cfb6d1db2b572bd","excerpt":".mercato/generated/modules.generated.ts(4938,66): error TS2339: Property 'path' does not exist on type '{ GET: { requireAuth: boolean; }; }'.\n.mercato/generated/modules.generated.ts(4939,67): error TS2339: Property 'path' does not exist on type '{ GET: { requireAuth: boolean; }; }'.","file":".mercato/generated/modules.generated.ts","line":4938},{"name":"initialize","status":"pass","sec":43,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"build","status":"fail","sec":185,"signature":"b3f2cb5ee982754a4be5801385b4ec2077af96e9","excerpt":".mercato/generated/modules.generated.ts(4938,66): error TS2339: Property 'path' does not exist on type '{ GET: { requireAuth: boolean; }; }'.\n.mercato/generated/modules.generated.ts(4939,67): error TS2339: Property 'path' does not exist on type '{ GET: { requireAuth: boolean; }; }'.\nFailed to type check.","file":".mercato/generated/modules.generated.ts","line":4938},{"name":"start","status":"skipped","sec":null,"signature":null,"excerpt":null,"file":null,"line":null},{"name":"smoke","status":"skipped","sec":null,"signature":null,"excerpt":null,"file":null,"line":null}],"result":{"status":"broken","failedStep":"typecheck","alsoFailed":["build"],"classification":"module-fail","quarantineUntil":null},"transition":{"from":null,"to":"broken","confirmed":true},"run":{"id":40842502780,"attempt":2,"url":"https://github.com/open-mercato/modules/actions/runs/40846683223/job/123356065739","at":"2026-10-29T09:03:43Z","durationSec":505},"attestation":null}],"rules":[{"id":"LST-1","pass":true,"detail":"Descriptor is valid."},{"id":"LST-2","pass":true,"detail":"Stable version exists and is not deprecated."},{"id":"LST-3","pass":true,"detail":"src/modules and dist/modules pair found."},{"id":"LST-4","pass":true,"detail":"License: MIT."},{"id":"LST-5","pass":true,"detail":"No known malware or open critical advisory."},{"id":"LST-6","pass":true,"detail":"Name reviewed at merge."},{"id":"VER-1","pass":false,"detail":"Broken at typecheck on 0.9 since 29 Oct."},{"id":"VER-2","pass":true,"detail":"Fits statically on 0.9: ok."},{"id":"VER-3","pass":true,"detail":"Supply chain: ok."},{"id":"VER-4","pass":true,"detail":"No lint errors."},{"id":"VER-5","pass":true,"detail":"Tarball repository.url matches the descriptor."}],"maintainers":["jtomaszewski"]}
