Skip to content

feat(config): add deployment settings for self-hosted and cloud - #78

Merged
RedStar071 merged 8 commits into
feat/v2-authfrom
feat/deployment-settings
Oct 19, 2026
Merged

RedStar071 merged 8 commits into
feat/v2-authfrom
feat/deployment-settings

Conversation

@RedStar071

@RedStar071 RedStar071 commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Summary

Related to #5. Deployment settings for both editions, on top of #72: where they come from, who may change them, and how every run is held to them.

  • Self-hosted: one source, chosen at startup with CODE_ZERO_SETTINGS_SOURCE.
    • file: the instance file config.yml (or an explicit CODE_ZERO_CONFIG). The new Settings page shows it read-only, with each problem listed by path when it is invalid.
    • dashboard: an administrator edits the settings on the page, they are stored in Postgres, and they export as a config.yml with no secrets.
    • .code-zero.yml stays the per-repository file, and the stricter of the two wins.
  • Managed cloud (CODE_ZERO_EDITION=cloud, never inferred from the host): the AI provider, sandbox, database and mail come from the service and cannot be changed. Customers see only whether each one is configured, never how. The plan sets the ceiling, and organization owners and admins may lower concurrency, the command timeout and the allowed modes for their own organization.
  • What is enforced: concurrency goes into the scheduler; the command timeout caps every repository command; allowed modes are refused before a run starts on every entry point (dashboard, REST, webhook, poller); the model choice replaces the repository's; a container runner forces container isolation and the network setting is a ceiling.
  • Strict parsing: an unknown key, a bad value or unparsable YAML makes the whole document invalid. No task starts until it is fixed; nothing falls back to a default.
  • Migration 0006 adds the deployment and organization settings tables.

Why

A self-hosted deployment should be able to keep its configuration in a file it versions, or manage it from the dashboard; the managed cloud needs settings customers cannot loosen. Keeping exactly one source active at a time means the page can never show a value the server is not using.

Verification

  • aube run check:repo
  • aube run lint:ci
  • aube run typecheck
  • aube test
  • aube run build

Safety and compatibility

  • I added or updated deterministic tests for changed behavior.
  • I preserved observe mode as read-only, or explained the policy change above.
  • Runtime commands and target-repository writes remain inside the runner boundary.
  • I did not expose secrets, tokens, personal data, or untrusted output in logs.
  • I updated documentation and Agent Skills when workflows or boundaries changed.

Settings mutations need a signed-in session; API keys and operator tokens are refused. The export and the service statuses never carry a credential, URL or host. Observe is always allowed. Deployments must run migration 0006. code-zero.deployment.yml is still read when it is the only file, with a note to rename it.

Agent context

  • Agent/tools used: Codex (GPT) and Claude Code (Claude Opus 5.5) in T3 Code, with subagents.
  • What the agent did, and what you changed or verified yourself: I decided section by section what is locked on the cloud and what each edition may change; the agents implemented it, tested it, and checked a production build in Chromium for the file source (valid and invalid), the dashboard source (refused and accepted saves, export), the cloud edition as owner and as member, and a non-admin.

Reviewer notes

  • The timeout is per command, which is what the runner can enforce today. A whole run with several commands can take longer, and the page says so.
  • Not here on purpose, because nothing could enforce them yet: a cost budget, a command allow-list, approval before writes, an organization 2FA requirement, per-organization repositories, and notification preferences. The guide lists them as not available yet.
  • /api/v1/settings/** exists in the OpenAPI surface, but that transport takes bearer credentials only and the settings procedures refuse those, so nobody can use it today. Hide it, or allow it for admin API keys later?
  • An unknown CODE_ZERO_EDITION value is treated as cloud with every run refused, failing closed.
  • i18n:report lists the new settings keys as unused because it only scans apps/web/app/**, not apps/web/modules/**.

🤖 AI disclosure: Wolfstar Agent Kit modified this description. My AI open-source policy.

RetriggerView in GreptileConfidence Score: 5/5

No outstanding findings block merging. All three previously reported issues are addressed in the current code.

Reviews (2) · Last reviewed commit: "fix(web): keep a late settings answer fr..." · Reviewed by Greptile

Add the deployment settings document (execution limits, model, container
runner) with one strict parser shared by the file and the dashboard: an
unknown key, an out-of-range value, a credential-shaped string or bad YAML
refuses the whole document. Read the edition and the settings source from
CODE_ZERO_EDITION and CODE_ZERO_SETTINGS_SOURCE, never from the host, and
refuse the dashboard source on the cloud edition.

The instance file is now config.yml by default; an explicit
CODE_ZERO_CONFIG still wins, and code-zero.deployment.yml is read when it
is the only file present. The timeout is named for what it limits: one
repository command (command_timeout_minutes), not a whole run.
Add deployment_setting (a singleton row holding the settings document the
dashboard source edits) and organization_setting (an organization's own
stricter limits on the managed cloud, removed with the organization), with
migration 0006 and the queries the composition root reads and writes them
through, including the member-role lookup used to authorize changes.
Add settings.get, settings.update, settings.export and
settings.organization.get/update. Self-hosted, only an admin session reads
them, and writes are refused on the server unless the dashboard is the
source. On the managed cloud a customer sees service status (configured or
not, nothing else) and the plan's limits; an organization owner or admin may
lower the organization's limits, never above the plan, with membership
checked in the store on every call. API keys and operator tokens can neither
read nor change settings. Refusals are audited.

tasks.create, runTask and the scheduler apply the resulting RunPolicy:
invalid settings refuse every run, allowed modes are checked before a task
is recorded, concurrency is capped deployment-wide and per organization, and
the settings are applied over .code-zero.yml with the stricter value winning.
Build the settings authority in server/utils/settings.ts from the
environment, the instance file and the store: exactly one source, the file's
settings sections reported as ignored rather than merged when the dashboard
is the source, and service status reported as configured or not, never how.
Pass it into the RPC and OpenAPI contexts, and hold webhook deliveries and
polling passes to the same policy: invalid settings start nothing, and a
repository whose mode the settings disallow is skipped.
Add /settings and a settings module on the typed oRPC client.

- Self-hosted, file source: the settings read-only, the file to edit, every
  issue by path when they are invalid, service status, and YAML export.
- Self-hosted, dashboard source: an editable form for execution limits,
  model and container runner, with bounds as hints only; the server's
  per-field issues are shown beside each field, plus pending, saved and
  error states, who saved last and when, and download or copy as config.yml.
- Managed cloud: service status, plan limits read-only, and the active
  organization's limits, editable for owners and admins and read-only for
  members, with the effective limits. The page re-reads when the sidebar
  switches organization.
- A refusal (for example a non-admin on self-hosted) renders as a message.

The timeout is labelled per command. Controls the server does not enforce
are not shown. Adds the Settings nav entry and the g s shortcut, EN and IT
copy, and unit and component tests.
Add a Deployment settings guide: editions, the two self-hosted sources,
the config.yml format with a validated example, editing and export from
the dashboard, what is locked on the managed cloud, the per-command
timeout, and the controls that do not exist yet. Add the settings
authority boundary to docs/architecture.md (included by the guide),
CODE_ZERO_EDITION and CODE_ZERO_SETTINGS_SOURCE to the environment
reference and apps/web/.env.example, and move references from
code-zero.deployment.yml to config.yml.
@vercel

vercel Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
agent-zero-docs Skipped Skipped Oct 19, 2026 10:32am UTC
agent-zero-marketing Skipped Skipped Oct 19, 2026 10:32am UTC

@coldtea-pr-lens

coldtea-pr-lens Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
  • Redraw · drawn at ec9e7d9, the branch has moved on

Architecture

Architecture diagram for wolfstar-project/code-zero at ec9e7d9

Play the walkthrough

Inside the changed components — 1 view

Component view — Control Plane Policy & Scheduling

Internal details of how settings authority governs router, task operations, and scheduler queues.

Architecture view of Component view — Control Plane Policy & Scheduling in wolfstar-project/code-zero

Data flow

Data flow diagram for wolfstar-project/code-zero at ec9e7d9

Follow each request

The other flows — 1 sequence

Creating and scheduling a task under policy

Sequence diagram of Creating and scheduling a task under policy in wolfstar-project/code-zero

Review

✨ Nothing flagged · reviewed ec9e7d9


Tip

Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."

🪧 More tips
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs as before
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion

Thanks for using PR Lens! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out on X, Bluesky, Mastodon, Reddit or LinkedIn

Comment thread packages/core/config/src/settings.ts
Comment thread packages/core/config/src/settings.ts
Comment thread apps/web/app/pages/(dashboard)/settings.vue Outdated
Under a network ceiling below `full`, a repository that chose container
isolation could still name its own container network. `restricted` is
the one policy where the container runner reads that name, so
`network: host` became `--network host` while the run reported
restricted networking. The repository's network name is now dropped
whenever the deployment narrows the network, not only when the
deployment imposes its own sandbox.

The settings parser ignored top-level keys outside its three sections,
because the deployment file shares its top level with control_plane and
poll. A mistyped `exection:` was therefore accepted and left every limit
at its permissive default. Any top-level key that belongs to neither half
is now refused; documents saved from the dashboard accept only the
settings sections.
…ation

Saving organization A, switching to B and letting B's read finish first
installed A's answer when it arrived: the form showed A's limits under
B's name, and the next save went to A. The limits form is now keyed by
organization, an answer for an organization the page no longer shows is
dropped, and a settings read superseded by a newer one is discarded
however late it lands.
@vercel
vercel Bot temporarily deployed to Preview – agent-zero-marketing October 19, 2026 10:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – agent-zero-docs October 19, 2026 10:32 Inactive
@RedStar071
RedStar071 merged commit f84aa85 into feat/v2-auth Oct 19, 2026
16 checks passed
@RedStar071
RedStar071 deleted the feat/deployment-settings branch October 19, 2026 12:31

This branch was previously deployed

2 inactive deployments
Preview – agent-zero-marketing — 524754b8 Deployed Oct 19, 2026 by vercel[bot]
Preview – agent-zero-docs — 524754b8 Deployed Oct 19, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant