eve-manifest-authoring
Eve Manifest Authoring
Keep the manifest as the single source of truth for build and deploy behavior.
Minimal skeleton (v2)
schema: eve/compose/v2
project: my-project
registry: "eve" # Use managed registry by default for Eve apps
services:
api:
build:
context: ./apps/api # Build context directory
dockerfile: Dockerfile # Optional, defaults to context/Dockerfile
# image omitted by default; when build is present, Eve derives image name from service key
ports: [3000]
environment:
NODE_ENV: production
x-eve:
ingress:
public: true
port: 3000
environments:
staging:
pipeline: deploy
pipeline_inputs:
some_key: default_value
pipelines:
deploy:
steps:
- name: build
action:
type: build # Builds all services with build: config
- name: release
depends_on: [build]
action:
type: release
- name: deploy
depends_on: [release]
action:
type: deploy
Registry Image Labels
Some registries require package metadata for permission and ownership inheritance. Add these labels to your Dockerfiles when supported by your registry:
LABEL org.opencontainers.image.source="https://github.com/YOUR_ORG/YOUR_REPO"
LABEL org.opencontainers.image.description="Service description"
Why this matters: Metadata helps preserve repository ownership and improves traceability. The Eve builder injects these labels automatically, but including them in your Dockerfile is still recommended.
For multi-stage Dockerfiles, add the labels to the final stage (the production image).
Registry Modes
registry: "eve" # Eve-native registry (internal JWT auth)
registry: "none" # Disable registry handling (public images)
registry: # BYO registry (full object — see section below)
host: public.ecr.aws/w7c4v0w3
namespace: myorg
auth: { username_secret: REGISTRY_USERNAME, token_secret: REGISTRY_PASSWORD }
For BYO/private registries, provide:
registry:
host: public.ecr.aws/w7c4v0w3
namespace: myorg
auth:
username_secret: REGISTRY_USERNAME
token_secret: REGISTRY_PASSWORD
Managed Databases
Declare platform-provisioned databases with x-eve.role: managed_db:
services:
db:
x-eve:
role: managed_db
managed:
class: db.p1
engine: postgres
engine_version: "16"
Not deployed to K8s — provisioned by the orchestrator on first deploy.
Reference managed values elsewhere: ${managed.db.url}.
Eve-Migrate for Database Migrations
Use the platform's migration runner instead of Flyway, TypeORM, or Knex. It uses plain SQL files with timestamp prefixes, tracked in schema_migrations:
services:
migrate:
image: public.ecr.aws/w7c4v0w3/eve-horizon/migrate:latest
environment:
DATABASE_URL: ${managed.db.url}
MIGRATIONS_DIR: /migrations
x-eve:
role: job
files:
- source: db/migrations
target: /migrations
Migration files: db/migrations/20260312000000_initial_schema.sql. The x-eve.files directive mounts them into the container at /migrations.
In the pipeline, the migrate step must run after deploy (managed DB needs provisioning):
pipelines:
deploy:
steps:
- name: build
action: { type: build }
- name: release
depends_on: [build]
action: { type: release }
- name: deploy
depends_on: [release]
action: { type: deploy }
- name: migrate
depends_on: [deploy]
action: { type: job, service: migrate }
For local dev, use the same image via Docker Compose for parity:
# docker-compose.yml
services:
migrate:
image: ghcr.io/incept5/eve-migrate:latest
environment:
DATABASE_URL: postgres://app:app@db:5432/myapp
volumes:
- ./db/migrations:/migrations:ro
depends_on:
db: { condition: service_healthy }
Legacy manifests
If the repo still uses components: from older manifests, migrate to services:
and add schema: eve/compose/v2. Keep ports and env keys the same.
Services
- Provide
imageand optionallybuild(context and dockerfile). - Use
ports,environment,healthcheck,depends_onas needed. - Use
x-eve.external: trueandx-eve.connection_urlfor externally hosted services. - Use
x-eve.role: jobfor one-off services (migrations, seeds). For database migrations, prefer Eve'seve-migrateimage (see below).
Build configuration
Services with Docker images should define their build configuration:
services:
api:
build:
context: ./apps/api # Build context directory
dockerfile: Dockerfile # Optional, defaults to context/Dockerfile
# image: api # optional if using build; managed registry derives this
ports: [3000]
Note: Every deploy pipeline should include a build step before release. The build step creates tracked BuildSpec/BuildRun records and produces image digests that releases use for deterministic deployments.
Local dev alignment
- Keep service names and ports aligned with Docker Compose.
- Prefer
${secret.KEY}and use.eve/dev-secrets.yamlfor local values.
Environments, pipelines, workflows
- Link each environment to a pipeline via
environments.<env>.pipeline. - When
pipelineis set,eve env deploy <env>triggers that pipeline instead of direct deploy. - Use
environments.<env>.pipeline_inputsto provide default inputs for pipeline runs. - Override inputs at runtime with
eve env deploy <env> --ref <sha> --inputs '{"key":"value"}' --repo-dir ./my-app. - Use
--directflag to bypass pipeline and do direct deploy:eve env deploy <env> --ref <sha> --direct --repo-dir ./my-app. - Pipeline steps can be
action,script, oragent. - Use
action.type: create-prfor PR automation when configured. - Workflows live under
workflowsand are invoked via CLI;db_accessis honored.
Platform-Injected Environment Variables
Eve automatically injects these into all deployed service containers:
| Variable | Description |
|---|---|
EVE_API_URL |
Internal cluster URL for server-to-server calls |
EVE_PUBLIC_API_URL |
Public ingress URL for browser-facing apps |
EVE_PROJECT_ID |
The project ID |
EVE_ORG_ID |
The organization ID |
EVE_ENV_NAME |
The environment name |
Use EVE_API_URL for backend calls from your container. Use EVE_PUBLIC_API_URL for
browser/client-side code. Services can override these in their environment section.
Interpolation and secrets
- Env interpolation:
${ENV_NAME},${PROJECT_ID},${ORG_ID},${ORG_SLUG},${COMPONENT_NAME}. - Secret interpolation:
${secret.KEY}pulls from Eve secrets or.eve/dev-secrets.yaml. - Managed DB interpolation:
${managed.<service>.<field>}resolves at deploy time. - Use
.eve/dev-secrets.yamlfor local overrides; set real secrets via the API for production.
Eve extensions
- Top-level defaults via
x-eve.defaults(env, harness, harness_profile, harness_options, hints, git, workspace). - Top-level agent policy via
x-eve.agents(profiles, councils, availability rules). - Agent packs via
x-eve.packswith optionalx-eve.install_agentsdefaults. - Agent config paths via
x-eve.agents.config_pathandx-eve.agents.teams_path. - Chat routing config via
x-eve.chat.config_path. - Service extensions under
x-eve(ingress, role, api specs, worker pools). - API specs:
x-eve.api_specorx-eve.api_specs(spec URL relative to service by default).
Example:
x-eve:
agents:
version: 1
config_path: agents/agents.yaml
teams_path: agents/teams.yaml
chat:
config_path: agents/chat.yaml
install_agents: [claude-code, codex]
packs:
- source: ./skillpacks/my-pack
App Object Store
Status: Schema exists, provisioning logic pending. The database schema (
storage_bucketstable) and bucket naming convention are implemented. Automatic provisioning from the manifest is not yet wired.
Declare app-scoped object storage buckets in the manifest. Each bucket is provisioned per environment with credentials injected as environment variables.
services:
api:
x-eve:
object_store:
buckets:
- name: uploads
visibility: private
- name: avatars
visibility: public
cors:
allowed_origins: ["*"]
Auto-Injected Storage Environment Variables
When object store buckets are provisioned, these env vars are injected into the service container:
| Variable | Description |
|---|---|
STORAGE_ENDPOINT |
S3-compatible endpoint URL |
STORAGE_ACCESS_KEY |
Access key for the bucket |
STORAGE_SECRET_KEY |
Secret key for the bucket |
STORAGE_BUCKET |
Physical bucket name |
STORAGE_FORCE_PATH_STYLE |
true for MinIO (local dev), false for cloud |
Design Rules
- One bucket per concern. Separate
uploadsfromavatarsfromexports. - Set visibility intentionally. Only buckets serving public assets should be
visibility: public. - Use CORS for browser uploads. Set
cors.allowed_originswhen the frontend uploads directly via presigned URLs. - Bucket names must be unique within a service. The platform derives the physical bucket name from the project, environment, and logical name.
For detailed storage layer documentation, see the eve-read-eve-docs skill: references/object-store-filesystem.md.