Files
mcq/CLAUDE.md
Kyle Isom b48fcc8465 sso: public MCIAS authorize URL + docs
Add [sso].public_url so the browser SSO authorize redirect uses the
public MCIAS hostname while the code exchange stays on the internal
address (mcdsl v1.9.0). Document the SSO URL split and the rootless-podman
/ unikernel-eligibility rules in CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 11:20:50 -07:00

101 lines
3.9 KiB
Markdown

# CLAUDE.md
## Overview
MCQ (Metacircular Document Queue) is a reading queue service. Documents
(raw markdown) are pushed via API from inside the infrastructure, then
read through a mobile-friendly web UI from anywhere. MCIAS authenticates
all access — any user (including guest) can read, any user (including
system accounts) can push.
## Build Commands
```bash
make all # vet → lint → test → build
make mcq # build binary with version injection
make build # go build ./...
make test # go test ./...
make vet # go vet ./...
make lint # golangci-lint run ./...
make proto # regenerate gRPC code from .proto files
make proto-lint # buf lint + buf breaking
make devserver # build and run locally against srv/mcq.toml
make clean # remove binaries
```
Run a single test:
```bash
go test ./internal/db/ -run TestPutDocument
```
## Architecture
Single binary, three concerns:
- **REST API** (`/v1/*`) — CRUD for documents, MCIAS Bearer token auth
- **gRPC API** (`:9443`) — same operations, MCIAS interceptor auth
- **Web UI** (`/`, `/d/{slug}`, `/login`) — goldmark-rendered reader, MCIAS session cookies
Documents keyed by slug (unique). PUT upserts — same slug replaces content.
## Project Structure
```
cmd/mcq/ CLI entry point (server subcommand)
internal/
db/ SQLite schema, migrations, document CRUD
server/ REST API routes and handlers
grpcserver/ gRPC server, interceptors, service handlers
webserver/ Web UI routes, templates, session management
render/ goldmark markdown-to-HTML renderer
proto/mcq/v1/ Protobuf definitions
gen/mcq/v1/ Generated Go code (do not edit)
web/ Embedded templates + static files
deploy/ systemd, examples
```
## Shared Library
MCQ uses `mcdsl` (git.wntrmute.dev/mc/mcdsl) for: auth, db, config,
httpserver, grpcserver, csrf, web (session cookies, auth middleware,
template rendering).
## Critical Rules
1. **REST/gRPC sync**: Every REST endpoint has a corresponding gRPC RPC.
2. **gRPC interceptor maps**: New RPCs must be added to the correct map.
3. **No test frameworks**: stdlib `testing` only, real SQLite in t.TempDir().
4. **CSRF on all web mutations**: double-submit cookie pattern.
5. **Session cookies**: HttpOnly, Secure, SameSite=Strict.
## SSO (public vs internal MCIAS URLs)
MCQ is reachable publicly (`mcq.metacircular.net`), so its SSO uses **two**
MCIAS URLs (via `mcdsl/sso` ≥ v1.9.0):
- `[mcias].server_url` — the **internal** address (`https://mcias.svc.mcp.metacircular.net:8443`)
used for the server-to-server authorization-code exchange. Efficient and
does not depend on the public edge.
- `[sso].public_url` — the **public, browser-facing** MCIAS base URL
(`https://mcias.metacircular.net`) used to build the authorize redirect, so
end-user browsers (which can't resolve the internal name) can reach it.
- `[sso].redirect_uri` must be the **public** callback
(`https://mcq.metacircular.net/sso/callback`) and must match the
`redirect_uri` registered for the `mcq` SSO client in MCIAS
(`mciasctl sso update --client-id mcq --redirect-uri ...`).
If `public_url` is empty the authorize redirect falls back to `server_url`
(tailnet-only SSO). The startup log prints both `authorize_url` and
`exchange_url` so you can confirm the split.
## Deployment / runtime
- **Containers run rootless under MCP.** Dockerfiles must NOT declare
`VOLUME /srv/mcq`, pre-create/chown the data dir, or set `USER` — MCP
bind-mounts `/srv/mcq` and runs `--user 0:0`. See
`../engineering-standards.md` → Containerization.
- **Not unikernel-eligible (yet).** MCQ writes a SQLite DB to `/srv/mcq`;
the unikernel runtime currently bakes config/certs read-only and has no
writable host mount, so MCQ stays a container until 9p/virtio-blk storage
lands. See `docs/unikernels.md` in the workspace root.