A comprehensive integration service that connects Notion with OpenSpec, enabling AI-powered specification management, validation, and collaboration workflows.
This service enables teams to create, manage, version, and collaborate on technical specifications directly within Notion, while leveraging OpenSpec's AI capabilities for intelligent spec generation, validation, and optimization.
- AI-Powered Specification Generation: Generate comprehensive specifications from minimal input using OpenSpec AI
- Automated Validation: Validate specifications against organizational standards with detailed scoring and feedback
- Version Control: Track all specification changes with complete audit trails and rollback capabilities
- Collaborative Review Workflows: Enable team collaboration with structured review and approval processes
- Notion Integration: Seamless two-way sync with Notion databases
- RESTful API: Complete REST API for all operations with authentication and rate limiting
┌─────────────────────────────────────────────────────────────────┐
│ Notion Workspace │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Database: Specifications │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
▲
│ Notion API (REST)
│
┌─────────────────────────────────────────────────────────────────┐
│ NOS Integration Service │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────┐ │
│ │ API Gateway │ │ Validation │ │ Version │ │
│ │ (Express.js) │ │ Engine │ │ Manager │ │
│ └──────────────────┘ └──────────────────┘ └──────────────┘ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Notion Adapter │ │ OpenSpec Client │ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
▲ ▲
│ Notion API │ OpenSpec API
│ │
┌────────────┐ ┌──────────────┐
│ Notion │ │ OpenSpec │
│ Cloud │ │ Service │
└────────────┘ └──────────────┘
- Runtime: Node.js 20+
- Language: TypeScript 5+
- Framework: Express.js
- API Integrations: Notion API, OpenSpec API
- Caching (Optional): Redis
- Database (Optional): PostgreSQL for audit logs
- Containerization: Podman (rootless, daemonless) - Docker compatible
- Testing: Jest
- Node.js 20+ and npm 10+
- Podman (recommended) or Docker (for containerized deployment)
- Podman provides rootless, daemonless containers for enhanced security
- Install from: https://podman.io/getting-started/installation
- Install podman-compose:
pip3 install podman-compose
- Notion workspace with API integration token
- OpenSpec API credentials (optional - fallback validation available)
-
Clone the repository
git clone https://github.com/your-org/notion-openspec-integration.git cd notion-openspec-integration -
Install dependencies
npm install
-
Configure environment variables
cp .env.example .env # Edit .env and add your API tokens and configuration -
Required Configuration
NOTION_API_TOKEN: Your Notion integration tokenNOTION_DATABASE_ID: ID of your Notion specifications databaseOPENSPEC_API_TOKEN: Your OpenSpec API token (optional)JWT_SECRET: Secret key for JWT authentication (change in production!)
Development mode with auto-reload:
npm run devBuild and run production:
npm run build
npm startRun tests:
npm testRun with coverage:
npm run test -- --coveragePodman provides enhanced security with:
- Rootless containers: No daemon running as root
- Daemonless architecture: Direct fork/exec model
- Drop-in Docker replacement: Compatible with Docker commands
- Better security: No single point of failure, reduced attack surface
Using Make commands (easiest):
# Check dependencies
make check-deps
# Build and start all services
make quick-start
# View logs
make logs
# Stop services
make down
# Restart everything
make quick-restart
# See all available commands
make helpUsing podman-compose directly:
# Start all services
podman-compose up -d
# View logs
podman-compose logs -f app
# Stop services
podman-compose down
# Rebuild after code changes
podman-compose up -d --buildUsing Podman directly (without compose):
# Build image
podman build -f Containerfile -t nos-integration:latest .
# Run container
podman run -d \
--name nos-integration \
-p 3000:3000 \
--env-file .env \
nos-integration:latest
# View logs
podman logs -f nos-integration
# Stop container
podman stop nos-integrationIf you prefer Docker over Podman:
# Use docker-compose.yml instead
docker-compose up -d
docker-compose logs -f app
docker-compose downNote: Dockerfile is maintained for Docker compatibility, but Containerfile is recommended for Podman.
http://localhost:3000/api/v1
All endpoints (except /health and /health/*) require authentication via JWT token:
Authorization: Bearer <your_jwt_token>
GET /healthReturns system health status including Notion API, OpenSpec API, and database connectivity.
POST /specifications
Content-Type: application/json
Authorization: Bearer <token>
{
"title": "User Authentication Feature",
"spec_type": "Feature",
"overview": "Implement secure user authentication...",
"priority": "P0",
"tags": ["security", "authentication"]
}POST /specifications/generate
Content-Type: application/json
Authorization: Bearer <token>
{
"feature_overview": "We need a user authentication system that supports email/password and OAuth providers...",
"goals": ["Secure authentication", "Social login support"],
"constraints": ["Must comply with GDPR"],
"spec_type": "Feature"
}POST /specifications/:spec_id/validate
Content-Type: application/json
Authorization: Bearer <token>
{
"ignore_cache": false
}GET /specifications/:spec_id
Authorization: Bearer <token>PUT /specifications/:spec_id
Content-Type: application/json
Authorization: Bearer <token>
{
"title": "Updated Title",
"overview": "Updated overview..."
}GET /specifications/:spec_id/versions?limit=20&offset=0
Authorization: Bearer <token>GET /specifications/:spec_id/versions/:version_id/diff?compare_to=<previous_version_id>
Authorization: Bearer <token>POST /specifications/:spec_id/rollback
Content-Type: application/json
Authorization: Bearer <token>
{
"target_version_id": "<version_uuid>",
"reason": "Reverting unintended changes"
}See .env.example for all available configuration options.
NODE_ENV: Environment (development/production)PORT: Server port (default: 3000)SERVICE_URL: Public service URL
NOTION_API_TOKEN: Notion integration token (required)NOTION_DATABASE_ID: Notion database ID (required)OPENSPEC_API_TOKEN: OpenSpec API token (optional)
AI_GENERATION_ENABLED: Enable/disable AI generation (default: true)AUTO_VALIDATION_ENABLED: Enable/disable auto-validation (default: true)VERSION_HISTORY_ENABLED: Enable/disable version tracking (default: true)REVIEW_WORKFLOW_ENABLED: Enable/disable review workflows (default: false)
JWT_SECRET: Secret for JWT token signing (change in production!)JWT_EXPIRY: Token expiration time (default: 1h)
RATE_LIMIT_WINDOW_MS: Rate limit window in millisecondsRATE_LIMIT_MAX_REQUESTS: Max requests per window
.
├── src/
│ ├── adapters/ # External service adapters
│ │ ├── notion-adapter.ts
│ │ └── openspec-client.ts
│ ├── api/ # API route handlers
│ │ ├── specifications.ts
│ │ ├── generation.ts
│ │ └── health.ts
│ ├── components/ # Core business logic
│ │ ├── validation-engine.ts
│ │ └── version-manager.ts
│ ├── config/ # Configuration management
│ │ └── index.ts
│ ├── middleware/ # Express middleware
│ │ ├── auth.ts
│ │ ├── error-handler.ts
│ │ ├── rate-limit.ts
│ │ └── request-logger.ts
│ ├── models/ # Data models (future)
│ ├── types/ # TypeScript type definitions
│ │ └── index.ts
│ ├── utils/ # Utility functions
│ │ ├── errors.ts
│ │ ├── logger.ts
│ │ ├── retry.ts
│ │ └── validators.ts
│ └── server.ts # Main application entry point
├── .env.example # Environment variables template
├── .gitignore
├── Dockerfile # Docker container definition
├── docker-compose.yml # Multi-container Docker setup
├── jest.config.js # Jest test configuration
├── package.json # Dependencies and scripts
├── README.md # This file
├── SPECIFICATION.md # Detailed specification document
└── tsconfig.json # TypeScript configuration
This project uses ESLint for code linting:
npm run lint
npm run lint:fixRun tests with coverage:
npm test
npm run test -- --coverageWatch mode for development:
npm run test:watchCompile TypeScript to JavaScript:
npm run buildThe compiled output will be in the dist/ directory.
Rootless Production Deployment:
-
Build the container image:
make build # or podman build -f Containerfile -t nos-integration:latest .
-
Run with podman-compose:
make up # or podman-compose up -d -
Enable systemd for auto-start (rootless):
make enable-systemd
This creates user-level systemd services that start on user login.
-
Check service health:
make health
Security Features Enabled:
- ✅ Rootless containers (no root daemon)
- ✅ Non-root user inside container (UID 1000)
- ✅ No new privileges flag
- ✅ Read-only root filesystem where possible
- ✅ Temporary filesystems with noexec, nosuid
- ✅ SELinux labels on volumes (:Z flag)
- ✅ Security scanning with
make scan
-
Build the Docker image:
docker build -f Dockerfile -t nos-integration:latest . -
Run with Docker Compose:
docker-compose up -d
-
Container Security:
- Use Podman rootless mode in production
- Regularly scan images:
make scan - Keep base images updated
- Use specific image tags, not :latest
-
Environment Variables: Never commit
.envfiles. Use secrets management. -
JWT Secret: Generate a strong random secret for production
openssl rand -base64 32
-
API Tokens: Rotate Notion and OpenSpec tokens regularly (90 days recommended)
-
HTTPS: Always use HTTPS in production (reverse proxy with Caddy/nginx)
-
Rate Limiting: Adjust rate limits based on your usage patterns
-
Monitoring: Set up monitoring and alerting (Datadog, CloudWatch, etc.)
-
Logging: Configure centralized logging for production
-
Backups:
- Notion serves as the source of truth
- Backup volumes:
make backup-volumes - Consider backing up audit logs
-
Systemd Integration (Podman only):
# Generate and enable systemd service make enable-systemd # Check status systemctl --user status container-nos-integration.service # Enable linger for non-logged-in user loginctl enable-linger $USER
1. Notion API Connection Failed
- Verify your
NOTION_API_TOKENis correct - Ensure the integration has access to your database
- Check that
NOTION_DATABASE_IDmatches your database
2. OpenSpec API Not Available
- The service will fall back to local validation if OpenSpec is unavailable
- Check
OPENSPEC_API_TOKENis valid - Verify
OPENSPEC_API_URLis correct
3. Rate Limiting Issues
- Adjust
RATE_LIMIT_WINDOW_MSandRATE_LIMIT_MAX_REQUESTS - Consider implementing user-specific rate limits
- Check if multiple instances are sharing the same rate limiter
4. Authentication Errors
- Ensure JWT tokens are properly formatted
- Check
JWT_SECRETmatches between token generation and verification - Verify token hasn't expired
5. Podman-Specific Issues
- Port binding errors: Rootless Podman can't bind to ports < 1024 without configuration
- Volume permissions: Use
:Zflag for SELinux systems:-v ./data:/data:Z - Network connectivity: Check with
podman network inspect nos-network - See PODMAN.md for detailed Podman troubleshooting
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
For issues and questions:
- Review the SPECIFICATION.md for detailed requirements
- Check existing GitHub issues
- Create a new issue with detailed information
See SPECIFICATION.md Section 20: Future Considerations for planned features including:
- Real-time Notion webhooks integration
- Advanced analytics dashboard
- Specification templates library
- Custom validation rules builder
- Mobile app support
- Multi-workspace federation
- Built with Notion API
- AI-powered by OpenSpec
- See SPECIFICATION.md for complete project documentation