eve-fullstack-app-design

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Full-Stack App Design on Eve Horizon

在Eve Horizon上设计全栈应用

Architect applications where the manifest is the blueprint, the platform handles infrastructure, and every design decision is intentional.
构建以清单为蓝图、平台托管基础设施、所有设计决策皆经过深思熟虑的应用。

When to Use

适用场景

Load this skill when:
  • Designing a new application from scratch on Eve
  • Migrating an existing app onto the platform
  • Evaluating whether your current architecture uses Eve's capabilities well
  • Planning service topology, database strategy, or deployment pipelines
  • Deciding between managed and external services
This skill teaches design thinking for Eve's PaaS layer. For CLI usage and operational detail, load the corresponding eve-se skills (
eve-manifest-authoring
,
eve-deploy-debugging
,
eve-auth-and-secrets
,
eve-pipelines-workflows
).
在以下场景中使用本技能:
  • 在Eve平台上从零设计新应用
  • 将现有应用迁移至Eve平台
  • 评估当前架构是否充分利用了Eve的能力
  • 规划服务拓扑、数据库策略或部署流水线
  • 在托管服务与外部服务之间做决策
本技能教授针对Eve PaaS层的设计思维。如需CLI用法和操作细节,请加载对应的eve-se技能(
eve-manifest-authoring
eve-deploy-debugging
eve-auth-and-secrets
eve-pipelines-workflows
)。

The Manifest as Blueprint

作为蓝图的清单

The manifest (
.eve/manifest.yaml
) is the single source of truth for your application's shape. Treat it as an architectural document, not just configuration.
清单(
.eve/manifest.yaml
)是应用形态的唯一可信来源。请将其视为架构文档,而非单纯的配置文件。

What the Manifest Declares

清单声明的内容

ConcernManifest SectionDesign Decision
Service topology
services
What processes run, how they connect
Infrastructure
services[].x-eve
Managed DB, ingress, roles
Build strategy
services[].build
+
registry
What gets built, where images live
Release pipeline
pipelines
How code flows from commit to production
Environment shape
environments
Which environments exist, what pipelines they use
Agent configuration
x-eve.agents
,
x-eve.chat
Agent profiles, team dispatch, chat routing
Runtime defaults
x-eve.defaults
Harness, workspace, git policies
Design principle: If an agent or operator can't understand your app's shape by reading the manifest, the manifest is incomplete.
关注点清单章节设计决策
服务拓扑
services
运行哪些进程、进程间如何连接
基础设施
services[].x-eve
托管数据库、入口规则、角色配置
构建策略
services[].build
+
registry
构建内容、镜像存储位置
发布流水线
pipelines
代码从提交到生产环境的流转路径
环境形态
environments
存在哪些环境、各环境使用的流水线
Agent配置
x-eve.agents
,
x-eve.chat
Agent配置文件、团队调度、聊天路由
运行时默认值
x-eve.defaults
资源调度、工作区、Git策略
设计原则:如果Agent或运维人员无法通过阅读清单理解应用的形态,说明清单不够完整。

Service Topology

服务拓扑

Choose Your Services

选择服务模式

Most Eve apps follow one of these patterns:
API + Database (simplest):
services:
  api:        # HTTP service with ingress
  db:         # managed Postgres
API + Worker + Database:
services:
  api:        # HTTP service (user-facing)
  worker:     # Background processor (jobs, queues)
  db:         # managed Postgres
Multi-Service:
services:
  web:        # Frontend/SSR
  api:        # Backend API
  worker:     # Background jobs
  db:         # managed Postgres
  redis:      # external cache (x-eve.external: true)
大多数Eve应用遵循以下模式之一:
API + 数据库(最简模式):
services:
  api:        # 带Ingress的HTTP服务
  db:         # 托管Postgres
API + Worker + 数据库
services:
  api:        # 面向用户的HTTP服务
  worker:     # 后台处理器(任务、队列)
  db:         # 托管Postgres
多服务模式
services:
  web:        # 前端/SSR服务
  api:        # 后端API
  worker:     # 后台任务
  db:         # 托管Postgres
  redis:      # 外部缓存(设置`x-eve.external: true`)

Service Design Rules

服务设计规则

  1. One concern per service. Separate HTTP serving from background processing. An API service should not also run scheduled jobs.
  2. Use managed DB for Postgres. Declare
    x-eve.role: managed_db
    and let the platform provision, connect, and inject credentials. No manual connection strings.
  3. Mark external services explicitly. Use
    x-eve.external: true
    with
    x-eve.connection_url
    for services hosted outside Eve (Redis, third-party APIs).
  4. Use
    x-eve.role: job
    for one-off tasks.
    Migrations, seeds, and data backfills are job services, not persistent processes.
  5. Expose ingress intentionally. Only services that need external HTTP access get
    x-eve.ingress.public: true
    . Internal services communicate via cluster networking.
  6. Choose a hostname strategy early. Every public service gets a generated platform URL by default. Layer on
    x-eve.ingress.alias
    for a friendlier platform-subdomain (
    ingest.eve.example.com
    ), or
    x-eve.ingress.domains: [limelee.com]
    to bring your own domain. Custom domains are env-scoped and first-bind-wins — design which environment owns the apex (usually
    production
    ) before declaring it. See
    eve-manifest-authoring
    and
    eve-deploy-debugging
    for declaration and DNS verification flow.
  1. 单一职责原则:将HTTP服务与后台处理分离。API服务不应同时运行定时任务。
  2. 使用托管Postgres数据库:声明
    x-eve.role: managed_db
    ,由平台负责数据库的部署、连接和凭证注入,无需手动配置连接字符串。
  3. 显式标记外部服务:对于Eve平台外的服务(如Redis、第三方API),需设置
    x-eve.external: true
    并配置
    x-eve.connection_url
  4. x-eve.role: job
    定义一次性任务
    :数据迁移、初始化填充等属于任务服务,而非持久运行进程。
  5. 谨慎配置Ingress:仅需对外提供HTTP访问的服务设置
    x-eve.ingress.public: true
    ,内部服务通过集群网络通信。
  6. 提前确定主机名策略:默认情况下,每个公共服务会获得平台生成的URL。可通过
    x-eve.ingress.alias
    设置更友好的平台子域名(如
    ingest.eve.example.com
    ),或通过
    x-eve.ingress.domains: [limelee.com]
    绑定自定义域名。自定义域名按环境划分,先绑定者生效——在声明前需确定哪个环境(通常是
    production
    )拥有主域名。具体声明和DNS验证流程请参考
    eve-manifest-authoring
    eve-deploy-debugging

Stable Outbound IPs (Egress)

稳定出口IP(Egress)

Most apps don't care about their outbound source IP — but if you integrate with vendors that allowlist source IPs (cameras, payment processors, partner APIs with strict source-IP rules), declare opt-in stable egress at the service level. The platform schedules the pod onto a public-egress node group with
hostNetwork: true
, giving the service a stable, predictable outbound path instead of a shared NAT mapping. Treat this as a deliberate architectural choice for the one or two services that need it — not a default.
大多数应用无需关注出口源IP,但如果您的应用需要与限制源IP的供应商集成(如摄像头、支付处理器、有严格源IP规则的合作API),可在服务级别声明启用稳定出口。平台会将Pod调度到启用
hostNetwork: true
的公共出口节点组,为服务提供稳定、可预测的出口路径,而非共享NAT映射。请将此视为针对特定服务的刻意架构选择,而非默认配置。

App Object Storage

应用对象存储

Apps that need to store files (uploads, avatars, exports) can declare object store buckets in the manifest:
yaml
services:
  api:
    x-eve:
      object_store:
        buckets:
          - name: uploads
            visibility: private
          - name: avatars
            visibility: public
Note: The database schema for app object stores exists, but automatic provisioning from the manifest is not yet wired. See
references/object-store-filesystem.md
for current status.
When wired, the platform injects
STORAGE_ENDPOINT
,
STORAGE_ACCESS_KEY
,
STORAGE_SECRET_KEY
,
STORAGE_BUCKET
, and
STORAGE_FORCE_PATH_STYLE
into the service container.
Credential isolation: app pods receive app-scoped storage credentials, not platform-internal credentials. A compromised app service can't reach platform buckets or other tenants' data. Design with this boundary in mind — don't try to share credentials across apps; declare each app's buckets and let the platform issue scoped keys.
需要存储文件(上传内容、头像、导出文件)的应用可在清单中声明对象存储桶:
yaml
services:
  api:
    x-eve:
      object_store:
        buckets:
          - name: uploads
            visibility: private
          - name: avatars
            visibility: public
注意:应用对象存储的数据库架构已存在,但目前尚未实现从清单自动创建存储桶的功能。请查看
references/object-store-filesystem.md
了解当前状态。
功能完善后,平台会将
STORAGE_ENDPOINT
STORAGE_ACCESS_KEY
STORAGE_SECRET_KEY
STORAGE_BUCKET
STORAGE_FORCE_PATH_STYLE
注入服务容器。
凭证隔离:应用Pod会收到应用级的存储凭证,而非平台内部凭证。即使应用服务被攻陷,也无法访问平台存储桶或其他租户的数据。设计时需注意此边界——不要尝试跨应用共享凭证,应为每个应用单独声明存储桶,由平台颁发范围限定的密钥。

Cloud FS / Google Drive Storage

云文件系统/Google Drive存储

For document-oriented storage, use cloud FS mounts. Each org connects its own Google Drive via BYOA OAuth credentials, then mounts folders into the org filesystem:
bash
eve integrations configure google-drive --client-id "..." --client-secret "..."
eve integrations connect google-drive
eve cloud-fs mount --org org_xxx --provider google-drive --folder-id <id> --label "Shared Drive"
Apps can browse and search mounted Drive content through Eve's Cloud FS surface (
eve cloud-fs ls
,
eve cloud-fs search
, and the per-mount Cloud FS API routes). This is complementary to object store buckets -- use cloud FS for shared documents and collaboration, use object store for app-managed binary assets.
对于面向文档的存储,可使用云文件系统挂载。每个组织可通过BYOA OAuth凭证连接自己的Google Drive,然后将文件夹挂载到组织文件系统:
bash
eve integrations configure google-drive --client-id "..." --client-secret "..."
eve integrations connect google-drive
eve cloud-fs mount --org org_xxx --provider google-drive --folder-id <id> --label "Shared Drive"
应用可通过Eve的Cloud FS界面(
eve cloud-fs ls
eve cloud-fs search
以及每个挂载点的Cloud FS API路由)浏览和搜索挂载的Drive内容。这与对象存储桶互为补充——使用云文件系统存储共享文档和协作内容,使用对象存储存储应用管理的二进制资产。

Platform-Injected Variables

平台注入的变量

Every deployed service receives
EVE_API_URL
,
EVE_PUBLIC_API_URL
,
EVE_PROJECT_ID
,
EVE_ORG_ID
, and
EVE_ENV_NAME
. Use
EVE_API_URL
for server-to-server calls. Use
EVE_PUBLIC_API_URL
for browser-facing code. Design your app to read these rather than hardcoding URLs.
每个部署的服务都会收到
EVE_API_URL
EVE_PUBLIC_API_URL
EVE_PROJECT_ID
EVE_ORG_ID
EVE_ENV_NAME
EVE_API_URL
用于服务器间调用,
EVE_PUBLIC_API_URL
用于浏览器端代码。设计应用时请读取这些变量,而非硬编码URL。

Reference Architecture: SPA + API + Managed DB

参考架构:SPA + API + 托管数据库

Use a public nginx SPA to proxy
/api/
to an internal Node service, backed by managed Postgres and a one-off migration job. This keeps the API off public ingress and gives the browser same-origin access.
Load
references/spa-api-managed-db.md
for the complete manifest, nginx template, Dockerfiles, migration layout, managed TLS rules, and transaction- scoped RLS implementation.
使用公共Nginx SPA将
/api/
请求代理到内部Node服务,后端使用托管Postgres和一次性迁移任务。这种架构可避免API暴露到公共Ingress,并为浏览器提供同源访问权限。
加载
references/spa-api-managed-db.md
获取完整清单、Nginx模板、Dockerfile、迁移目录结构、托管TLS规则以及事务范围的RLS实现细节。

Database Design

数据库设计

Declare Postgres with
x-eve.role: managed_db
and consume
${managed.db.url}
. Keep its managed
sslmode=verify-full
; the platform injects the trust bundle and client environment. Never disable certificate verification.
Use timestamped plain-SQL migrations, design tenant-owned tables with
org_id TEXT NOT NULL
and RLS from the start, and set tenant context inside a transaction before every query. Inspect before changing with
eve db schema
and
eve db sql --env <env>
. Keep product data separate from agent memory and coordination storage.
Load
references/spa-api-managed-db.md
for the managed DB declaration, transaction wrapper, RLS policy template, and access conventions.
通过
x-eve.role: managed_db
声明Postgres数据库,并使用
${managed.db.url}
连接。请保持默认的
sslmode=verify-full
配置,平台会注入信任证书和客户端环境。切勿禁用证书验证。
使用带时间戳的纯SQL迁移脚本,从一开始就为租户所属表设计
org_id TEXT NOT NULL
字段和RLS,并在每次查询前的事务中设置租户上下文。修改前可通过
eve db schema
eve db sql --env <env>
检查数据库状态。请将产品数据与Agent内存和协调存储分开。
加载
references/spa-api-managed-db.md
获取托管数据库声明、事务包装器、RLS策略模板和访问约定。

Build and Release Pipeline

构建与发布流水线

The Canonical Flow

标准流程

Every production app should follow
build → release → deploy → migrate → smoke-test
:
yaml
pipelines:
  deploy:
    steps:
      - name: build
        action:
          type: build          # Creates BuildSpec + BuildRun, produces image digests
      - name: release
        depends_on: [build]
        action:
          type: release        # Creates immutable release from build artifacts
      - name: deploy
        depends_on: [release]
        action:
          type: deploy         # Deploys release to target environment
      - name: migrate
        depends_on: [deploy]
        action:
          type: job
          service: migrate     # Runs eve-migrate against the managed DB
      - name: smoke-test
        depends_on: [migrate]
        script:
          run: ./scripts/smoke-test.sh
          timeout: 300
Why this order matters:
  • build
    produces SHA256 image digests.
    release
    pins those exact digests.
    deploy
    uses the pinned release. You deploy exactly what you built — no tag drift, no "latest" surprises.
  • migrate
    runs after deploy because the managed DB must be provisioned first. The eve-migrate job applies any pending SQL migrations.
  • smoke-test
    validates the deployed services end-to-end before the pipeline reports success.
每个生产应用应遵循
构建 → 发布 → 部署 → 迁移 → 冒烟测试
的流程:
yaml
pipelines:
  deploy:
    steps:
      - name: build
        action:
          type: build          # 创建BuildSpec + BuildRun,生成镜像摘要
      - 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     # 针对托管数据库运行eve-migrate
      - name: smoke-test
        depends_on: [migrate]
        script:
          run: ./scripts/smoke-test.sh
          timeout: 300
此顺序的重要性
  • build
    生成SHA256镜像摘要,
    release
    固定这些摘要,
    deploy
    使用固定的发布版本。确保部署的内容与构建的内容完全一致,避免标签漂移或“latest”镜像带来的意外。
  • migrate
    deploy
    之后运行,因为托管数据库必须先完成部署。eve-migrate任务会应用所有待处理的SQL迁移。
  • smoke-test
    会在流水线报告成功前对部署的服务进行端到端验证。

Registry Decisions

镜像仓库选择

OptionWhen to Use
registry: "eve"
Default. Internal registry with JWT auth. Simplest setup.
BYO registry (GHCR, ECR)When you need images accessible outside Eve, or have existing CI.
registry: "none"
Public base images only. No custom builds.
For GHCR, add OCI labels to Dockerfiles for automatic repository linking:
dockerfile
LABEL org.opencontainers.image.source="https://github.com/YOUR_ORG/YOUR_REPO"
选项适用场景
registry: "eve"
默认选项。带JWT认证的内部仓库,设置最简单。
自定义仓库(GHCR、ECR)需要镜像可在Eve外部访问,或已有CI流程时使用。
registry: "none"
仅使用公共基础镜像,无需自定义构建。
若使用GHCR,请在Dockerfile中添加OCI标签以实现自动仓库关联:
dockerfile
LABEL org.opencontainers.image.source="https://github.com/YOUR_ORG/YOUR_REPO"

Build Configuration

构建配置

Every service with a custom image needs a
build
section:
yaml
services:
  api:
    build:
      context: ./apps/api
      dockerfile: Dockerfile
    image: ghcr.io/org/my-api
Use multi-stage Dockerfiles. BuildKit handles them natively. Place the OCI label on the final stage.
每个需要自定义镜像的服务都需要
build
章节:
yaml
services:
  api:
    build:
      context: ./apps/api
      dockerfile: Dockerfile
    image: ghcr.io/org/my-api
使用多阶段Dockerfile,BuildKit原生支持该特性。请在最终阶段添加OCI标签。

Deployment and Environments

部署与环境

Environment Strategy

环境策略

EnvironmentTypePurposePipeline
staging
persistentIntegration testing, demos
deploy
production
persistentLive traffic
deploy
(with promotion)
preview-*
temporaryPR previews, feature branches
deploy
(auto-cleanup)
Link each environment to a pipeline in the manifest:
yaml
environments:
  staging:
    pipeline: deploy
  production:
    pipeline: deploy
环境类型用途流水线
staging
持久化集成测试、演示
deploy
production
持久化生产流量
deploy
(需版本推广)
preview-*
临时PR预览、特性分支
deploy
(自动清理)
在清单中为每个环境关联流水线:
yaml
environments:
  staging:
    pipeline: deploy
  production:
    pipeline: deploy

Deployment Patterns

部署模式

Standard deploy:
eve env deploy staging --ref main --repo-dir .
triggers the linked pipeline.
Direct deploy (bypass pipeline):
eve env deploy staging --ref <sha> --direct
for emergencies or simple setups.
Promotion: Build once in staging, then promote the same release artifacts to production. The build step's digests carry forward, guaranteeing identical images.
标准部署
eve env deploy staging --ref main --repo-dir .
触发关联的流水线。
直接部署(跳过流水线):
eve env deploy staging --ref <sha> --direct
用于紧急情况或简单部署场景。
版本推广:在staging环境构建一次,然后将相同的发布产物推广到production环境。构建步骤的镜像摘要会被保留,确保镜像完全一致。

Recovery

故障恢复

When a deploy fails:
  1. Diagnose:
    eve env diagnose <project> <env>
    — shows health, recent deploys, service status.
  2. Logs:
    eve env logs <project> <env>
    — container output.
  3. Rollback: Redeploy the previous known-good release.
  4. Reset:
    eve env reset <project> <env>
    — nuclear option, reprovisions from scratch.
Design your app to be rollback-safe: migrations should be forward-compatible, and services should handle schema version mismatches gracefully during rolling deploys.
部署失败时:
  1. 诊断
    eve env diagnose <project> <env>
    —— 查看健康状态、最近部署记录、服务状态。
  2. 日志
    eve env logs <project> <env>
    —— 查看容器输出。
  3. 回滚:重新部署上一个已知可用的版本。
  4. 重置
    eve env reset <project> <env>
    —— 终极方案,重新从零部署环境。
设计应用时需确保支持回滚:迁移脚本需向前兼容,服务需能在滚动部署期间优雅处理架构版本不匹配的情况。

The System App Pattern

系统应用模式

Platform-tier and admin apps deploy through the same Eve pipeline as customer apps — no special path. The Eve Dashboard is the canonical example: it ships through the standard build → release → deploy flow, sits in the CI publish matrix alongside other apps, and consumes the same SSO + analytics APIs any customer app would. If you're building an internal admin console, a control plane for your own platform, or a system-tier surface, adopt this pattern. The win is parity: one deployment story, one auth story, one observability story across all your apps. Avoid carving out bespoke "platform-only" deploy paths — they rot and diverge.
平台级和管理应用与客户应用通过相同的Eve流水线部署——无需特殊路径。Eve Dashboard就是典型示例:它通过标准的
构建 → 发布 → 部署
流程发布,与其他应用一起纳入CI发布矩阵,并使用所有客户应用都能访问的SSO + 分析API。如果您正在构建内部管理控制台、自有平台的控制平面或系统级界面,请采用此模式。优势在于一致性:所有应用使用相同的部署流程、认证流程和可观测性流程。避免定制“仅平台可用”的部署路径——这类路径会逐渐过时并与标准流程脱节。

Per-Org OAuth for App Integrations

应用集成的按组织OAuth

Apps that integrate with Google Drive, Slack, or other OAuth providers use per-org credentials (BYOA -- Bring Your Own App). Each org registers its own OAuth app, giving it control over branding, scopes, rate limits, and credential rotation.
bash
eve integrations configure google-drive --client-id "..." --client-secret "..."
eve integrations connect google-drive
Design implications: Apps that consume Google Drive data or Slack messages should reference integration tokens through the Eve API, not store OAuth credentials themselves. The platform handles token refresh using the org's registered OAuth app credentials.
与Google Drive、Slack或其他OAuth供应商集成的应用使用按组织划分的凭证(BYOA——Bring Your Own App)。每个组织注册自己的OAuth应用,从而控制品牌、权限范围、速率限制和凭证轮换。
bash
eve integrations configure google-drive --client-id "..." --client-secret "..."
eve integrations connect google-drive
设计影响:使用Google Drive数据或Slack消息的应用应通过Eve API引用集成令牌,而非自行存储OAuth凭证。平台会使用组织注册的OAuth应用凭证处理令牌刷新。

Event Triggers for Workflows

工作流的事件触发

Workflows can be triggered by platform events, enabling reactive automation:
yaml
workflows:
  on-deploy:
    trigger:
      system.event: environment.deployed
    steps:
      - name: smoke-test
        script:
          run: ./scripts/smoke-test.sh

  on-ingest:
    trigger:
      system.event: doc.ingest.completed
    steps:
      - name: process
        agent: doc-processor
Event sources include: GitHub webhooks, Slack events, system events (deploy, build, ingest), cron schedules, and manual triggers. See
eve-pipelines-workflows
for trigger syntax and
references/events.md
for the full event catalog.
工作流可由平台事件触发,实现响应式自动化:
yaml
workflows:
  on-deploy:
    trigger:
      system.event: environment.deployed
    steps:
      - name: smoke-test
        script:
          run: ./scripts/smoke-test.sh

  on-ingest:
    trigger:
      system.event: doc.ingest.completed
    steps:
      - name: process
        agent: doc-processor
事件源包括:GitHub webhook、Slack事件、系统事件(部署、构建、导入)、定时任务和手动触发。请查看
eve-pipelines-workflows
了解触发语法,查看
references/events.md
获取完整事件目录。

App CLI Framework — The Eve Way

应用CLI框架——Eve风格

Every app with an API should ship a CLI. This is the Eve way — agents interact with app data through CLI commands, not raw REST calls. A CLI gives agents discoverable, auth-transparent, type-safe access to your app's domain. It reduces LLM calls per operation from 3-5 (curl) to 1 (CLI command), eliminates URL construction and JSON quoting, and surfaces domain-specific error messages instead of HTTP status codes.
每个带API的应用都应提供CLI。这是Eve的标准做法——Agent通过CLI命令与应用数据交互,而非直接调用REST接口。CLI为Agent提供可发现、认证透明、类型安全的应用领域访问方式。它将每个操作的LLM调用次数从3-5次(curl方式)减少到1次(CLI命令),无需构造URL和转义JSON,并提供领域特定的错误信息而非HTTP状态码。

Why CLI-First Matters

CLI优先的重要性

When a coding agent needs to read or write app data, it faces a choice: construct a curl command with the right URL, auth header, and JSON body — or run
eden projects list --json
. The CLI approach wins on every dimension:
DimensionCLIRaw REST
AuthInvisible (
EVE_JOB_TOKEN
read automatically)
Manual header construction
URLNone (CLI knows the service URL)Build from
EVE_APP_API_URL_*
Discoverability
myapp --help
Read OpenAPI spec or docs
ErrorsDomain-specific messagesHTTP status codes
LLM cost1 call per operation3-5 calls per operation
当编码Agent需要读写应用数据时,它有两种选择:构造包含正确URL、认证头和JSON体的curl命令,或运行
eden projects list --json
。CLI方式在各维度都更具优势:
维度CLI原生REST
认证自动处理(自动读取
EVE_JOB_TOKEN
手动构造请求头
URL无需构造(CLI知晓服务URL)
EVE_APP_API_URL_*
拼接
可发现性
myapp --help
阅读OpenAPI规范或文档
错误处理领域特定消息HTTP状态码
LLM成本每个操作1次调用每个操作3-5次调用

Declare the CLI in the Manifest

在清单中声明CLI

yaml
services:
  api:
    x-eve:
      api_spec:
        type: openapi
      cli:
        name: myapp              # Binary name on $PATH
        bin: cli/bin/myapp       # Pre-bundled executable (repo-bundled mode)
The platform auto-discovers services with
x-eve.cli
from the manifest and makes them available on
$PATH
for all agent jobs in the project — no explicit
with_apis
needed. Just declare the CLI in the manifest and every agent gets it. Agents run
myapp --help
to discover capabilities. See
eve-manifest-authoring
for declaration details and
references/app-cli.md
for the full implementation pattern (bundling, env var contract, testing).
yaml
services:
  api:
    x-eve:
      api_spec:
        type: openapi
      cli:
        name: myapp              # $PATH中的二进制文件名
        bin: cli/bin/myapp       # 预打包的可执行文件(仓库打包模式)
平台会自动从清单中发现带有
x-eve.cli
的服务,并将其添加到项目中所有Agent任务的
$PATH
——无需显式配置
with_apis
。只需在清单中声明CLI,所有Agent即可使用。Agent可通过
myapp --help
发现功能。请查看
eve-manifest-authoring
了解声明细节,查看
references/app-cli.md
获取完整实现模式(打包、环境变量约定、测试)。

Design Guidance

设计指南

  1. Build the CLI early. Don't wait until the API is "done." Start the CLI alongside the first API endpoints. Agents will use it immediately.
  2. Mirror the API surface. Every REST endpoint should have a CLI subcommand.
    GET /items
    myapp items list
    ,
    POST /items
    myapp items create --file data.json
    .
  3. Support
    --json
    everywhere.
    Default output is human-readable tables;
    --json
    gives machine-readable output for agent pipelines.
  4. Bundle as a single file. Use esbuild to produce a self-contained Node.js script committed to the repo. Zero startup latency.
  5. Point agent skills at the CLI. Skill instructions should say "Use
    myapp items list
    ", never "curl the API at..."
  1. 尽早构建CLI:不要等到API“完成”才开始。在开发第一个API端点时就同步开发CLI,Agent会立即使用它。
  2. 镜像API界面:每个REST端点都应有对应的CLI子命令。例如
    GET /items
    对应
    myapp items list
    POST /items
    对应
    myapp items create --file data.json
  3. 全局支持
    --json
    参数
    :默认输出为人类可读的表格,
    --json
    参数提供机器可读的输出以支持Agent流水线。
  4. 打包为单文件:使用esbuild生成独立的Node.js脚本并提交到仓库,实现零启动延迟。
  5. 引导Agent技能使用CLI:技能说明应写“使用
    myapp items list
    ”,而非“调用API的...接口”。

Embedded Conversations

嵌入式对话

If your app has a chat surface — a sidebar pane, an inline assistant, an "ask about this object" button — use Eve's embedded conversation API and chat SDK. Don't hand-roll auth, dispatch, SSE, reconnect, or optimistic-send. The platform exposes find-or-create thread routing keyed by an app-supplied identifier (e.g.
myapp:{project_id}:{conversation_id}
), JWKS-verified browser tokens, and a replayable SSE stream — composed into
@eve-horizon/chat
and
@eve-horizon/chat-react
for ~50 lines of UI code.
Design implications:
  • Map your product objects (a document, a project, a ticket) to Eve threads by stable key. The platform owns thread state; your app owns product projections that reference
    thread_id
    .
  • Route through
    chat.yaml
    , an agent, a team, or a workflow using the same primitives external gateways use. Chat is just another dispatch target.
  • Phase 1 push uses SSE with snapshot + polling catch-up; design your UI to tolerate brief reconnects rather than assuming a persistent socket.
For SDK shape and routing patterns, see
references/eve-sdk.md
in the
eve-read-eve-docs
skill.
如果您的应用包含聊天界面——侧边栏、内嵌助手、“询问此对象”按钮,请使用Eve的嵌入式对话API和聊天SDK。无需自行实现认证、调度、SSE、重连或乐观发送逻辑。平台提供基于应用提供的标识符(如
myapp:{project_id}:{conversation_id}
)的查找或创建线程路由、JWKS验证的浏览器令牌,以及可重放的SSE流——这些功能已整合到
@eve-horizon/chat
@eve-horizon/chat-react
中,只需约50行UI代码即可实现。
设计影响
  • 将产品对象(文档、项目、工单)通过稳定的键映射到Eve线程。平台负责线程状态,应用负责存储引用
    thread_id
    的产品投影。
  • 使用与外部网关相同的原语,通过
    chat.yaml
    、Agent、团队或工作流进行路由。聊天只是另一个调度目标。
  • 第一阶段推送使用SSE加快照+轮询补全机制;设计UI时需容忍短暂的重连,而非假设连接始终保持。
有关SDK形态和路由模式,请查看
eve-read-eve-docs
技能中的
references/eve-sdk.md

App Undeploy/Delete Lifecycle

应用卸载/删除生命周期

Manage the full lifecycle of environments and projects:
bash
undefined
管理环境和项目的完整生命周期:
bash
undefined

Undeploy services (stops pods, keeps env record and history)

卸载服务(停止Pod,保留环境记录和历史)

eve env undeploy <project> <env>
eve env undeploy <project> <env>

Delete environment entirely (cascades to managed DB, secrets)

完全删除环境(级联删除托管数据库、密钥)

eve env delete <project> <env>
eve env delete <project> <env>

Delete project (cascades to all environments, artifacts, history)

删除项目(级联删除所有环境、产物、历史)

eve project delete <project-id>

Design your app for clean teardown: migrations should be idempotent, managed DB deletion is irreversible, and pipeline history is preserved in audit logs even after environment deletion.
eve project delete <project-id>

设计应用时需支持干净的销毁:迁移脚本需具备幂等性,托管数据库删除不可恢复,流水线历史会保留在审计日志中即使环境已删除。

Secrets and Configuration

密钥与配置

Scoping Model

作用域模型

Secrets resolve with cascading precedence: project > user > org > system. A project-level
API_KEY
overrides an org-level
API_KEY
.
密钥解析遵循级联优先级:项目 > 用户 > 组织 > 系统。项目级的
API_KEY
会覆盖组织级的
API_KEY

Design Rules

设计规则

  1. Set secrets per-project. Use
    eve secrets set KEY "value" --project proj_xxx
    . Keep project secrets self-contained.
  2. Use interpolation in the manifest. Reference
    ${secret.KEY}
    in service environment blocks. The platform resolves at deploy time.
  3. Validate before deploying. Run
    eve manifest validate --validate-secrets
    to catch missing secret references before they cause deploy failures.
  4. Use
    .eve/dev-secrets.yaml
    for local development.
    Mirror the production secret keys with local values. This file is gitignored.
  5. Never store secrets in environment variables directly. Always use
    ${secret.KEY}
    interpolation. This ensures secrets flow through the platform's resolution and audit chain.
  1. 按项目设置密钥:使用
    eve secrets set KEY "value" --project proj_xxx
    ,保持项目密钥独立。
  2. 在清单中使用插值:在服务环境块中引用
    ${secret.KEY}
    ,平台会在部署时解析。
  3. 部署前验证:运行
    eve manifest validate --validate-secrets
    检查缺失的密钥引用,避免部署失败。
  4. 使用
    .eve/dev-secrets.yaml
    进行本地开发
    :镜像生产环境的密钥键名,设置本地值。此文件需加入git忽略。
  5. 切勿直接将密钥存储在环境变量中:始终使用
    ${secret.KEY}
    插值,确保密钥通过平台的解析和审计流程流转。

Service Tokens (Manifest-Declared, Read-Only by Default)

服务令牌(清单声明,默认只读)

Services that call the Eve API on their own behalf get an auto-injected
EVE_SERVICE_TOKEN
. Permissions are declared explicitly per service in the manifest, and the default is read-only — services that need to write must opt in. Treat this as a least-privilege contract: a service shouldn't quietly gain write access by being deployed. Declare the minimum capabilities each service needs and let code review surface the deltas. See
references/secrets-auth.md
and
references/manifest.md
in
eve-read-eve-docs
for declaration syntax.
需要自行调用Eve API的服务会自动注入
EVE_SERVICE_TOKEN
。权限需在清单中按服务显式声明,默认权限为只读——需要写入权限的服务需主动开启。请将此视为最小权限约定:服务不应因部署而自动获得写入权限。为每个服务声明所需的最小权限,代码评审时可关注权限变更。请查看
eve-read-eve-docs
中的
references/secrets-auth.md
references/manifest.md
了解声明语法。

Scoped Job Tokens (Platform-Tier Least Privilege)

作用域限定的任务令牌(平台级最小权限)

For platform-tier apps that orchestrate jobs over multi-tenant resources, permission names alone are not enough —
orgfs:read
says nothing about which prefix. Declare resource scope on workflow steps to enforce least-privilege at the token level:
yaml
workflows:
  scoped-review:
    scope:
      orgfs: { allow_prefixes: [/groups/projects/proj-a/**] }
    steps:
      - name: review
        agent: { name: reviewer }
        scope:
          cloud_fs: { allow_mount_ids: [mount_a] }
Scope axes match access bindings:
orgfs
,
orgdocs
,
envdb
,
cloud_fs
. Workflow, step, and invocation scopes are intersected (empty intersection fails closed) and persisted as
jobs.token_scope
. The orchestrator uses the same scope to build the workspace
.org
mount and mint the job token — the on-disk view and the API authority match. Design platform-tier workflows so each step only sees the resources it actually needs.
对于在多租户资源上编排任务的平台级应用,仅靠权限名称不足以实现最小权限——
orgfs:read
并未指定哪个路径前缀。请在工作流步骤中声明资源作用域,在令牌层面强制执行最小权限:
yaml
workflows:
  scoped-review:
    scope:
      orgfs: { allow_prefixes: [/groups/projects/proj-a/**] }
    steps:
      - name: review
        agent: { name: reviewer }
        scope:
          cloud_fs: { allow_mount_ids: [mount_a] }
作用域维度与访问绑定一致:
orgfs
orgdocs
envdb
cloud_fs
。工作流、步骤和调用的作用域会相交(空交集会导致失败),并以
jobs.token_scope
的形式持久化。编排器会使用相同的作用域构建工作区
.org
挂载并生成任务令牌——磁盘视图与API权限保持一致。设计平台级工作流时,应确保每个步骤仅能访问实际需要的资源。

Git Credentials

Git凭证

Agents need repository access. Set either
github_token
(HTTPS) or
ssh_key
(SSH) as project secrets. The worker injects these automatically during git operations.
Agent需要仓库访问权限。请将
github_token
(HTTPS方式)或
ssh_key
(SSH方式)设置为项目密钥。Worker会在Git操作期间自动注入这些凭证。

SSO Authentication

SSO认证

Adding SSO to Your App

为应用添加SSO

Eve provides shared auth packages that eliminate boilerplate. Add Eve SSO login in ~25 lines of code.
Backend (
@eve-horizon/auth
):
typescript
import { eveUserAuth, eveAuthGuard, eveAuthConfig } from '@eve-horizon/auth';

app.use(eveUserAuth());                                     // Parse tokens (non-blocking)
app.get('/auth/config', eveAuthConfig());                   // Serve SSO discovery
app.get('/auth/me', eveAuthGuard(), (req, res) => {
  res.json(req.eveUser);                                    // { id, email, orgId, role }
});
app.use('/api', eveAuthGuard());                            // Protect all API routes
Frontend (
@eve-horizon/auth-react
):
tsx
import { EveAuthProvider, EveLoginGate } from '@eve-horizon/auth-react';

function App() {
  return (
    <EveAuthProvider apiUrl="/api">
      <EveLoginGate>
        <ProtectedApp />
      </EveLoginGate>
    </EveAuthProvider>
  );
}
For authenticated API calls from components, use
createEveClient
:
typescript
import { createEveClient } from '@eve-horizon/auth-react';
const client = createEveClient('/api');
const res = await client.fetch('/data');
Custom auth gate — When you need control over loading and login states (custom login page, richer loading UI), use
useEveAuth()
directly instead of
EveLoginGate
:
tsx
import { EveAuthProvider, useEveAuth } from '@eve-horizon/auth-react';

function AuthGate() {
  const { user, loading, loginWithToken, loginWithSso, logout } = useEveAuth();
  if (loading) return <Spinner />;
  if (!user) return <LoginPage onSso={loginWithSso} onToken={loginWithToken} />;
  return <AppShell user={user} onLogout={logout}><Routes /></AppShell>;
}

export default function App() {
  return (
    <EveAuthProvider apiUrl={API_BASE}>
      <AuthGate />
    </EveAuthProvider>
  );
}
Eve提供共享认证包,可消除重复代码。只需约25行代码即可添加Eve SSO登录功能。
后端
@eve-horizon/auth
):
typescript
import { eveUserAuth, eveAuthGuard, eveAuthConfig } from '@eve-horizon/auth';

app.use(eveUserAuth());                                     // 解析令牌(非阻塞)
app.get('/auth/config', eveAuthConfig());                   // 提供SSO发现信息
app.get('/auth/me', eveAuthGuard(), (req, res) => {
  res.json(req.eveUser);                                    // { id, email, orgId, role }
});
app.use('/api', eveAuthGuard());                            // 保护所有API路由
前端
@eve-horizon/auth-react
):
tsx
import { EveAuthProvider, EveLoginGate } from '@eve-horizon/auth-react';

function App() {
  return (
    <EveAuthProvider apiUrl="/api">
      <EveLoginGate>
        <ProtectedApp />
      </EveLoginGate>
    </EveAuthProvider>
  );
}
若要从组件中调用认证后的API,请使用
createEveClient
typescript
import { createEveClient } from '@eve-horizon/auth-react';
const client = createEveClient('/api');
const res = await client.fetch('/data');
自定义认证网关——当您需要控制加载和登录状态(自定义登录页面、更丰富的加载UI)时,请直接使用
useEveAuth()
而非
EveLoginGate
tsx
import { EveAuthProvider, useEveAuth } from '@eve-horizon/auth-react';

function AuthGate() {
  const { user, loading, loginWithToken, loginWithSso, logout } = useEveAuth();
  if (loading) return <Spinner />;
  if (!user) return <LoginPage onSso={loginWithSso} onToken={loginWithToken} />;
  return <AppShell user={user} onLogout={logout}><Routes /></AppShell>;
}

export default function App() {
  return (
    <EveAuthProvider apiUrl={API_BASE}>
      <AuthGate />
    </EveAuthProvider>
  );
}

How It Works

工作原理

  1. EveAuthProvider
    checks
    sessionStorage
    for cached token
  2. If no token, probes SSO broker
    /session
    (root-domain cookie)
  3. If SSO session exists, gets fresh Eve RS256 token
  4. If no session, shows login form (SSO redirect or token paste)
  5. All API requests include
    Authorization: Bearer <token>
  1. EveAuthProvider
    检查
    sessionStorage
    中是否有缓存的令牌
  2. 如果没有令牌,探测SSO代理的
    /session
    接口(根域Cookie)
  3. 如果存在SSO会话,获取新的Eve RS256令牌
  4. 如果没有会话,显示登录表单(SSO重定向或令牌粘贴)
  5. 所有API请求都会包含
    Authorization: Bearer <token>

NestJS Backend

NestJS后端

Apply
eveUserAuth()
as global middleware in
main.ts
. If existing controllers expect
req.user
rather than
req.eveUser
, add a thin bridge that maps Eve roles to app-specific roles in one place:
typescript
import { eveUserAuth } from '@eve-horizon/auth';

app.use(eveUserAuth());
app.use((req, _res, next) => {
  if (req.eveUser) {
    req.user = { ...req.eveUser, role: req.eveUser.role === 'member' ? 'viewer' : 'admin' };
  }
  next();
});
main.ts
中全局应用
eveUserAuth()
中间件。如果现有控制器期望
req.user
而非
req.eveUser
,可添加一个简单的桥接中间件,在一处将Eve角色映射为应用特定角色:
typescript
import { eveUserAuth } from '@eve-horizon/auth';

app.use(eveUserAuth());
app.use((req, _res, next) => {
  if (req.eveUser) {
    req.user = { ...req.eveUser, role: req.eveUser.role === 'member' ? 'viewer' : 'admin' };
  }
  next();
});

Auto-Injected Variables

自动注入的变量

The platform injects
EVE_SSO_URL
,
EVE_API_URL
,
EVE_ORG_ID
, and
EVE_PROJECT_ID
into deployed containers. No manual configuration needed. Use
${SSO_URL}
in manifest env blocks for frontend-accessible SSO URLs.
EVE_PROJECT_ID
is what enables the platform to scope branding, redirect allowlists, and app-scoped auth policy to your project.
平台会将
EVE_SSO_URL
EVE_API_URL
EVE_ORG_ID
EVE_PROJECT_ID
注入部署的容器,无需手动配置。在清单的环境块中使用
${SSO_URL}
供前端访问SSO URL。
EVE_PROJECT_ID
用于平台将品牌、重定向允许列表和应用级认证策略限定到您的项目。

Passwordless / Magic-Link Apps

无密码/魔法链接应用

If your app's onboarding is "admin invites a user, user clicks email, user lands in app" — model it as a passwordless app. Don't build a password reset flow you don't need. Declare it in the manifest and let the platform render a branded magic-link login page:
yaml
x-eve:
  auth:
    login_method: magic_link            # or password_or_magic_link, password
    self_signup: false                  # unknown emails return generic success, no email
    invite_requires_password: false     # invite acceptance skips /set-password
Design implications:
  • Users are created through invites, not self-signup. Plan your admin invite UX accordingly.
  • The magic-link email reuses the same
    x-eve.branding
    block as invite emails — one branding source, two email copies.
  • Eve API handles eligibility (existing user, pending invite, domain signup) before any email is sent, so account-enumeration defense is preserved without app-side work.
如果您的应用采用“管理员邀请用户,用户点击邮件链接进入应用”的入职流程,请将其设计为无密码应用。无需构建不需要的密码重置流程。在清单中声明,由平台渲染品牌化的魔法链接登录页面:
yaml
x-eve:
  auth:
    login_method: magic_link            # 可选值:password_or_magic_link、password
    self_signup: false                  # 未知邮箱返回通用成功信息,不发送邮件
    invite_requires_password: false     # 接受邀请时跳过/set-password步骤
设计影响
  • 用户通过邀请创建,而非自行注册。请相应规划管理员邀请的UX。
  • 魔法链接邮件与邀请邮件使用相同的
    x-eve.branding
    配置块——一处配置品牌,两处邮件复用。
  • Eve API会在发送邮件前验证用户资格(已有用户、待处理邀请、域名注册),无需在应用端实现账号枚举防护。

App Branding (Invites and Magic-Link Emails)

应用品牌(邀请与魔法链接邮件)

Per-app branding is a manifest concern, not a code concern. Declare it once and the platform applies it to invite emails, magic-link emails, and SSO login pages:
yaml
x-eve:
  branding:
    app_name: "ACME Portal"
    app_logo_url: "https://app.example.com/assets/logo.svg"
    primary_color: "#1f6feb"
    email_from_name: "ACME Portal"
    reply_to_email: "support@example.com"
    support_email: "support@example.com"
    support_url: "https://example.com/help"
The
From:
display name and email body carry the app identity; the sender address remains the platform default (verified per-tenant
From:
is a later phase). Treat branding as a property of the project, not a per-org concern.
应用级品牌是清单的配置项,而非代码实现。只需声明一次,平台会将其应用到邀请邮件、魔法链接邮件和SSO登录页面:
yaml
x-eve:
  branding:
    app_name: "ACME Portal"
    app_logo_url: "https://app.example.com/assets/logo.svg"
    primary_color: "#1f6feb"
    email_from_name: "ACME Portal"
    reply_to_email: "support@example.com"
    support_email: "support@example.com"
    support_url: "https://example.com/help"
邮件的
From:
显示名称和正文会携带应用标识;发件地址仍为平台默认值(后续阶段会支持按租户验证的
From:
地址)。请将品牌视为项目的属性,而非按组织划分的配置。

App Org Access and In-App Admin Invites

应用组织访问与应用内管理员邀请

By default an app is scoped to its project owner org. For multi-tenant apps that serve multiple customer orgs, declare an allowlist and (optionally) enable in-app admin invites:
yaml
x-eve:
  auth:
    org_access:
      mode: allowlist
      allowed_orgs: [org_customer123, customer-slug]
      invite:
        enabled: true
        admin_roles: [admin, owner]
        invited_role: member          # fixed; app invites cannot create admins
Design implications:
  • Backends should use
    eveAppUserAuth()
    (not
    eveUserAuth()
    ) so authorization is bound to the app policy, not the project owner org. The middleware consults
    GET /auth/app-access
    and selects an org from
    X-Eve-Org-Id
    ,
    ?eve_org_id=
    , or the first allowed org.
  • Build admin pages around
    POST /auth/app-invites
    (sends branded magic-link onboarding) instead of generic org-invite APIs. The platform enforces org role + app allowlist policy before sending.
  • The React SDK exposes
    useEveAppAccess()
    for orgs/admin-org listings and inviting members.
默认情况下,应用限定为项目所属组织使用。如需构建服务多个客户组织的多租户应用,请声明允许列表并(可选)启用应用内管理员邀请:
yaml
x-eve:
  auth:
    org_access:
      mode: allowlist
      allowed_orgs: [org_customer123, customer-slug]
      invite:
        enabled: true
        admin_roles: [admin, owner]
        invited_role: member          # 固定值;应用邀请无法创建管理员
设计影响
  • 后端应使用
    eveAppUserAuth()
    (而非
    eveUserAuth()
    ),使授权绑定到应用策略,而非项目所属组织。中间件会调用
    GET /auth/app-access
    并从
    X-Eve-Org-Id
    ?eve_org_id=
    或第一个允许的组织中选择组织。
  • 围绕
    POST /auth/app-invites
    构建管理员页面(发送品牌化的魔法链接入职邮件),而非使用通用的组织邀请API。平台会在发送前验证组织角色+应用允许列表策略。
  • React SDK提供
    useEveAppAccess()
    用于组织/管理员组织列表和邀请成员。

Domain-Based Signup (Path C Auto-Attach)

基于域名的注册(路径C自动关联)

When an app needs to serve a whole customer email domain — "anyone with a
@yourcompany.com
address should land in
org_yourcompany
as a member" — use domain signup. Eve writes a one-shot invite on first magic-link request and auto-attaches membership when the user accepts. One project can route different domains to different orgs:
yaml
x-eve:
  auth:
    org_access:
      mode: allowlist
      allowed_orgs: [org_acme, org_globex]
      domain_signup:
        enabled: true
        domains:
          - { domain: acme.com,   target_org: org_acme,   role: member }
          - { domain: globex.com, target_org: org_globex }
Design implications:
  • Rules are walked in declaration order — first match wins. Declare more-specific patterns first.
  • The trust model is "operator declares, platform trusts" — no DNS proof in v1. Declaring
    free-mail.example
    produces a coherence warning but is permitted.
  • Explicit pending invites (Path B) always win over domain signup (Path C); existing users with allowed-org membership (Path A) get the standard branded send.
  • Removing a rule stops new signups but does not retroactively remove existing memberships — plan offboarding as an explicit
    eve org members remove
    .
  • Audit via
    auth.domain_signup.invite_created
    and
    auth.domain_signup.member_attached
    events.
如果应用需要服务整个客户邮箱域名——“所有
@yourcompany.com
邮箱用户应自动加入
org_yourcompany
并成为成员”,请使用域名注册功能。Eve会在首次魔法链接请求时生成一次性邀请,并在用户接受时自动关联成员身份。一个项目可将不同域名路由到不同组织:
yaml
x-eve:
  auth:
    org_access:
      mode: allowlist
      allowed_orgs: [org_acme, org_globex]
      domain_signup:
        enabled: true
        domains:
          - { domain: acme.com,   target_org: org_acme,   role: member }
          - { domain: globex.com, target_org: org_globex }
设计影响
  • 规则按声明顺序匹配——第一个匹配项生效。请先声明更具体的规则。
  • 信任模型为“运维人员声明,平台信任”——v1版本无需DNS验证。声明
    free-mail.example
    会产生一致性警告,但仍允许使用。
  • 显式的待处理邀请(路径B)始终优先于域名注册(路径C);已有允许组织成员身份的用户(路径A)会收到标准的品牌化邮件。
  • 删除规则会停止新注册,但不会追溯移除现有成员身份——请将离职处理规划为显式的
    eve org members remove
    操作。
  • 可通过
    auth.domain_signup.invite_created
    auth.domain_signup.member_attached
    事件进行审计。

Project-Scoped Redirect Allowlist (Custom Domains)

项目级重定向允许列表(自定义域名)

If your app runs on its own custom domain (not under the cluster domain), declare which origins SSO may redirect to. Without this, SSO rewrites the redirect to the platform-default hostname and your branded app URL is lost:
yaml
x-eve:
  auth:
    allowed_redirect_origins:
      - https://app.example.com
      - https://www.example.com
The final allowlist is the union of manifest entries, the project's own eligible custom domains, and (for
mode: allowlist
) cross-org custom domains owned by projects in
allowed_orgs
. This replaces the legacy hard-coded
EVE_DEFAULT_DOMAIN
allowlist. The platform also guarantees
SameSite=None; Secure
on SSO session cookies so cross-site
/session
probes from your custom-domain frontend carry credentials — you no longer need to configure cookie attributes yourself.
如果应用运行在自定义域名(而非集群域名下),请声明SSO允许重定向的源。否则,SSO会将重定向地址改写为平台默认主机名,导致应用的品牌化URL丢失:
yaml
x-eve:
  auth:
    allowed_redirect_origins:
      - https://app.example.com
      - https://www.example.com
最终的允许列表是清单条目、项目自身的合格自定义域名,以及(对于
mode: allowlist
allowed_orgs
中项目所属的跨组织自定义域名的并集。这取代了旧版硬编码的
EVE_DEFAULT_DOMAIN
允许列表。平台还会确保SSO会话Cookie设置
SameSite=None; Secure
,以便自定义域名前端的跨域
/session
探测能携带凭证——您无需自行配置Cookie属性。

Design Rules

设计规则

  1. Use the SDK, not custom auth. The SDK replaces ~750 lines of hand-rolled auth with ~50 lines.
  2. Non-blocking middleware first. Use
    eveUserAuth()
    globally, then
    eveAuthGuard()
    on protected routes. This enables mixed public/private routes.
  3. The
    /auth/config
    endpoint is the handshake.
    The frontend discovers the SSO URL by calling the backend's
    eveAuthConfig()
    endpoint. This decouples the frontend from platform env vars and works identically in local dev and deployed environments.
  4. Design for token staleness. The
    orgs
    JWT claim reflects membership at mint time (1-day TTL). Use
    strategy: 'remote'
    for immediate revocation if needed.
For full SDK reference, see
references/auth-sdk.md
in the
eve-read-eve-docs
skill.
  1. 使用SDK,而非自定义认证:SDK用约50行代码替代了约750行手写认证代码。
  2. 先使用非阻塞中间件:全局使用
    eveUserAuth()
    ,然后在受保护路由上使用
    eveAuthGuard()
    ,支持混合公共/私有路由。
  3. /auth/config
    端点是握手点
    :前端通过调用后端的
    eveAuthConfig()
    端点发现SSO URL,使前端与平台环境变量解耦,在本地开发和部署环境中表现一致。
  4. 针对令牌过期设计
    orgs
    JWT声明反映令牌生成时的成员身份(TTL为1天)。如需立即撤销权限,请使用
    strategy: 'remote'
完整SDK参考请查看
eve-read-eve-docs
技能中的
references/auth-sdk.md

Observability and Debugging

可观测性与调试

The Debugging Ladder

调试阶梯

Escalate through these stages:
1. Status    → eve env show <project> <env>
2. Diagnose  → eve env diagnose <project> <env>
3. Logs      → eve env logs <project> <env>
4. Pipeline  → eve pipeline logs <pipeline> <run-id> --follow
5. Recover   → eve env deploy (rollback) or eve env reset
Start at the top. Each stage provides more detail and more cost. Most issues resolve at stages 1-2.
按以下阶段逐步排查:
1. 状态    → eve env show <project> <env>
2. 诊断  → eve env diagnose <project> <env>
3. 日志      → eve env logs <project> <env>
4. 流水线  → eve pipeline logs <pipeline> <run-id> --follow
5. 恢复   → eve env deploy(回滚)或eve env reset
从最上层开始排查。每个阶段提供的细节更多,但成本也更高。大多数问题可在1-2阶段解决。

Pipeline Observability

流水线可观测性

Monitor pipeline execution in real time:
bash
eve pipeline logs <pipeline> <run-id> --follow         # stream all steps
eve pipeline logs <pipeline> <run-id> --follow --step build  # stream one step
Failed steps include failure hints and link to build diagnostics when applicable.
实时监控流水线执行:
bash
eve pipeline logs <pipeline> <run-id> --follow         # 流式查看所有步骤日志
eve pipeline logs <pipeline> <run-id> --follow --step build  # 流式查看单个步骤日志
失败步骤会包含失败提示,并在适用时链接到构建诊断信息。

Build Debugging

构建调试

When builds fail:
bash
eve build list --project <project_id>
eve build diagnose <build_id>
eve build logs <build_id>
Common causes: missing registry credentials, Dockerfile path mismatch, build context too large.
构建失败时:
bash
eve build list --project <project_id>
eve build diagnose <build_id>
eve build logs <build_id>
常见原因:缺少仓库凭证、Dockerfile路径不匹配、构建上下文过大。

Health Checks

健康检查

Design services with health endpoints. Eve polls health to determine deployment readiness. A deploy is complete when
ready === true
and
active_pipeline_run === null
.
为服务设计健康检查端点。Eve会轮询健康状态以确定部署是否就绪。当
ready === true
active_pipeline_run === null
时,部署完成。

Design Checklist

设计检查清单

Service Topology:
  • Each service has one responsibility
  • Managed DB declared for Postgres needs
  • External services marked with
    x-eve.external: true
  • Only public-facing services have ingress enabled
  • Platform-injected env vars used (not hardcoded URLs)
  • Hostname strategy chosen (generated URL, alias, or custom domain via
    x-eve.ingress.domains
    )
  • Stable egress opted in only for services that integrate with source-IP-allowlisted vendors
Database:
  • Migrations are plain SQL files in
    db/migrations/
    with timestamp prefixes
  • eve-migrate
    job service declared in manifest with
    x-eve.files
    mount
  • DatabaseService
    wraps all DB access with RLS context (
    set_config
    )
  • RLS policies on every table with
    org_id
  • pgcrypto
    extension enabled, UUID primary keys,
    updated_at
    triggers
  • App data separated from agent data by schema or convention
Pipeline:
  • Canonical
    build → release → deploy → migrate → smoke-test
    pipeline defined
  • Migrate step runs after deploy (managed DB must exist first)
  • Smoke test script validates deployed services end-to-end
  • Registry chosen and credentials set as secrets
  • OCI labels on Dockerfiles (for GHCR)
  • Image digests flow through release (no tag-based deploys)
Environments:
  • Staging and production environments defined
  • Each environment linked to a pipeline
  • Promotion workflow defined (build once, deploy many)
  • Recovery procedure known (diagnose -> rollback -> reset)
Secrets:
  • All secrets set per-project via
    eve secrets set
  • Manifest uses
    ${secret.KEY}
    interpolation
  • eve manifest validate --validate-secrets
    passes
  • .eve/dev-secrets.yaml
    exists for local development
  • Git credentials (
    github_token
    or
    ssh_key
    ) configured
  • Service token permissions declared per service (default read-only; write opted in explicitly)
Authentication:
  • @eve-horizon/auth
    middleware added to backend (
    eveUserAuth
    +
    eveAuthGuard
    , or
    eveAppUserAuth
    for multi-org apps)
  • Auth config endpoint serves SSO discovery (
    eveAuthConfig
    )
  • @eve-horizon/auth-react
    wraps frontend (
    EveAuthProvider
    +
    EveLoginGate
    or custom
    useEveAuth
    gate)
  • createEveClient
    used for authenticated API calls from frontend
  • Platform-injected auth env vars used (
    EVE_SSO_URL
    ,
    EVE_ORG_ID
    ,
    EVE_PROJECT_ID
    )
  • Eve roles mapped to app roles in one place (bridge middleware), not scattered across controllers
  • If passwordless:
    x-eve.auth.login_method: magic_link
    +
    invite_requires_password: false
  • If multi-tenant:
    x-eve.auth.org_access.mode: allowlist
    with
    allowed_orgs
    declared; in-app admin invites use
    POST /auth/app-invites
  • If domain-based onboarding:
    domain_signup.domains
    declares per-rule
    target_org
    ; more-specific rules listed first
  • If custom domain:
    x-eve.auth.allowed_redirect_origins
    declared;
    eve project auth-context
    confirms resolved allowlist
  • If branded:
    x-eve.branding
    declared (shared by invite and magic-link emails);
    From:
    display name and logo set
App CLI (the Eve way):
  • App API wrapped in a domain CLI (e.g.,
    eden projects list
    )
  • CLI declared in manifest via
    x-eve.cli
    with
    name
    and
    bin
  • CLI bundled as single-file executable (esbuild for Node.js)
  • CLI reads
    EVE_APP_API_URL_{SERVICE}
    and
    EVE_JOB_TOKEN
    automatically
  • All CLI commands support
    --json
    for machine-readable output
  • Agent skill references CLI commands, not raw curl/REST calls
Observability:
  • Services expose health endpoints
  • The debugging ladder is understood (status -> diagnose -> logs -> recover)
  • Pipeline logs are accessible via
    eve pipeline logs --follow
服务拓扑
  • 每个服务单一职责
  • 为Postgres需求声明托管数据库
  • 外部服务标记
    x-eve.external: true
  • 仅面向公众的服务启用Ingress
  • 使用平台注入的环境变量(而非硬编码URL)
  • 确定主机名策略(生成URL、别名或通过
    x-eve.ingress.domains
    绑定自定义域名)
  • 仅为与限制源IP的供应商集成的服务启用稳定出口
数据库
  • 迁移脚本为
    db/migrations/
    目录下带时间戳前缀的纯SQL文件
  • 在清单中声明
    eve-migrate
    任务服务并配置
    x-eve.files
    挂载
  • DatabaseService
    使用RLS上下文(
    set_config
    )封装所有数据库访问
  • 每个带
    org_id
    的表都配置RLS策略
  • 启用
    pgcrypto
    扩展,使用UUID主键和
    updated_at
    触发器
  • 应用数据与Agent数据按架构或约定分离
流水线
  • 定义标准的
    构建 → 发布 → 部署 → 迁移 → 冒烟测试
    流水线
  • 迁移步骤在部署后运行(托管数据库需先存在)
  • 冒烟测试脚本对部署的服务进行端到端验证
  • 选择镜像仓库并将凭证设置为密钥
  • Dockerfile中添加OCI标签(针对GHCR)
  • 镜像摘要通过发布流程流转(不使用基于标签的部署)
环境
  • 定义staging和production环境
  • 每个环境关联流水线
  • 定义版本推广流程(构建一次,多次部署)
  • 了解恢复流程(诊断 → 回滚 → 重置)
密钥
  • 所有密钥通过
    eve secrets set
    按项目设置
  • 清单使用
    ${secret.KEY}
    插值
  • eve manifest validate --validate-secrets
    验证通过
  • 存在
    .eve/dev-secrets.yaml
    用于本地开发
  • 配置Git凭证(
    github_token
    ssh_key
  • 按服务声明服务令牌权限(默认只读;写入权限需显式开启)
认证
  • 后端添加
    @eve-horizon/auth
    中间件(
    eveUserAuth
    +
    eveAuthGuard
    ,多租户应用使用
    eveAppUserAuth
  • 提供认证配置端点用于SSO发现(
    eveAuthConfig
  • 前端使用
    @eve-horizon/auth-react
    封装(
    EveAuthProvider
    +
    EveLoginGate
    或自定义
    useEveAuth
    网关)
  • 使用
    createEveClient
    从前端调用认证后的API
  • 使用平台注入的认证环境变量(
    EVE_SSO_URL
    EVE_ORG_ID
    EVE_PROJECT_ID
  • 在一处将Eve角色映射为应用角色(桥接中间件),而非分散在多个控制器中
  • 若为无密码应用:设置
    x-eve.auth.login_method: magic_link
    +
    invite_requires_password: false
  • 若为多租户应用:设置
    x-eve.auth.org_access.mode: allowlist
    并声明
    allowed_orgs
    ;应用内管理员邀请使用
    POST /auth/app-invites
  • 若为基于域名的入职:
    domain_signup.domains
    声明每个规则的
    target_org
    ;先声明更具体的规则
  • 若使用自定义域名:声明
    x-eve.auth.allowed_redirect_origins
    ;使用
    eve project auth-context
    确认最终允许列表
  • 若为品牌化应用:声明
    x-eve.branding
    (邀请和魔法链接邮件共享);设置
    From:
    显示名称和Logo
应用CLI(Eve风格)
  • 应用API封装为领域CLI(如
    eden projects list
  • 在清单中通过
    x-eve.cli
    声明CLI的
    name
    bin
  • CLI打包为单文件可执行程序(Node.js使用esbuild)
  • CLI自动读取
    EVE_APP_API_URL_{SERVICE}
    EVE_JOB_TOKEN
  • 所有CLI命令支持
    --json
    参数以提供机器可读输出
  • Agent技能引用CLI命令,而非原生curl/REST调用
可观测性
  • 服务暴露健康检查端点
  • 理解调试阶梯(状态 → 诊断 → 日志 → 恢复)
  • 可通过
    eve pipeline logs --follow
    访问流水线日志

Cross-References

交叉引用

  • SPA + API + managed Postgres implementation:
    references/spa-api-managed-db.md
  • Manifest syntax and options:
    eve-manifest-authoring
  • Deploy commands and error resolution:
    eve-deploy-debugging
  • Secret management and access groups:
    eve-auth-and-secrets
  • Pipeline and workflow definitions:
    eve-pipelines-workflows
  • Local development workflow:
    eve-local-dev-loop
  • Layering agentic capabilities onto this foundation:
    eve-agentic-app-design
  • Auth SDK and SSO integration:
    eve-read-eve-docs
    references/auth-sdk.md
  • Object storage and filesystem:
    eve-read-eve-docs
    references/object-store-filesystem.md
  • External integrations (Slack, GitHub):
    eve-read-eve-docs
    references/integrations.md
  • SPA + API + 托管Postgres实现
    references/spa-api-managed-db.md
  • 清单语法与选项
    eve-manifest-authoring
  • 部署命令与错误排查
    eve-deploy-debugging
  • 密钥管理与访问组
    eve-auth-and-secrets
  • 流水线与工作流定义
    eve-pipelines-workflows
  • 本地开发流程
    eve-local-dev-loop
  • 在此基础上添加Agent能力
    eve-agentic-app-design
  • Auth SDK与SSO集成
    eve-read-eve-docs
    references/auth-sdk.md
  • 对象存储与文件系统
    eve-read-eve-docs
    references/object-store-filesystem.md
  • 外部集成(Slack、GitHub)
    eve-read-eve-docs
    references/integrations.md