{"_id":"@0xlucasliao/techops-sidecar","_rev":"2-38d5a7ae2ee05a7be996e9f2e9e98b46","name":"@0xlucasliao/techops-sidecar","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@0xlucasliao/techops-sidecar","version":"1.0.0","keywords":["techops","sidecar","health-check","telegram","0xlucasliao"],"license":"MIT","_id":"@0xlucasliao/techops-sidecar@1.0.0","maintainers":[{"name":"0xlucasliao","email":"lucas.liao@11a0.com"}],"homepage":"https://github.com/0xlucasliao/techops-sidecar#readme","bugs":{"url":"https://github.com/0xlucasliao/techops-sidecar/issues"},"bin":{"techops-sidecar":"bin/techops-sidecar.js"},"dist":{"shasum":"cc5f8bdf4decbb384a21fb903a00fe49d94f0879","tarball":"https://registry.npmjs.org/@0xlucasliao/techops-sidecar/-/techops-sidecar-1.0.0.tgz","fileCount":12,"integrity":"sha512-SAPRvptG5Rmkpuj+mxqkAGmE2q5rQe1GxIz0vWNvHvf30/KSB2cu3F7DKcFdb9WU/e/AxSfhQ5kQcObdHYY5EA==","signatures":[{"sig":"MEUCIQDD5DWR61lulN9feOHn2gSLB0M9nb0yp8bDX2CjAztvxgIgI39VFu/5BTqQjEJHcus8VgXqf2bjPu5mPU+73T+93QU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":24009},"type":"module","engines":{"node":">=18.18.0"},"gitHead":"986dca854c0d4598e48fc2b8cc15c666d46da996","scripts":{"test":"node --test test/*.test.js","start":"node bin/techops-sidecar.js"},"_npmUser":{"name":"0xlucasliao","email":"lucas.liao@11a0.com"},"repository":{"url":"git+https://github.com/0xlucasliao/techops-sidecar.git","type":"git"},"_npmVersion":"10.9.2","description":"TechOps runtime sidecar: health checks, daily heartbeat, and structured log ERROR alerts to Telegram.","directories":{},"_nodeVersion":"23.7.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/techops-sidecar_1.0.0_1777308518162_0.7362917298300764","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@0xlucasliao/techops-sidecar","version":"1.0.1","description":"TechOps runtime sidecar: health checks, daily heartbeat, and structured log ERROR alerts to Telegram.","type":"module","engines":{"node":">=18.18.0"},"bin":{"techops-sidecar":"bin/techops-sidecar.js"},"scripts":{"start":"node bin/techops-sidecar.js","test":"node --test test/*.test.js"},"keywords":["techops","sidecar","health-check","telegram","0xlucasliao"],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/0xlucasliao/techops-sidecar.git"},"publishConfig":{"access":"public"},"_id":"@0xlucasliao/techops-sidecar@1.0.1","gitHead":"9219c577dc0df39f2406aacf8c174ee91b7ddcf8","bugs":{"url":"https://github.com/0xlucasliao/techops-sidecar/issues"},"homepage":"https://github.com/0xlucasliao/techops-sidecar#readme","_nodeVersion":"23.7.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-/y5/8G3z19lgRqburAWxNiGzhW3R2LQ0QmetApButfBLr/ChhbTrT58Zm3A1mAFFmC/2ZRI0yETNr8wguqq1sg==","shasum":"38aa666eddc4f13104252e581a24bc957f500847","tarball":"https://registry.npmjs.org/@0xlucasliao/techops-sidecar/-/techops-sidecar-1.0.1.tgz","fileCount":12,"unpackedSize":25286,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGMEumkewqLkndTFG0FYl6dn7kxVGsurNo3cj8krgDvgAiBEKrqjeYaZs+FfM3FybiTuYk/TFiuoLISZ/21uUrjU+g=="}]},"_npmUser":{"name":"0xlucasliao","email":"lucas.liao@11a0.com"},"directories":{},"maintainers":[{"name":"0xlucasliao","email":"lucas.liao@11a0.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/techops-sidecar_1.0.1_1777309419830_0.970043608464987"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-27T16:48:38.084Z","modified":"2026-04-27T17:03:40.143Z","1.0.0":"2026-04-27T16:48:38.301Z","1.0.1":"2026-04-27T17:03:40.032Z"},"bugs":{"url":"https://github.com/0xlucasliao/techops-sidecar/issues"},"license":"MIT","homepage":"https://github.com/0xlucasliao/techops-sidecar#readme","keywords":["techops","sidecar","health-check","telegram","0xlucasliao"],"repository":{"type":"git","url":"git+https://github.com/0xlucasliao/techops-sidecar.git"},"description":"TechOps runtime sidecar: health checks, daily heartbeat, and structured log ERROR alerts to Telegram.","maintainers":[{"name":"0xlucasliao","email":"lucas.liao@11a0.com"}],"readme":"# @0xlucasliao/techops-sidecar\n\nRuntime monitoring sidecar for TechOps-managed services. It aligns with **SOP-OPS-STACK-001** (health + structured logs + Telegram alerting): polls a health URL, sends a daily **UTC midnight** heartbeat, tails `/logs/<SERVICE_NAME>/app.log`, and on `[ERROR]` lines bundles logs by `SESSION_ID` and sends a `.txt` to Telegram.\n\n## Install and run\n\n```bash\nnpx --yes @0xlucasliao/techops-sidecar\n# or after npm install:\nnpx techops-sidecar\n```\n\n## Required environment variables\n\n| Variable | Description |\n|----------|-------------|\n| `HEALTH_CHECK_URL` | HTTP(S) URL the sidecar `GET`s on each interval (2xx = success). |\n| `TELEGRAM_BOT_TOKEN` | Bot token from [@BotFather](https://t.me/BotFather). |\n| `TELEGRAM_CHAT_ID` | Target chat or group ID (supergroups are often negative; use the full ID string). |\n| `SERVICE_NAME` | Service id; default log path is `/logs/<SERVICE_NAME>/app.log`. |\n\nOptional `TECHOPS_*` aliases are supported for the same values (see `src/config.js`).\n\n## Optional environment variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `ENVIRONMENT` | `unknown` | Shown in alerts (e.g. `production`). |\n| `RUNBOOK_URL` | _(empty)_ | Included in alert text when set (SOP recommends it). |\n| `LOG_FILE_PATH` | `/logs/<SERVICE_NAME>/app.log` | Override log file path. |\n| `HEALTH_CHECK_INTERVAL_MS` | `30000` | Health poll interval. |\n| `HEALTH_CONSECUTIVE_FAILURES` | `5` | Failed pings in a row before Telegram alert. |\n| `HEALTH_REQUEST_TIMEOUT_MS` | `10000` | Per-request timeout. |\n| `LOG_BUNDLE_WINDOW_MS` | `30000` | After first `[ERROR]` for a `SESSION_ID`, collect same-session lines for this long, then send the bundle. |\n| `MAX_ALERTS_PER_MINUTE` | `5` | Cap on Telegram sends per rolling minute (health + log alerts combined). |\n| `ALERT_DEDUP_TTL_MS` | `120000` | Suppress repeats with the same dedupe signature. |\n\n## GitHub Actions → container env\n\nStore secrets per repository (or per environment), then map them in the deploy workflow:\n\n```yaml\nenv:\n  HEALTH_CHECK_URL: ${{ secrets.HEALTH_CHECK_URL }}\n  TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}\n  TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}\n  SERVICE_NAME: my-service\n  ENVIRONMENT: production\n  RUNBOOK_URL: https://wiki.example.com/runbooks/my-service\n```\n\n## Docker (multi-stage pattern)\n\nInstall the package in the image and run the binary next to your app. Share a read-only volume for logs per SOP (`/logs/<service-name>/app.log`).\n\n```dockerfile\nFROM node:22-bookworm-slim AS sidecar\nRUN npm install -g @0xlucasliao/techops-sidecar@^1.0.0\n\nFROM your-app-base\nCOPY --from=sidecar /usr/local/lib/node_modules/@0xlucasliao/techops-sidecar /opt/techops-sidecar\nENV PATH=\"/opt/techops-sidecar/node_modules/.bin:${PATH}\"\n# Or: node /opt/techops-sidecar/.../bin/techops-sidecar.js\n\n# Your app writes logs here; sidecar reads read-only.\nVOLUME [\"/logs/my-service\"]\n\n# Example: supervisor or shell starts both processes.\n```\n\nUsing `npx` at **runtime** (slower cold start, always latest):\n\n```dockerfile\nRUN npm install -g npm@latest\n# CMD runs your app; start sidecar with:\n# npx --yes @0xlucasliao/techops-sidecar\n```\n\n### Full sample (app + sidecar + GitHub Secrets)\n\nRunnable reference in **`examples/`**:\n\n| File | Purpose |\n|------|---------|\n| `examples/Dockerfile.app-with-sidecar` | Installs `@0xlucasliao/techops-sidecar`, copies a tiny sample app, starts **sidecar then app** via entrypoint. |\n| `examples/docker-entrypoint.sh` | Runs `techops-sidecar` in the background, **`exec`** your main process in the foreground. |\n| `examples/sample-app/server.mjs` | Placeholder app with `/health` and structured logs under `/logs/<SERVICE_NAME>/app.log`. |\n| `examples/github-actions.deploy.sample.yml` | Build **without** secrets; `docker run` **with** `-e` from `${{ secrets.* }}`. |\n\nBuild locally:\n\n```bash\ndocker build -f examples/Dockerfile.app-with-sidecar -t myapp:with-sidecar .\ndocker run --rm -p 3000:3000 \\\n  -e SERVICE_NAME=demo-service \\\n  -e ENVIRONMENT=local \\\n  -e TELEGRAM_BOT_TOKEN=\"your-token\" \\\n  -e TELEGRAM_CHAT_ID=\"your-chat-id\" \\\n  -e HEALTH_CHECK_URL=\"http://127.0.0.1:3000/health\" \\\n  myapp:with-sidecar\n```\n\n**Secrets rule of thumb:** define them in **GitHub → Settings → Secrets and variables → Actions**, reference them only in workflow **`env:`** or **`docker run -e ...`**, never as `docker build --build-arg` for tokens (they can remain in image history).\n\n## Log format (mandatory for ERROR bundling)\n\nLines must match:\n\n```text\n[TIMESTAMP] [LEVEL] [SERVICE] [SESSION_ID] MESSAGE\n```\n\nExample:\n\n```text\n2026-04-27T14:23:01Z [ERROR] payment-gateway sess-8f2a1c3e Connection to upstream failed: timeout after 30s\n```\n\n## Behaviour summary\n\n1. **Health** — `GET` `HEALTH_CHECK_URL` every `HEALTH_CHECK_INTERVAL_MS`. After `HEALTH_CONSECUTIVE_FAILURES` consecutive failures, sends one Telegram message (subject to rate limit + dedupe). Counter resets when a request succeeds.\n2. **Daily heartbeat** — Every **00:00:00 UTC**, sends an “I’m alive” style message.\n3. **Logs** — Tails the log file from EOF (no backlog replay on restart). On `[ERROR]`, waits `LOG_BUNDLE_WINDOW_MS` and includes all parsed lines with the same `SESSION_ID` seen in that window, then sends a UTF-8 `.txt` document plus caption.\n\n## Development\n\n```bash\nnpm test\n```\n\n## Licence\n\nMIT\n","readmeFilename":"README.md"}