diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..57e11e37 --- /dev/null +++ b/.env.example @@ -0,0 +1,34 @@ +POSTGRES_DB=samosachaat +POSTGRES_USER=samosachaat_admin +POSTGRES_PASSWORD=localdev +DATABASE_URL=postgresql+asyncpg://samosachaat_admin:localdev@localhost:5432/samosachaat + +FRONTEND_PORT=3000 +AUTH_PORT=8001 +CHAT_API_PORT=8002 +INFERENCE_PORT=8003 +GRAFANA_PORT=3001 +PROMETHEUS_PORT=9090 +LOKI_PORT=3100 + +AUTH_SERVICE_URL=http://auth:8001 +CHAT_API_URL=http://chat-api:8002 +INFERENCE_SERVICE_URL=http://inference:8003 +NEXTAUTH_URL=http://localhost:3000 + +GOOGLE_CLIENT_ID=your-google-client-id +GOOGLE_CLIENT_SECRET=your-google-client-secret +GITHUB_CLIENT_ID=your-github-client-id +GITHUB_CLIENT_SECRET=your-github-client-secret + +JWT_ALGORITHM=RS256 +JWT_PRIVATE_KEY=generate-an-rs256-private-key +JWT_PUBLIC_KEY=generate-the-matching-rs256-public-key +NEXTAUTH_SECRET=generate-a-random-secret +INTERNAL_API_KEY=generate-a-random-internal-api-key + +HF_TOKEN=your-huggingface-token +MODEL_STORAGE_PATH=./models +DEFAULT_MODEL_TAG=samosachaat-d12 +NANOCHAT_DTYPE=float32 +NUM_WORKERS=1 diff --git a/.gitignore b/.gitignore index ad7db224..1229f1a7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,17 @@ __pycache__/ dev-ignore/ report.md eval_bundle/ +models/ +.terraform/ +*.tfstate +*.tfstate.* +*.tfvars +*.tfvars.json # Secrets .env +.env.local +.env.*.local # Local setup CLAUDE.md diff --git a/README.md b/README.md index 79b12df3..a2ad401b 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,30 @@ nanochat is the simplest experimental harness for training LLMs. It is designed For questions about the repo, I recommend either using [DeepWiki](https://deepwiki.com/karpathy/nanochat) from Devin/Cognition to ask questions about the repo, or use the [Discussions tab](https://github.com/karpathy/nanochat/discussions), or come by the [#nanochat](https://discord.com/channels/1020383067459821711/1427295580895314031) channel on Discord. +## Platform monorepo scaffold + +This repository now also carries the samosaChaat platform scaffold alongside the +original nanochat training code. The new top-level directories are organized for +service-oriented development: + +- `services/` contains the frontend, auth, chat API, and inference services +- `contracts/` contains the shared OpenAPI and JSON schema contracts +- `db/migrations/` contains PostgreSQL schema bootstrap scripts +- `helm/` contains application and observability chart scaffolding +- `terraform/` contains shared modules plus `dev`, `uat`, and `prod` environment scaffolding + +### Local platform quick start + +1. Copy `.env.example` to `.env` and replace the placeholder secrets. +2. Start the local stack with `bash scripts/local-dev.sh`. +3. Seed the local database with `bash scripts/seed-db.sh`. +4. Open the placeholder frontend at [http://localhost:3000](http://localhost:3000). + +The initial scaffold keeps the service topology stable for local development. +`services/auth`, `services/chat-api`, and `services/frontend` are placeholders +until their dedicated implementations land; the inference service is extracted on +the follow-up branch. + ## Time-to-GPT-2 Leaderboard Presently, the main focus of development is on tuning the pretraining stage, which takes the most amount of compute. Inspired by the modded-nanogpt repo and to incentivise progress and community collaboration, nanochat maintains a leaderboard for a "GPT-2 speedrun", which is the wall-clock time required to train a nanochat model to GPT-2 grade capability, as measured by the DCLM CORE score. The [runs/speedrun.sh](runs/speedrun.sh) script always reflects the reference way to train GPT-2 grade model and talk to it. The current leaderboard looks as follows: diff --git a/contracts/openapi/auth-api.yaml b/contracts/openapi/auth-api.yaml new file mode 100644 index 00000000..192e9ae6 --- /dev/null +++ b/contracts/openapi/auth-api.yaml @@ -0,0 +1,108 @@ +openapi: 3.1.0 +info: + title: samosaChaat Auth API + version: 0.1.0 + description: > + Contract skeleton for the authentication service. OAuth providers, session + exchange, and user identity endpoints must conform to this document. +servers: + - url: http://auth:8001 +paths: + /health: + get: + summary: Readiness probe for the auth service. + security: [] + responses: + "200": + description: Auth service health. + content: + application/json: + schema: + type: object + properties: + status: + type: string + ready: + type: boolean + required: + - status + - ready + /auth/oauth/{provider}/start: + get: + summary: Begin an OAuth login flow. + parameters: + - $ref: "#/components/parameters/OAuthProvider" + responses: + "302": + description: Redirect to the provider authorization page. + /auth/oauth/{provider}/callback: + get: + summary: Complete an OAuth login flow. + parameters: + - $ref: "#/components/parameters/OAuthProvider" + - in: query + name: code + required: true + schema: + type: string + responses: + "200": + description: Session established. + content: + application/json: + schema: + type: object + properties: + user: + $ref: ../schemas/user.json + access_token: + type: string + required: + - user + - access_token + /auth/me: + get: + summary: Return the authenticated user profile. + security: + - sessionCookie: [] + responses: + "200": + description: Current user profile. + content: + application/json: + schema: + $ref: ../schemas/user.json + /auth/token/refresh: + post: + summary: Exchange a refresh token for a new access token. + responses: + "200": + description: Refreshed session token pair. + content: + application/json: + schema: + type: object + properties: + access_token: + type: string + expires_in: + type: integer + required: + - access_token + - expires_in +components: + parameters: + OAuthProvider: + in: path + name: provider + required: true + schema: + type: string + enum: + - google + - github + securitySchemes: + sessionCookie: + type: apiKey + in: cookie + name: session diff --git a/contracts/openapi/chat-api.yaml b/contracts/openapi/chat-api.yaml new file mode 100644 index 00000000..ffa7b908 --- /dev/null +++ b/contracts/openapi/chat-api.yaml @@ -0,0 +1,153 @@ +openapi: 3.1.0 +info: + title: samosaChaat Chat API + version: 0.1.0 + description: > + Contract skeleton for conversations, persisted message history, and chat + orchestration between the frontend and inference service. +servers: + - url: http://chat-api:8002 +security: + - bearerAuth: [] +paths: + /health: + get: + summary: Readiness probe for the chat API. + security: [] + responses: + "200": + description: Chat API health. + content: + application/json: + schema: + type: object + properties: + status: + type: string + ready: + type: boolean + required: + - status + - ready + /conversations: + get: + summary: List the current user's conversations. + responses: + "200": + description: Conversation collection. + content: + application/json: + schema: + type: array + items: + $ref: ../schemas/conversation.json + post: + summary: Create a new conversation. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + model_tag: + type: string + required: + - title + - model_tag + responses: + "201": + description: Conversation created. + content: + application/json: + schema: + $ref: ../schemas/conversation.json + /conversations/{conversationId}: + get: + summary: Fetch a single conversation. + parameters: + - $ref: "#/components/parameters/ConversationId" + responses: + "200": + description: Conversation details. + content: + application/json: + schema: + $ref: ../schemas/conversation.json + patch: + summary: Update mutable conversation metadata. + parameters: + - $ref: "#/components/parameters/ConversationId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + model_tag: + type: string + responses: + "200": + description: Updated conversation. + content: + application/json: + schema: + $ref: ../schemas/conversation.json + /conversations/{conversationId}/messages: + get: + summary: List persisted messages for a conversation. + parameters: + - $ref: "#/components/parameters/ConversationId" + responses: + "200": + description: Conversation message history. + content: + application/json: + schema: + type: array + items: + $ref: ../schemas/message.json + post: + summary: Append a message and begin streaming completion. + parameters: + - $ref: "#/components/parameters/ConversationId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + message: + $ref: ../schemas/message.json + stream: + type: boolean + default: true + required: + - message + responses: + "200": + description: Server-sent token stream from the inference service. + content: + text/event-stream: + schema: + type: string +components: + parameters: + ConversationId: + in: path + name: conversationId + required: true + schema: + type: string + format: uuid + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT diff --git a/contracts/openapi/inference-api.yaml b/contracts/openapi/inference-api.yaml new file mode 100644 index 00000000..017cf41b --- /dev/null +++ b/contracts/openapi/inference-api.yaml @@ -0,0 +1,174 @@ +openapi: 3.1.0 +info: + title: samosaChaat Inference API + version: 0.1.0 + description: > + Contract skeleton for the standalone inference microservice that streams + tokens and manages model weight lifecycle. +servers: + - url: http://inference:8003 +paths: + /health: + get: + summary: Liveness and readiness probe. + responses: + "200": + description: Inference service health. + content: + application/json: + schema: + type: object + properties: + status: + type: string + ready: + type: boolean + current_model: + type: + - string + - "null" + required: + - status + - ready + /generate: + post: + summary: Stream generated tokens as server-sent events. + security: + - internalApiKey: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/GenerateRequest" + responses: + "200": + description: SSE response of token chunks and done marker. + content: + text/event-stream: + schema: + type: string + /models: + get: + summary: List available and loaded model weights. + security: + - internalApiKey: [] + responses: + "200": + description: Model registry view. + content: + application/json: + schema: + type: object + properties: + current_model: + type: + - string + - "null" + models: + type: array + items: + $ref: "#/components/schemas/ModelInfo" + required: + - current_model + - models + /models/swap: + post: + summary: Drain workers and swap the loaded model weights. + security: + - internalApiKey: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + model_tag: + type: string + required: + - model_tag + responses: + "202": + description: Swap request accepted. + content: + application/json: + schema: + type: object + properties: + status: + type: string + current_model: + type: string + required: + - status + - current_model + /stats: + get: + summary: Worker pool and throughput statistics. + security: + - internalApiKey: [] + responses: + "200": + description: Runtime worker statistics. + content: + application/json: + schema: + type: object +components: + securitySchemes: + internalApiKey: + type: apiKey + in: header + name: X-Internal-API-Key + schemas: + ChatMessage: + type: object + additionalProperties: false + properties: + role: + type: string + content: + type: string + required: + - role + - content + GenerateRequest: + type: object + additionalProperties: false + properties: + messages: + type: array + items: + $ref: "#/components/schemas/ChatMessage" + temperature: + type: + - number + - "null" + max_tokens: + type: + - integer + - "null" + top_k: + type: + - integer + - "null" + required: + - messages + ModelInfo: + type: object + additionalProperties: false + properties: + model_tag: + type: string + source: + type: string + path: + type: string + loaded: + type: boolean + required: + - model_tag + - source + - path + - loaded diff --git a/contracts/schemas/conversation.json b/contracts/schemas/conversation.json new file mode 100644 index 00000000..4c401c1e --- /dev/null +++ b/contracts/schemas/conversation.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Conversation", + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "user_id": { + "type": "string", + "format": "uuid" + }, + "title": { + "type": "string" + }, + "model_tag": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "user_id", + "title", + "model_tag", + "created_at", + "updated_at" + ] +} diff --git a/contracts/schemas/message.json b/contracts/schemas/message.json new file mode 100644 index 00000000..df9e551b --- /dev/null +++ b/contracts/schemas/message.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Message", + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "conversation_id": { + "type": "string", + "format": "uuid" + }, + "role": { + "type": "string" + }, + "content": { + "type": "string" + }, + "token_count": { + "type": "integer", + "minimum": 0 + }, + "model_tag": { + "type": "string" + }, + "inference_time_ms": { + "type": "integer", + "minimum": 0 + }, + "created_at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "conversation_id", + "role", + "content", + "token_count", + "model_tag", + "inference_time_ms", + "created_at" + ] +} diff --git a/contracts/schemas/user.json b/contracts/schemas/user.json new file mode 100644 index 00000000..e6b57ff9 --- /dev/null +++ b/contracts/schemas/user.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "User", + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "email": { + "type": "string", + "format": "email" + }, + "name": { + "type": "string" + }, + "avatar_url": { + "type": [ + "string", + "null" + ], + "format": "uri" + }, + "provider": { + "type": "string" + }, + "provider_id": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "last_login_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + } + }, + "required": [ + "id", + "email", + "name", + "avatar_url", + "provider", + "provider_id", + "created_at", + "updated_at", + "last_login_at" + ] +} diff --git a/db/migrations/0001_initial_schema.sql b/db/migrations/0001_initial_schema.sql new file mode 100644 index 00000000..bb40f32e --- /dev/null +++ b/db/migrations/0001_initial_schema.sql @@ -0,0 +1,42 @@ +CREATE EXTENSION IF NOT EXISTS pgcrypto; + +CREATE TABLE IF NOT EXISTS users ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + email TEXT NOT NULL UNIQUE, + name TEXT NOT NULL, + avatar_url TEXT, + provider TEXT NOT NULL, + provider_id TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + last_login_at TIMESTAMPTZ +); + +CREATE UNIQUE INDEX IF NOT EXISTS users_provider_lookup_idx + ON users (provider, provider_id); + +CREATE TABLE IF NOT EXISTS conversations ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, + title TEXT NOT NULL, + model_tag TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS conversations_user_id_idx + ON conversations (user_id); + +CREATE TABLE IF NOT EXISTS messages ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE, + role TEXT NOT NULL, + content TEXT NOT NULL, + token_count INTEGER NOT NULL DEFAULT 0, + model_tag TEXT NOT NULL, + inference_time_ms INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS messages_conversation_id_idx + ON messages (conversation_id, created_at); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..51a5360b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,98 @@ +services: + postgres: + image: postgres:15 + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB:-samosachaat} + POSTGRES_USER: ${POSTGRES_USER:-samosachaat_admin} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-localdev} + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data + - ./db/migrations:/docker-entrypoint-initdb.d:ro + + frontend: + build: + context: ./services/frontend + restart: unless-stopped + ports: + - "${FRONTEND_PORT:-3000}:3000" + environment: + AUTH_SERVICE_URL: ${AUTH_SERVICE_URL:-http://auth:8001} + CHAT_API_URL: ${CHAT_API_URL:-http://chat-api:8002} + NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000} + depends_on: + - auth + - chat-api + + auth: + build: + context: ./services/auth + restart: unless-stopped + ports: + - "${AUTH_PORT:-8001}:8001" + environment: + DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://samosachaat_admin:localdev@postgres:5432/samosachaat} + GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-} + GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-} + GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-} + GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-} + JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY:-} + JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY:-} + depends_on: + - postgres + + chat-api: + build: + context: ./services/chat-api + restart: unless-stopped + ports: + - "${CHAT_API_PORT:-8002}:8002" + environment: + DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://samosachaat_admin:localdev@postgres:5432/samosachaat} + AUTH_SERVICE_URL: ${AUTH_SERVICE_URL:-http://auth:8001} + INFERENCE_SERVICE_URL: ${INFERENCE_SERVICE_URL:-http://inference:8003} + INTERNAL_API_KEY: ${INTERNAL_API_KEY:-} + depends_on: + - postgres + - auth + - inference + + inference: + build: + context: ./services/inference + restart: unless-stopped + ports: + - "${INFERENCE_PORT:-8003}:8003" + environment: + MODEL_STORAGE_PATH: /models + DEFAULT_MODEL_TAG: ${DEFAULT_MODEL_TAG:-samosachaat-d12} + NANOCHAT_DTYPE: ${NANOCHAT_DTYPE:-float32} + HF_TOKEN: ${HF_TOKEN:-} + INTERNAL_API_KEY: ${INTERNAL_API_KEY:-} + NUM_WORKERS: ${NUM_WORKERS:-1} + volumes: + - ./models:/models + + grafana: + image: grafana/grafana:latest + restart: unless-stopped + ports: + - "${GRAFANA_PORT:-3001}:3000" + + prometheus: + image: prom/prometheus:latest + restart: unless-stopped + ports: + - "${PROMETHEUS_PORT:-9090}:9090" + + loki: + image: grafana/loki:latest + restart: unless-stopped + command: -config.file=/etc/loki/local-config.yaml + ports: + - "${LOKI_PORT:-3100}:3100" + +volumes: + pgdata: diff --git a/helm/README.md b/helm/README.md new file mode 100644 index 00000000..cf577202 --- /dev/null +++ b/helm/README.md @@ -0,0 +1,4 @@ +# Helm Charts + +This directory holds Kubernetes deployment charts for the samosaChaat platform +and its supporting observability stack. diff --git a/helm/observability/Chart.yaml b/helm/observability/Chart.yaml new file mode 100644 index 00000000..071fb150 --- /dev/null +++ b/helm/observability/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: observability +description: Observability chart scaffold for Grafana, Prometheus, and Loki. +type: application +version: 0.1.0 +appVersion: "0.1.0" diff --git a/helm/observability/templates/NOTES.txt b/helm/observability/templates/NOTES.txt new file mode 100644 index 00000000..9e750d08 --- /dev/null +++ b/helm/observability/templates/NOTES.txt @@ -0,0 +1,4 @@ +The observability chart scaffold is in place. + +Add concrete manifests for Grafana, Prometheus, Loki, dashboards, and scrape +configuration as the platform monitoring stack is implemented. diff --git a/helm/observability/values.yaml b/helm/observability/values.yaml new file mode 100644 index 00000000..013a3646 --- /dev/null +++ b/helm/observability/values.yaml @@ -0,0 +1,8 @@ +grafana: + enabled: true + +prometheus: + enabled: true + +loki: + enabled: true diff --git a/helm/samosachaat/Chart.yaml b/helm/samosachaat/Chart.yaml new file mode 100644 index 00000000..08a4ce2f --- /dev/null +++ b/helm/samosachaat/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: samosachaat +description: Application chart scaffold for the samosaChaat platform. +type: application +version: 0.1.0 +appVersion: "0.1.0" diff --git a/helm/samosachaat/templates/NOTES.txt b/helm/samosachaat/templates/NOTES.txt new file mode 100644 index 00000000..74a5ef53 --- /dev/null +++ b/helm/samosachaat/templates/NOTES.txt @@ -0,0 +1,4 @@ +The samosaChaat application chart is scaffolded. + +Populate this chart with Deployments, Services, Ingress, Secrets, and ConfigMaps +as the platform services are implemented. diff --git a/helm/samosachaat/values.yaml b/helm/samosachaat/values.yaml new file mode 100644 index 00000000..2f26a777 --- /dev/null +++ b/helm/samosachaat/values.yaml @@ -0,0 +1,10 @@ +image: + repository: ghcr.io/manmohan659/nanochat/frontend + tag: latest + pullPolicy: IfNotPresent + +replicaCount: 1 + +service: + type: ClusterIP + port: 3000 diff --git a/scripts/local-dev.sh b/scripts/local-dev.sh new file mode 100755 index 00000000..f635bd15 --- /dev/null +++ b/scripts/local-dev.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +ENV_FILE="${ROOT_DIR}/.env" + +if [[ ! -f "${ENV_FILE}" ]]; then + ENV_FILE="${ROOT_DIR}/.env.example" + echo "Using ${ENV_FILE} because .env is not present." +fi + +exec docker compose --env-file "${ENV_FILE}" up --build "$@" diff --git a/scripts/seed-db.sh b/scripts/seed-db.sh new file mode 100755 index 00000000..8d0be3f2 --- /dev/null +++ b/scripts/seed-db.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +ENV_FILE="${ROOT_DIR}/.env" + +if [[ ! -f "${ENV_FILE}" ]]; then + ENV_FILE="${ROOT_DIR}/.env.example" +fi + +set -a +source "${ENV_FILE}" +set +a + +docker compose exec -T postgres psql \ + -U "${POSTGRES_USER:-samosachaat_admin}" \ + -d "${POSTGRES_DB:-samosachaat}" <<'SQL' +INSERT INTO users ( + id, + email, + name, + avatar_url, + provider, + provider_id, + last_login_at +) VALUES ( + '11111111-1111-1111-1111-111111111111', + 'demo@samosachaat.local', + 'Demo User', + 'https://example.com/avatar.png', + 'github', + 'demo-user', + NOW() +) ON CONFLICT (id) DO NOTHING; + +INSERT INTO conversations ( + id, + user_id, + title, + model_tag +) VALUES ( + '22222222-2222-2222-2222-222222222222', + '11111111-1111-1111-1111-111111111111', + 'Welcome to samosaChaat', + 'samosachaat-d12' +) ON CONFLICT (id) DO NOTHING; + +INSERT INTO messages ( + id, + conversation_id, + role, + content, + token_count, + model_tag, + inference_time_ms +) VALUES ( + '33333333-3333-3333-3333-333333333333', + '22222222-2222-2222-2222-222222222222', + 'assistant', + 'The database scaffold is ready for local development.', + 9, + 'samosachaat-d12', + 12 +) ON CONFLICT (id) DO NOTHING; +SQL diff --git a/services/auth/Dockerfile b/services/auth/Dockerfile new file mode 100644 index 00000000..bce37ff9 --- /dev/null +++ b/services/auth/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY README.md /app/README.md + +EXPOSE 8001 + +CMD ["python", "-m", "http.server", "8001", "--bind", "0.0.0.0"] diff --git a/services/auth/README.md b/services/auth/README.md new file mode 100644 index 00000000..97433de7 --- /dev/null +++ b/services/auth/README.md @@ -0,0 +1,7 @@ +# Auth Service + +Scaffold placeholder for Issue #5. + +The monorepo branch provisions this directory and a minimal Docker image so +local `docker compose up` remains viable before the real auth service +implementation lands. diff --git a/services/chat-api/Dockerfile b/services/chat-api/Dockerfile new file mode 100644 index 00000000..1cbef5b5 --- /dev/null +++ b/services/chat-api/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY README.md /app/README.md + +EXPOSE 8002 + +CMD ["python", "-m", "http.server", "8002", "--bind", "0.0.0.0"] diff --git a/services/chat-api/README.md b/services/chat-api/README.md new file mode 100644 index 00000000..a671d66b --- /dev/null +++ b/services/chat-api/README.md @@ -0,0 +1,7 @@ +# Chat API Service + +Scaffold placeholder for Issue #6. + +This container is intentionally minimal on the monorepo scaffold branch. It +keeps the compose topology stable while the dedicated chat API implementation +is developed. diff --git a/services/frontend/Dockerfile b/services/frontend/Dockerfile new file mode 100644 index 00000000..14c93d73 --- /dev/null +++ b/services/frontend/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY index.html /app/index.html + +EXPOSE 3000 + +CMD ["python", "-m", "http.server", "3000", "--bind", "0.0.0.0"] diff --git a/services/frontend/index.html b/services/frontend/index.html new file mode 100644 index 00000000..cae9179e --- /dev/null +++ b/services/frontend/index.html @@ -0,0 +1,65 @@ + + + + + + samosaChaat frontend scaffold + + + +
+

samosaChaat platform scaffold

+

+ The monorepo structure is in place. This placeholder frontend keeps + docker compose up usable until the real UI lands. +

+ +
+ + diff --git a/services/inference/Dockerfile b/services/inference/Dockerfile new file mode 100644 index 00000000..271d6416 --- /dev/null +++ b/services/inference/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY README.md /app/README.md + +EXPOSE 8003 + +CMD ["python", "-m", "http.server", "8003", "--bind", "0.0.0.0"] diff --git a/services/inference/README.md b/services/inference/README.md new file mode 100644 index 00000000..8bcb6dce --- /dev/null +++ b/services/inference/README.md @@ -0,0 +1,6 @@ +# Inference Service + +Scaffold placeholder for Issue #3. + +This branch only creates the monorepo structure. The next branch extracts the +FastAPI inference microservice into this directory. diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 00000000..dd92fc00 --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,6 @@ +# Terraform + +Environment and module scaffolding for the samosaChaat AWS platform. + +- `environments/` holds per-environment stacks for `dev`, `uat`, and `prod` +- `modules/` holds reusable building blocks for shared infrastructure diff --git a/terraform/environments/dev/README.md b/terraform/environments/dev/README.md new file mode 100644 index 00000000..e8a0247e --- /dev/null +++ b/terraform/environments/dev/README.md @@ -0,0 +1,6 @@ +# dev + +Development environment stack scaffold. + +Use this directory to wire together the shared Terraform modules for the dev +AWS account and domain configuration. diff --git a/terraform/environments/prod/README.md b/terraform/environments/prod/README.md new file mode 100644 index 00000000..5428bb2d --- /dev/null +++ b/terraform/environments/prod/README.md @@ -0,0 +1,6 @@ +# prod + +Production environment stack scaffold. + +Use this directory to compose the shared Terraform modules with production +networking, security, and availability requirements. diff --git a/terraform/environments/uat/README.md b/terraform/environments/uat/README.md new file mode 100644 index 00000000..a2cd31c4 --- /dev/null +++ b/terraform/environments/uat/README.md @@ -0,0 +1,6 @@ +# uat + +User acceptance testing environment stack scaffold. + +Use this directory to compose the shared Terraform modules with UAT-specific +variables, state backends, and deployment topology. diff --git a/terraform/modules/acm/README.md b/terraform/modules/acm/README.md new file mode 100644 index 00000000..72f42139 --- /dev/null +++ b/terraform/modules/acm/README.md @@ -0,0 +1,3 @@ +# acm module + +Scaffold placeholder for the shared ACM certificate module. diff --git a/terraform/modules/ecr/README.md b/terraform/modules/ecr/README.md new file mode 100644 index 00000000..82fb7bcd --- /dev/null +++ b/terraform/modules/ecr/README.md @@ -0,0 +1,3 @@ +# ecr module + +Scaffold placeholder for the shared container registry module. diff --git a/terraform/modules/efs/README.md b/terraform/modules/efs/README.md new file mode 100644 index 00000000..2524aaa3 --- /dev/null +++ b/terraform/modules/efs/README.md @@ -0,0 +1,3 @@ +# efs module + +Scaffold placeholder for the shared EFS storage module. diff --git a/terraform/modules/eks/README.md b/terraform/modules/eks/README.md new file mode 100644 index 00000000..cdef5f16 --- /dev/null +++ b/terraform/modules/eks/README.md @@ -0,0 +1,3 @@ +# eks module + +Scaffold placeholder for the shared EKS cluster module. diff --git a/terraform/modules/iam/README.md b/terraform/modules/iam/README.md new file mode 100644 index 00000000..1f836ca7 --- /dev/null +++ b/terraform/modules/iam/README.md @@ -0,0 +1,3 @@ +# iam module + +Scaffold placeholder for the shared IAM roles and policy module. diff --git a/terraform/modules/rds/README.md b/terraform/modules/rds/README.md new file mode 100644 index 00000000..74451ef4 --- /dev/null +++ b/terraform/modules/rds/README.md @@ -0,0 +1,3 @@ +# rds module + +Scaffold placeholder for the shared PostgreSQL / RDS module. diff --git a/terraform/modules/route53/README.md b/terraform/modules/route53/README.md new file mode 100644 index 00000000..b6b0c8e1 --- /dev/null +++ b/terraform/modules/route53/README.md @@ -0,0 +1,3 @@ +# route53 module + +Scaffold placeholder for the shared DNS management module. diff --git a/terraform/modules/vpc/README.md b/terraform/modules/vpc/README.md new file mode 100644 index 00000000..d324fa85 --- /dev/null +++ b/terraform/modules/vpc/README.md @@ -0,0 +1,3 @@ +# vpc module + +Scaffold placeholder for the shared VPC networking module.