Lucid's first hosted topology is deliberately small: one managed PostgreSQL database, one Lucid server container, and one separately managed Heddle Execution Host Runtime. This repository contains a portable server image and configuration contract. It contains no deployment-specific account IDs, database endpoints, credentials, Terraform state, or other environment data.
This is a small multi-principal preview posture, not a highly available or production social-network architecture.
flowchart LR
Client["User client"] --> Server["Lucid server container"]
Server --> Postgres[("Managed PostgreSQL")]
Server --> AgentCore["Heddle Execution Host on AgentCore Runtime"]
AgentCore --> MCP["Lucid scoped MCP endpoint"]
MCP --> Server
- Lucid owns user authentication, product authorization, signed invocation authority, PostgreSQL data, and the exact MCP tools exposed to a turn.
- The private Execution Host owns the Heddle loop and isolated shell workspace. It receives no database credential.
- The AWS SDK in Lucid uses its standard credential provider chain. On EC2,
grant the instance role only
bedrock-agentcore:InvokeAgentRuntimefor the selected Runtime ARN instead of injecting static AWS keys.
The Runtime configuration must allow these three adopter-defined headers:
x-heddle-execution-host-assertion
x-heddle-execution-host-mcp-capability
x-heddle-execution-host-model-api-key
The AgentCore Runtime session header is part of the managed invocation API and is not one of the custom allowlist entries.
The checked-in Dockerfile targets ARM64 so the same artifact can run on a small Graviton EC2 instance:
yarn server:docker:buildThe final image:
- runs as the non-root
nodeuser undertini; - stores non-authoritative local Heddle artifacts under
/var/lib/lucid; - exposes port
8081and a process-liveness probe atGET /healthz; - serves the compiled user SPA and
/api/trpc/from the same origin; - includes the compiled migration entrypoint and checked-in Drizzle migrations; and
- contains no server credentials. Supabase browser values, when supplied, are public build configuration embedded into the SPA.
Supabase's browser project URL and publishable key are Vite build inputs rather than runtime secrets:
docker build --platform linux/arm64 \
--build-arg VITE_SUPABASE_URL=https://project-ref.supabase.co \
--build-arg VITE_SUPABASE_PUBLISHABLE_KEY=your-publishable-key \
--file apps/server/Dockerfile \
--tag lucid-server:local .Never pass a Supabase service-role key or Google client secret to this build.
The health route proves that the Node process can answer HTTP. It deliberately does not claim that PostgreSQL, AgentCore, or model providers are ready.
Use .env.hosted.example as the deployment contract.
Provide its values through the target platform's secret and configuration
mechanisms. Never bake a populated file into the image.
Required environment-specific inputs are:
- a TLS PostgreSQL URL reachable from the server container;
- a public HTTPS Lucid origin reachable from the Runtime;
- the Supabase project URL plus a server-only break-glass operator token;
- an owner-readable ES256 private JWK file;
- model credentials;
- product authority IDs and distinct execution/MCP audiences; and
- the AgentCore region, Runtime ARN, and optional endpoint qualifier.
Some managed PostgreSQL providers expose an IPv6-only direct endpoint. An IPv4-only host should use the provider's IPv4-capable session pooler rather than buying an address add-on solely for this demo.
Migrations are an explicit deployment step and ordinary startup never mutates the database schema:
docker run --rm \
--env-file /path/to/deployment.env \
lucid-server:local \
node apps/server/dist/migrate.jsThe migration environment only needs the database URL. Then start the same immutable image with the full configuration and signing-key secret mount. A new workspace is created with background checks disabled, so image startup and migrations alone do not initiate model work. Only an explicit operator resume or hosted conversation request can spend model/Runtime budget.
For this demo stage, local Terraform apply and an intentionally manual image rollout are easier to audit than merge-triggered deployment. CI should build and verify the image; automatic apply can wait until rollback, secret management, and environment promotion are worth operating.
Google provider configuration and the publishable browser key belong to the private deployment environment. The Google client secret stays only in Supabase; it is not an application, image, GitHub, or AWS secret.
The repository tests prove request signing, custom-header placement, strict SSE handling, cancellation propagation, configuration validation, and the paused database default without contacting AWS. They do not prove managed AgentCore header forwarding, microVM isolation, workload-role containment, runtime lifecycle, or real cost. Those claims require a separately approved, budget-bounded managed smoke test.