cial/docker-compose.yml
Eliot M c50cc2b5fb refactor(layout): consolidate workspace under /cial — core/, platform/, app/
Reorganize the dev/prod tenant container so the agent runs in the monorepo
root with a clear, semantic directory tree:

  /cial/core/      — runtime (back, front, edge, ui, sdk, protocol, scripts,
                     docker). Locked down to the cial linux user (mode 0700
                     in prod; :ro bind mount in restricted dev).
  /cial/platform/  — agent-editable surface (back, front).
  /cial/app/       — App control plane sources, present in workspace but
                     never built or run inside the tenant container.
  /cial/docs/      — architecture + ops reference.
  /cial/.claude/   — project skills/agents/commands (symlinked into the
                     harness HOME by the dev entrypoint).
  /cial/data/      — persistent state (sqlite, deploy-logs, agent home).

Concrete changes:
- git mv cial-core → core, cial-platform → platform, cial-app → app,
  scripts → core/scripts.
- pnpm-workspace.yaml: packages now core/*, platform/*, app/*.
- Bulk path rewrites across 250+ source / docker / docs files.
- core/scripts/dev-tenant.mjs: ROOT path fix, rw mount of repo + ro
  overlay of /cial/core when --unrestricted is not set (FS-level
  trust boundary, defense in depth).
- core/edge/src/supervisor.{ts,dev.ts}: cwd + CLAUDE_HOME relocated to
  /cial/data/home; agent runs from /cial root so skill discovery picks
  up /cial/.claude/skills automatically.
- core/back providers/claude.ts: HOME defaults to /cial/data/home, cwd
  defaults to /cial.
- core/docker/{Dockerfile,Dockerfile.dev,dev-entrypoint.sh}: COPY +
  WORKDIR + ENTRYPOINT updated; .claude → harness symlink.
- app/docker/{Dockerfile,Dockerfile.router}: COPY core, COPY app
  (instead of cial-core / cial-app).
- New docs/file-structure.md — single canonical map of the runtime
  layout. cial:self-edit SKILL.md mandates reading it first.
- cial:build SKILL.md: scope notes updated to platform/* and core/*.
- root package.json: smoke / dev:tenant scripts now under core/scripts/.
- core/scripts/smoke.mjs: cial-core.db → cial.db.

Externals preserved as-is by intent:
- JWT issuer string 'cial-app' in core/back/src/modules/sso/index.ts +
  app/api/src/lib/sso.ts is an external contract — NOT renamed.
- @cial/back / @cial/edge / @cial/protocol / @cial/sdk / @cial/front
  package names kept stable to minimize blast radius.

Verified:
- pnpm install --prod=false → ok
- turbo run build for protocol, sdk, back, edge, front, platform-back,
  platform-front → all 7 successful (Next builds + tsc clean).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-29 13:04:45 +00:00

93 lines
3.3 KiB
YAML

# ---------------------------------------------------------------------------
# Cial — local mode (PLAN-LOCAL.md L1+)
#
# `docker compose up --build` brings up:
# - postgres (control-plane DB, port 5432 on host)
# - app-api (Next.js owner UI + API, port 3100 on host)
# - router (subdomain reverse proxy, port 8080 on host)
#
# Tenant containers (L3) are spawned at runtime by app-api via the host
# Docker socket and are not declared statically here.
# ---------------------------------------------------------------------------
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: cial
POSTGRES_PASSWORD: cial
POSTGRES_DB: cial
ports:
- "5432:5432"
volumes:
- cial-pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U cial -d cial"]
interval: 2s
timeout: 3s
retries: 30
app-api:
build:
context: .
dockerfile: app/docker/Dockerfile
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
# DooD: app-api spawns tenant containers via the host docker daemon.
# Running as root is the simplest portable way to access the socket
# across Linux + Docker Desktop (mac/windows). Local-dev only.
user: "0:0"
environment:
NODE_ENV: production
PORT: "3100"
DATABASE_URL: postgres://cial:cial@postgres:5432/cial
BETTER_AUTH_URL: http://localhost:3100
# Override in a local .env or shell before `docker compose up` for any
# non-throwaway environment.
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:-dev-only-not-for-prod-please-replace}
# Image the orchestrator spawns per tenant. Built by L0
# (`docker build -f core/docker/Dockerfile -t cial-tenant:dev .`).
TENANT_IMAGE: cial-tenant:dev
# Hostname the app-api container uses to reach freshly-spawned tenant
# containers (which bind on the host's ephemeral ports). On Linux this
# resolves via the extra_hosts entry below; Docker Desktop ships it
# natively.
TENANT_HOST: host.docker.internal
# Shared HS256 SSO secret. The orchestrator passes the same value
# into each tenant container so Core Back can verify owner-minted
# tokens (PLAN-LOCAL.md L5).
CIAL_SSO_SECRET: ${CIAL_SSO_SECRET:-dev-only-sso-secret-please-replace}
# Public base URL the owner's browser uses to reach a tenant. {slug}
# is substituted at mint time. Modern browsers resolve *.localhost
# → 127.0.0.1 automatically.
TENANT_PUBLIC_BASE: http://{slug}.localhost:8080
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "3100:3100"
router:
build:
context: .
dockerfile: app/docker/Dockerfile.router
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
PORT: "8080"
DATABASE_URL: postgres://cial:cial@postgres:5432/cial
# Tenant containers bind on the host; reach them through the gateway.
TENANT_HOST: host.docker.internal
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "8080:8080"
volumes:
cial-pg-data: