{"_id":"@cisco_open/linting-reports","_rev":"3-e302e54183360d804963c7339b465b5b","name":"@cisco_open/linting-reports","dist-tags":{"latest":"1.0.0-rc.5"},"versions":{"1.0.0-rc.4":{"name":"@cisco_open/linting-reports","version":"1.0.0-rc.4","keywords":["linting","reports","api","spectral"],"author":{"name":"Cisco Systems, Inc. and its affiliates"},"license":"Apache-2.0","_id":"@cisco_open/linting-reports@1.0.0-rc.4","maintainers":[{"name":"cisco-service","email":"ospo@cisco.com"}],"homepage":"https://github.com/cisco-open/linting-orchestrator/tree/main/packages/reports#readme","bugs":{"url":"https://github.com/cisco-open/linting-orchestrator/issues"},"bin":{"spectifyr":"build/index.js"},"dist":{"shasum":"cc01398406e534f86a8bd216da4faf3d8a2d2b10","tarball":"https://registry.npmjs.org/@cisco_open/linting-reports/-/linting-reports-1.0.0-rc.4.tgz","fileCount":57,"integrity":"sha512-yrJ6vOIT2qhXDkZejCsxR17YJug6jKm2cC3xHCfHjBGG5shw+6lrGO+TIRn7W3wIOUN0sgPaAViJ1mP/cb5hOQ==","signatures":[{"sig":"MEYCIQDUGv9CQnWMjaSh3oB0B9Tz0+1sJaPso5WNMbW+LiQbCwIhAJj5HEj+6jyQ3gGRlMoXbJ7SfZZFwUjWrRbRk5mT2y6K","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cisco_open%2flinting-reports@1.0.0-rc.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":211311},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":"./build/index.js","./types":"./build/types.js","./client":"./build/client/index.js"},"gitHead":"9ce19e065db9f3e218f174005c2a8b40f3313f2c","scripts":{"dev":"NODE_ENV=development tsx src/index.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsc && npm run copy:templates && npm run copy:schema && chmod 755 build/index.js","reset":"rm -f ${DATABASE_PATH:-./reports.db} && echo '✅ Database reset complete. The database will be recreated on next server start.'","start":"DOTENV_CONFIG_QUIET=true NODE_ENV=production SPECTIFYR_DB_PATH=~/.spectify/reports/database/reports.db node build/index.js","cleanup":"tsx src/cleanup/cleanup.ts","example":"tsx examples/client-usage.ts","test:unit":"vitest run tests/unit","start:prod":"npm start","test:watch":"vitest watch","copy:schema":"mkdir -p build/schema && cp schema/schema.sql build/schema/","copy:templates":"mkdir -p build/templates && cp -r src/templates/* build/templates/","test:integration":"vitest run tests/integration"},"_npmUser":{"name":"cisco-service","email":"ospo@cisco.com"},"repository":{"url":"git+https://github.com/cisco-open/linting-orchestrator.git","type":"git","directory":"packages/reports"},"_npmVersion":"10.8.2","description":"Persistent storage and web UI for lint job results. The linting reporting service (spectifyr) receives notifications from the linting orchestrator, stores them in SQLite, and exposes a browsable web UI.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"pino":"^10.3.0","dotenv":"^17.2.3","semver":"^7.7.3","fastify":"^5.7.4","handlebars":"^4.7.8","pino-pretty":"^13.1.3","better-sqlite3":"^11.0.0","@fastify/static":"^7.0.0"},"clientVersion":"1.6.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.7.0","eslint":"^8.57.1","vitest":"^4.0.18","typescript":"^5.3.3","@types/node":"^20.11.0","@types/semver":"^7.7.1","@types/better-sqlite3":"^7.6.9","@typescript-eslint/parser":"^8.56.1","@typescript-eslint/eslint-plugin":"^8.56.1"},"_npmOperationalInternal":{"tmp":"tmp/linting-reports_1.0.0-rc.4_1782753307691_0.3613741645556381","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-rc.5":{"name":"@cisco_open/linting-reports","version":"1.0.0-rc.5","keywords":["linting","reports","api","spectral"],"author":{"name":"Cisco Systems, Inc. and its affiliates"},"license":"Apache-2.0","_id":"@cisco_open/linting-reports@1.0.0-rc.5","maintainers":[{"name":"cisco-service","email":"ospo@cisco.com"}],"homepage":"https://github.com/cisco-open/linting-orchestrator/tree/main/packages/reports#readme","bugs":{"url":"https://github.com/cisco-open/linting-orchestrator/issues"},"bin":{"spectifyr":"build/index.js"},"dist":{"shasum":"7b20526f478f6b7531faeea5032c2476bda00b19","tarball":"https://registry.npmjs.org/@cisco_open/linting-reports/-/linting-reports-1.0.0-rc.5.tgz","fileCount":57,"integrity":"sha512-kWXxtuw5HDN/2HQUifmkrKVUKWaD7/m3jir9IBBgLXuE3ezrluGvRfVudBdBZ4EayF4wUG29yC51Uj1PLXw0Cg==","signatures":[{"sig":"MEUCIQCFN0Sig/PAFvbvCBqLQ0iOm6kAGlShmXDsUhgZ5s5YaAIgGEylN8hmM7goyJ9jk5951zRzSphkyrFw16JWJtrx4yo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cisco_open%2flinting-reports@1.0.0-rc.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":211311},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":"./build/index.js","./types":"./build/types.js","./client":"./build/client/index.js"},"gitHead":"0c27893acf02d46658817715238fec3310889b5a","scripts":{"dev":"NODE_ENV=development tsx src/index.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsc && npm run copy:templates && npm run copy:schema && chmod 755 build/index.js","reset":"rm -f ${DATABASE_PATH:-./reports.db} && echo '✅ Database reset complete. The database will be recreated on next server start.'","start":"DOTENV_CONFIG_QUIET=true NODE_ENV=production SPECTIFYR_DB_PATH=~/.spectify/reports/database/reports.db node build/index.js","cleanup":"tsx src/cleanup/cleanup.ts","example":"tsx examples/client-usage.ts","test:unit":"vitest run tests/unit","start:prod":"npm start","test:watch":"vitest watch","copy:schema":"mkdir -p build/schema && cp schema/schema.sql build/schema/","copy:templates":"mkdir -p build/templates && cp -r src/templates/* build/templates/","test:integration":"vitest run tests/integration"},"_npmUser":{"name":"cisco-service","email":"ospo@cisco.com"},"repository":{"url":"git+https://github.com/cisco-open/linting-orchestrator.git","type":"git","directory":"packages/reports"},"_npmVersion":"10.8.2","description":"Persistent storage and web UI for lint job results. The linting reporting service (spectifyr) receives notifications from the linting orchestrator, stores them in SQLite, and exposes a browsable web UI.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"pino":"^10.3.0","dotenv":"^17.2.3","semver":"^7.7.3","fastify":"^5.7.4","handlebars":"^4.7.8","pino-pretty":"^13.1.3","better-sqlite3":"^11.0.0","@fastify/static":"^7.0.0"},"clientVersion":"1.6.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.7.0","eslint":"^8.57.1","vitest":"^4.0.18","typescript":"^5.3.3","@types/node":"^20.11.0","@types/semver":"^7.7.1","@types/better-sqlite3":"^7.6.9","@typescript-eslint/parser":"^8.56.1","@typescript-eslint/eslint-plugin":"^8.56.1"},"_npmOperationalInternal":{"tmp":"tmp/linting-reports_1.0.0-rc.5_1782831390854_0.46700540167318616","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-06-29T17:15:07.575Z","modified":"2026-07-31T11:00:31.326Z","1.0.0-rc.4":"2026-06-29T17:15:07.847Z","1.0.0-rc.5":"2026-06-30T14:56:31.008Z"},"bugs":{"url":"https://github.com/cisco-open/linting-orchestrator/issues"},"author":{"name":"Cisco Systems, Inc. and its affiliates"},"license":"Apache-2.0","homepage":"https://github.com/cisco-open/linting-orchestrator/tree/main/packages/reports#readme","keywords":["linting","reports","api","spectral"],"repository":{"url":"git+https://github.com/cisco-open/linting-orchestrator.git","type":"git","directory":"packages/reports"},"description":"Persistent storage and web UI for lint job results. The linting reporting service (spectifyr) receives notifications from the linting orchestrator, stores them in SQLite, and exposes a browsable web UI.","maintainers":[{"email":"ospo@cisco.com","name":"cisco-service"},{"email":"steve.sfartz@gmail.com","name":"objectisadvantag"}],"readme":"# Linting Reporting Service (`spectifyr`)\n\n> Package: `@cisco_open/linting-reports`\n> Binary: `spectifyr`\n\nThe **linting reporting service** stores lint job results\nproduced by the [linting orchestrator](https://github.com/cisco-open/linting-orchestrator)\nand exposes them through a browsable web UI. *Linting Reports* is the\nuser-facing label of this service; on the command line and in\nconfiguration, it is named `spectifyr`.\n\n## What is the linting reporting service?\n\nThe linting reporting service (`spectifyr`) is a standalone companion to\nthe linting orchestrator that provides:\n\n- **Persistent Storage**: Job results survive orchestrator restarts\n- **Web UI**: Browse and search lint results in your browser\n- **Independent Operation**: Can be stopped/started without affecting the orchestrator\n- **Production-Ready**: Never lose reports with local backup and retry logic\n\n## Features\n\n- ✅ HTTP API for receiving job notifications from the linting orchestrator\n- ✅ SQLite database for persistent storage\n- ✅ API key authentication (Bearer token)\n- ✅ Job listing with filtering and pagination\n- ✅ Detailed job results API\n- ✅ Health check endpoint with version info\n- ✅ **Web UI** - Browse reports in your browser (Phase 3)\n- ✅ **Manual cleanup CLI** - Delete old reports (Phase 4)\n- ✅ Reusable TypeScript client library with retry logic\n- ✅ Runtime version compatibility checking\n- ✅ Payload validation before sending\n- 🚧 PostgreSQL support (future)\n- 🚧 Charts and trends (future)\n\n## Project Structure\n\nThis is a **monorepo** containing both the reports service server and a reusable TypeScript client library for integrating with it:\n\n```\nlinting-reports/\n├── src/\n│   ├── server/               # spectifyr HTTP server\n│   ├── client/               # Reusable TypeScript client library\n│   │   └── CHANGELOG.md      # Detailed client library changelog\n│   └── types.ts              # Shared TypeScript types\n├── docs/\n│   ├── SPECTIFYR_ARCHITECTURE.md\n│   └── VERSIONING_STRATEGY.md\n├── CHANGELOG.md              # Server changelog (references client)\n├── package.json              # Dual versions (server + client)\n└── README.md                 # This file\n```\n\n### Versioning & Changelogs\n\nWe use **dual versioning** to independently track server and client library versions:\n\n- **Server Version**: `package.json` → `version` field (e.g., `0.2.2`)\n  - Changes tracked in root **[CHANGELOG.md](CHANGELOG.md)**\n  - Server-specific features (endpoints, database, health checks)\n\n- **Client Library Version**: `package.json` → `clientVersion` field (e.g., `1.0.0`)\n  - Changes tracked in **[src/client/CHANGELOG.md](src/client/CHANGELOG.md)**\n  - Client API, configuration options, bug fixes\n\n**Where to Find What:**\n- **Server changes** → [CHANGELOG.md](CHANGELOG.md) (high-level summaries)\n- **Client library changes** → [src/client/CHANGELOG.md](src/client/CHANGELOG.md) (detailed API docs)\n- **Versioning rules** → [docs/internal/versioning-strategy.md](docs/internal/versioning-strategy.md)\n\nThis allows the server to evolve (adding endpoints, database changes) without forcing client library version bumps when the client API hasn't changed.\n\n## Quick Start\n\n### Development Mode (Recommended for Local Testing)\n\n```bash\n# Install dependencies\nnpm install\n\n# Build the project\nnpm run build\n\n# Start in development mode (no configuration needed)\nnpm run dev\n```\n\nDevelopment mode runs with sensible defaults:\n- ✅ Auto-generates API key (with warning)\n- ✅ Local database: `./reports.db`\n- ✅ Human-readable logs\n- ✅ Port 3010\n\nAccess at `http://localhost:3010`\n\n### Production Mode\n\n**1. Create `.env` file:**\n\n```bash\ncp .env.example .env\n```\n\n**2. Edit `.env` and set your API key:**\n\n```bash\n# Required\nSPECTIFYR_API_KEY=your-secure-production-key\n\n# Optional (production defaults shown)\nSPECTIFYR_PORT=3010\nSPECTIFYR_HOST=0.0.0.0\nSPECTIFYR_DB_PATH=~/.spectify/reports/database/reports.db\nLOG_LEVEL=info\nLOG_FORMAT=pretty  # or 'json' for structured logs\n```\n\n**3. Build and start:**\n\n```bash\nnpm run build\nnpm start\n```\n\nProduction mode validates all configuration and fails fast if misconfigured.\n\n### Configuration via .env File (Recommended)\n\nCreate a `.env` file in the project root:\n\n```bash\n# .env - Report Service Configuration\n\n# Required: API key for authentication\nSPECTIFYR_API_KEY=your-secret-key-here\n\n# Optional: Server configuration (defaults shown)\nSPECTIFYR_PORT=3010\nSPECTIFYR_HOST=0.0.0.0\n\n# Optional: Database location\n# Development default: ./reports.db\n# Production default: ~/.spectify/reports/database/reports.db\nSPECTIFYR_DB_PATH=~/.spectify/reports/database/reports.db\n\n# Optional: Logging\nLOG_LEVEL=info            # debug, info, warn, error\nLOG_FORMAT=pretty         # 'pretty' (human-readable) or 'json' (structured)\n```\n\n### Environment Variables\n\nAlternatively, use environment variables:\n\n```bash\nexport SPECTIFYR_API_KEY=your-secret-key-here\nexport SPECTIFYR_PORT=3010\nexport SPECTIFYR_DB_PATH=~/.spectify/reports/database/reports.db\nnpm start\n```\n\n### Configure the linting orchestrator\n\nIn the orchestrator's configuration:\n\n```yaml\n# config.yaml\nreportService:\n  enabled: true\n  url: 'http://localhost:3010'\n  apiKey: ${SPECTIFYR_API_KEY}\n  retries: 3\n  pendingDir: './pending-reports'\n```\n\nOr with environment variables:\n\n```bash\nexport SPECTIFYR_URL=http://localhost:3010\nexport SPECTIFYR_API_KEY=your-secret-key-here\n```\n\n## Usage\n\n### Web UI\n\nNavigate to `http://localhost:3010` in your browser to:\n- View recent lint jobs\n- Search by document name or organization\n- Filter by status, ruleset, or date range\n- View detailed results for each job\n- See per-ruleset breakdown\n\n### API\n\n#### POST /reports/jobs\nReceive job completion notification from the linting orchestrator (authenticated).\n\n```bash\ncurl -X POST http://localhost:3010/reports/jobs \\\n  -H \"Authorization: Bearer your-secret-key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d @job-notification.json\n```\n\n#### GET /jobs\nList all jobs (paginated).\n\n```bash\ncurl http://localhost:3010/jobs?limit=50&offset=0\n```\n\n#### GET /jobs/:jobId\nGet detailed results for specific job.\n\n```bash\ncurl http://localhost:3010/jobs/abc123\n```\n\n### Cleanup\n\nDelete reports older than N days:\n\n```bash\n# Dry run (shows what would be deleted)\nnpm run cleanup -- --days 90 --dry-run\n\n# Actually delete\nnpm run cleanup -- --days 90\n```\n\n## Architecture\n\nThe linting reporting service is designed as an independent companion to\nthe linting orchestrator:\n\n```\n┌──────────────────┐                  ┌──────────────────┐\n│  spectifyd       │ ───────────────> │  spectifyr       │\n│  (orchestrator)  │  HTTP POST       │  (reports)       │\n│  port 3003       │  notifications   │  port 3010       │\n└──────────────────┘  (fire-and-forget)        │\n                                               │\n                                               v\n                                        ┌─────────────┐\n                                        │   SQLite    │\n                                        │  Database   │\n                                        └─────────────┘\n```\n\n**Communication Pattern:**\n- Fire-and-forget HTTP POST notifications\n- 3 retry attempts with exponential backoff (1s, 2s, 4s)\n- If all retries fail, the orchestrator stores the notification locally\n- Background job retries pending notifications every 5 minutes\n- **Never lose production reports**\n\n## Deployment\n\n### Docker\n\n```bash\n# Build image\ndocker build -t linting-reports:latest .\n\n# Run container\ndocker run -d \\\n  -p 3010:3010 \\\n  -v $(pwd)/reports.db:/app/reports.db \\\n  -e SPECTIFYR_API_KEY=your-secret-key \\\n  linting-reports:latest\n```\n\n### Docker Compose\n\nSee [examples/docker-compose.yml](examples/docker-compose.yml) for running\nthe linting orchestrator and the linting reporting service\ntogether.\n\n### Systemd\n\nSee [examples/spectifyr.service](examples/spectifyr.service) for systemd configuration.\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build TypeScript\nnpm run build\n\n# Run tests\nnpm test\n\n# Development mode (auto-reload)\nnpm run dev\n\n# Type checking\nnpm run typecheck\n```\n\n## Documentation\n\n- [**Architecture**](docs/SPECTIFYR_ARCHITECTURE.md) - Complete design specification\n- [**AGENTS.md**](AGENTS.md) - AI agent instructions\n\n## Configuration Options\n\n| Environment Variable | Default | Description |\n|---------------------|---------|-------------|\n| `PORT` | `3010` | HTTP server port |\n| `HOST` | `0.0.0.0` | Bind address |\n| `DATABASE_PATH` | `./reports.db` | SQLite database file |\n| `SPECTIFYR_API_KEY` | *(required)* | API key for authentication |\n| `LOG_LEVEL` | `info` | Logging level (debug, info, warn, error) |\n| `LOG_FORMAT` | `pretty` | Log format (`json` for JSON, anything else for human-readable) |\n\n## License\n\nSee [LICENSE](LICENSE)\n\n## Related Projects\n\n- [spectify](https://github.com/cisco-open/linting-orchestrator) — the linting orchestrator (`spectifyd` daemon + `spectify` CLI)\n- [linting-document-store](https://github.com/cisco-open/linting-document-store) — the document store\n- [mcp-openapi-analysis](https://github.com/cisco-open/mcp-openapi-analysis) — MCP server for OpenAPI documents analysis\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## Support\n\n- Issues: [GitHub Issues](https://github.com/cisco-open/linting-reports/issues)\n- Documentation: [docs/](docs/)\n- Discussions: [spectify Discussions](https://github.com/cisco-open/linting-orchestrator/discussions)\n","readmeFilename":"README.md"}