first commit

Made-with: Cursor
This commit is contained in:
Michilis
2026-02-28 02:17:55 +00:00
commit 41f6ae916f
92 changed files with 12332 additions and 0 deletions

279
README.md Normal file
View File

@@ -0,0 +1,279 @@
# Calendar & Contacts API
A production-grade REST API for calendar management, event scheduling, contacts, availability queries, and public booking links. Built with Go, PostgreSQL, and designed for human users, AI agents, and programmatic automation.
## Features
- **Calendars** - Create, share, and manage multiple calendars with role-based access (owner/editor/viewer)
- **Events** - Full CRUD with recurring events (RFC 5545 RRULE), reminders, attendees, tags, and attachments
- **Contacts** - Personal contact management with search
- **Availability** - Query busy/free time across calendars
- **Booking Links** - Public scheduling pages with configurable working hours, duration, and buffer time
- **ICS Import/Export** - Standard iCalendar format compatibility
- **Dual Auth** - JWT tokens for interactive use, scoped API keys for agents and automation
- **Background Jobs** - Reminder notifications via Redis + Asynq (optional)
## Tech Stack
| Component | Technology |
|-----------|-----------|
| Language | Go 1.24 |
| Router | Chi |
| Database | PostgreSQL 15+ |
| Query Layer | sqlc |
| Migrations | golang-migrate |
| Auth | JWT (golang-jwt/jwt/v5) + bcrypt |
| Recurrence | rrule-go (RFC 5545) |
| Background Jobs | Asynq (Redis) |
| API Docs | OpenAPI 3.1.0 + Swagger UI |
## Quick Start
### Prerequisites
- Go 1.24+
- PostgreSQL 15+
- Redis (optional, for background reminder jobs)
### Setup
1. Clone the repository and navigate to the project directory.
2. Copy the environment file and configure it:
```bash
cp .env.example .env
```
3. Edit `.env` with your database credentials:
```env
DATABASE_URL=postgres://calendarapi:password@localhost:5432/calendarapi?sslmode=disable
JWT_SECRET=your-secret-key-change-me
SERVER_PORT=3019
ENV=development
# REDIS_ADDR=localhost:6379 # uncomment to enable background jobs
```
4. Create the database:
```bash
createdb calendarapi
```
5. Run the server (migrations run automatically on startup):
```bash
go run cmd/server/main.go
```
The server starts on `http://localhost:3019`. Swagger UI is available at `http://localhost:3019/docs`.
## API Documentation
| Resource | URL |
|----------|-----|
| Swagger UI | http://localhost:3019/docs |
| OpenAPI Spec | http://localhost:3019/openapi.json |
| LLM Reference | [llms.txt](llms.txt) |
| Agent Skill | [SKILL.md](SKILL.md) |
## Authentication
### JWT (for users)
Register or login to receive an access token (15 min) and refresh token:
```bash
# Register
curl -X POST http://localhost:3019/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "securepassword123", "timezone": "UTC"}'
# Login
curl -X POST http://localhost:3019/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "securepassword123"}'
```
Use the access token in subsequent requests:
```
Authorization: Bearer <access_token>
```
### API Keys (for agents)
Create a scoped API key for long-lived programmatic access:
```bash
curl -X POST http://localhost:3019/api-keys \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "my-agent",
"scopes": {
"calendars": ["read", "write"],
"events": ["read", "write"],
"contacts": ["read", "write"],
"availability": ["read"],
"booking": ["write"]
}
}'
```
Use the returned token in subsequent requests:
```
X-API-Key: <token>
```
## API Endpoints
### Auth
| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| POST | `/auth/register` | None | Create account |
| POST | `/auth/login` | None | Login |
| POST | `/auth/refresh` | None | Refresh JWT tokens |
| POST | `/auth/logout` | Yes | Revoke refresh token |
| GET | `/auth/me` | Yes | Get current user |
### Users
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/users/me` | Get profile |
| PUT | `/users/me` | Update profile |
| DELETE | `/users/me` | Delete account |
### API Keys
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api-keys` | Create API key |
| GET | `/api-keys` | List API keys |
| DELETE | `/api-keys/{id}` | Revoke API key |
### Calendars
| Method | Endpoint | Scope | Description |
|--------|----------|-------|-------------|
| GET | `/calendars` | calendars:read | List calendars |
| POST | `/calendars` | calendars:write | Create calendar |
| GET | `/calendars/{id}` | calendars:read | Get calendar |
| PUT | `/calendars/{id}` | calendars:write | Update calendar |
| DELETE | `/calendars/{id}` | calendars:write | Delete calendar |
| POST | `/calendars/{id}/share` | calendars:write | Share calendar |
| GET | `/calendars/{id}/members` | calendars:read | List members |
| DELETE | `/calendars/{id}/members/{userID}` | calendars:write | Remove member |
### Events
| Method | Endpoint | Scope | Description |
|--------|----------|-------|-------------|
| GET | `/events` | events:read | List events in time range |
| POST | `/events` | events:write | Create event |
| GET | `/events/{id}` | events:read | Get event |
| PUT | `/events/{id}` | events:write | Update event |
| DELETE | `/events/{id}` | events:write | Delete event |
| POST | `/events/{id}/reminders` | events:write | Add reminders |
| DELETE | `/events/{id}/reminders/{reminderID}` | events:write | Remove reminder |
| POST | `/events/{id}/attendees` | events:write | Add attendees |
| PUT | `/events/{id}/attendees/{attendeeID}` | events:write | Update RSVP |
| DELETE | `/events/{id}/attendees/{attendeeID}` | events:write | Remove attendee |
### Contacts
| Method | Endpoint | Scope | Description |
|--------|----------|-------|-------------|
| GET | `/contacts` | contacts:read | List contacts |
| POST | `/contacts` | contacts:write | Create contact |
| GET | `/contacts/{id}` | contacts:read | Get contact |
| PUT | `/contacts/{id}` | contacts:write | Update contact |
| DELETE | `/contacts/{id}` | contacts:write | Delete contact |
### Availability
| Method | Endpoint | Scope | Description |
|--------|----------|-------|-------------|
| GET | `/availability` | availability:read | Get busy blocks for a calendar |
### Booking
| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| POST | `/calendars/{id}/booking-link` | booking:write | Create booking link |
| GET | `/booking/{token}/availability` | None | Get available slots |
| POST | `/booking/{token}/reserve` | None | Reserve a slot |
### ICS
| Method | Endpoint | Scope | Description |
|--------|----------|-------|-------------|
| GET | `/calendars/{id}/export.ics` | calendars:read | Export as ICS |
| POST | `/calendars/import` | calendars:write | Import ICS file |
## Project Structure
```
calendarapi/
cmd/server/main.go Entry point
internal/
api/
routes.go Route definitions
handlers/ HTTP handlers
openapi/ OpenAPI spec files + Swagger UI
auth/ JWT manager
config/ Environment config
middleware/ Auth, rate limiting, scope enforcement
models/ Domain models
repository/ sqlc-generated database queries
scheduler/ Asynq background job scheduler
service/ Business logic layer
utils/ Shared utilities
migrations/ SQL migration files
sqlc/ sqlc configuration
about/ Design specifications
overview.md Architecture and data model
logic.md Business logic rules
details.md Endpoint contracts
SKILL.md AI agent integration guide
llms.txt LLM-optimized API reference
.env.example Environment template
go.mod
go.sum
```
## Architecture
```
Client (Web / Mobile / Agent)
|
HTTP REST API (Chi router)
|
Middleware (Auth, Rate Limiting, Scope Enforcement)
|
Handler Layer (Parse request, validate, return JSON)
|
Service Layer (Business logic, permissions, transactions)
|
Repository Layer (sqlc queries)
|
PostgreSQL
```
## Design Principles
- **Stateless** - JWT or API key on every request, no server-side sessions
- **UTC everywhere** - All timestamps stored in UTC, original timezone preserved
- **Soft deletes** - No data is permanently destroyed
- **Strict ownership** - Ownership derived from auth context, never from client input
- **Cursor pagination** - Efficient, consistent pagination on all list endpoints
- **Scoped API keys** - Fine-grained permission control for agent access
- **Race-safe booking** - Database transactions with row locking prevent double-booking
## License
MIT