Files
GoCalGoo/llm/PLAN.md
2026-04-01 20:57:38 +02:00

7.0 KiB

GoCalGoo — Implementation Plan

Overview

GoCalGoo is a single Go application with four surfaces sharing one service layer:

  1. CLI — direct human use via cobra
  2. HTTP API — programmatic access (REST/JSON)
  3. MCP server — tool-style integration (stdio + HTTP)
  4. Shared service layer — underneath all three

Architecture

cmd/gocalgoo/         ← main entrypoint
internal/app/         ← app wiring, lifecycle
internal/config/      ← config loading, validation, profiles
internal/auth/        ← OAuth2, PKCE, token lifecycle, callback server
internal/google/      ← Google client init, raw API adapters
internal/calendar/    ← business logic: calendars, events
internal/contacts/    ← business logic: contacts
internal/httpapi/     ← REST/JSON API handlers
internal/mcp/         ← MCP server (stdio + HTTP)
internal/security/    ← API key auth, middleware, secret redaction
internal/store/       ← token store, API key store, local state
internal/output/      ← CLI tables/json/yaml rendering
internal/telemetry/   ← structured logging, tracing (optional)

Key Design Decisions

  • No CLI→API calling: HTTP API and MCP layer call shared services directly, not the CLI.
  • Google types at the edge: Convert Google API types to internal types immediately.
  • Interfaces at the call site: Interface definitions live in the package that uses them.
  • Config precedence: CLI flags > env vars > profile config > base config file > defaults.
  • SQLite for local metadata: API keys, audit log, local state.
  • Token file permissions: 0600, never world-readable.
  • API keys: Hashed at rest (bcrypt). Show raw key once on creation only.

Core Interfaces

type AuthManager interface {
    LoginLoopback(ctx context.Context, port int) error
    LoginManual(ctx context.Context, port int) error
    Status(ctx context.Context) (AuthStatus, error)
    Logout(ctx context.Context) error
}

type CalendarService interface {
    ListCalendars(ctx context.Context) ([]Calendar, error)
    ListEvents(ctx context.Context, req ListEventsRequest) ([]Event, error)
    AddEvent(ctx context.Context, req AddEventRequest) (*Event, error)
    UpdateEvent(ctx context.Context, req UpdateEventRequest) (*Event, error)
    DeleteEvent(ctx context.Context, calendarID, eventID string) error
}

type ContactsService interface {
    ListContacts(ctx context.Context, req ListContactsRequest) ([]Contact, error)
    AddContact(ctx context.Context, req AddContactRequest) (*Contact, error)
}

type APIKeyService interface {
    CreateKey(ctx context.Context, req CreateAPIKeyRequest) (*IssuedAPIKey, error)
    ValidateKey(ctx context.Context, raw string) (*Principal, error)
    RevokeKey(ctx context.Context, id string) error
}

OAuth2 Plan

Google installed-app / desktop-style flow with Authorization Code + PKCE.

Login modes

Mode Flag Behavior
Fixed-port loopback --port 53682 Bind 127.0.0.1:<port>, open browser, receive code
Random-port loopback --port 0 OS picks port, prints actual port before browser launch
Manual fallback --manual Print URL, user pastes redirect or code, CLI exchanges

Scopes (v1)

  • https://www.googleapis.com/auth/calendar
  • https://www.googleapis.com/auth/contacts

CLI Commands

gocalgoo auth login [--port 53682] [--manual]
gocalgoo auth status
gocalgoo auth logout
gocalgoo calendars list
gocalgoo events list --calendar primary [--from RFC3339] [--to RFC3339]
gocalgoo events add --calendar primary --title "..." --start RFC3339 --end RFC3339
gocalgoo events update --calendar primary --id ID --title "..."
gocalgoo events delete --calendar primary --id ID
gocalgoo contacts list
gocalgoo contacts add --given-name NAME --family-name NAME --email EMAIL
gocalgoo serve api
gocalgoo serve mcp
gocalgoo serve all
gocalgoo admin api-keys create --name NAME --perm events.read [--perm events.write]
gocalgoo admin api-keys list
gocalgoo admin api-keys revoke --id ID
gocalgoo config validate

HTTP API

Base path: /api/v1

Method Path Description
POST /api/v1/auth/login/start Begin OAuth login
POST /api/v1/auth/login/complete Complete OAuth login
GET /api/v1/auth/status Auth status
POST /api/v1/auth/logout Logout
GET /api/v1/calendars List calendars
GET /api/v1/calendars/{calendarId}/events List events
POST /api/v1/calendars/{calendarId}/events Add event
PATCH /api/v1/calendars/{calendarId}/events/{eventId} Update event
DELETE /api/v1/calendars/{calendarId}/events/{eventId} Delete event
GET /api/v1/contacts List contacts
POST /api/v1/contacts Add contact
POST /api/v1/admin/api-keys Create API key
GET /api/v1/admin/api-keys List API keys
DELETE /api/v1/admin/api-keys/{id} Revoke API key
GET /healthz Liveness
GET /readyz Readiness

MCP

Transports: stdio + Streamable HTTP

Tools

  • calendars_list
  • events_list
  • events_add
  • events_update
  • events_delete
  • contacts_list
  • contacts_add

Resources

  • gocalgoo://calendars
  • gocalgoo://calendar/{id}/events
  • gocalgoo://contacts

Auth

  • stdio: rely on environment/config (no transport auth)
  • HTTP MCP: require API key (X-API-Key header)

API Key Design

  • Header: X-API-Key: <key> or Authorization: Bearer <service-key>
  • Storage: hashed secret (bcrypt), never raw after creation
  • Fields: id, hashed_secret, name, scopes, created_at, last_used_at, disabled
  • Permissions: calendars.read, events.read, events.write, contacts.read, contacts.write, mcp.call

Security Requirements

  • Bind OAuth callback loopback to 127.0.0.1 only
  • Validate OAuth state parameter
  • Use PKCE
  • Redact secrets/codes from logs
  • Token file permissions: 0600
  • Hash API keys at rest
  • Show raw API key once on creation only
  • Admin endpoints disabled by default
  • Require API key for HTTP API and MCP HTTP

Delivery Phases

Phase Status Description
1 In progress Foundation: repo scaffold, config, logging, token store, OAuth2 CLI
2 Pending Core business logic: calendars, events, contacts
3 Pending CLI completion: output formats, validation, robust errors
4 Pending HTTP API: auth middleware, REST endpoints, API key management
5 Pending MCP: stdio transport, HTTP transport, tool/resource exposure
6 Pending Hardening: audit log, retry/backoff, quota-aware errors, tests, packaging

Go Stack

Library Purpose
github.com/spf13/cobra CLI framework
github.com/spf13/viper Config management
go.uber.org/zap Structured logging
github.com/go-chi/chi/v5 HTTP routing
golang.org/x/oauth2 OAuth2 plumbing
google.golang.org/api Google API clients
github.com/stretchr/testify Test assertions
golang.org/x/crypto/bcrypt API key hashing
SQLite Local metadata (API keys, audit log)