Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions docs/ADRs/0069-ready-made-configuration-presets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
Comment thread
ifireball marked this conversation as resolved.
title: "69. Ready-made configuration presets for simplified installation"
status: Accepted
relates_to:
- agent-infrastructure
- governance
Comment thread
ifireball marked this conversation as resolved.
Comment thread
ifireball marked this conversation as resolved.
- security-threat-model
Comment thread
ifireball marked this conversation as resolved.
topics:
- configuration
- github-setup
- installation
---

# 69. Ready-made configuration presets for simplified installation

Date: 2026-06-29

## Status

Accepted

## Context

`fullsend github setup` today spreads installation decisions across many CLI
flags (`--mint-url`, `--inference-project`, `--inference-region`, and others)
and separate enrollment steps: operators run `fullsend mint enroll` to register
repos with the token mint, and the installer provisions inference WIF
infrastructure via the inference layer
([ADR 0033](0033-per-repo-installation-mode.md),
[ADR 0029](0029-central-token-mint-secretless-fullsend.md)). The all-in-one
`fullsend admin install` command is deprecated in favor of `fullsend github
setup`.
Comment thread
ifireball marked this conversation as resolved.

Per-repo configuration lives in `.fullsend/config.yaml` within the target
repository ([ADR 0033](0033-per-repo-installation-mode.md)), but key runtime
settings (mint endpoint, inference backend) are only partially represented
there; much of the effective configuration still comes from flags and ephemeral
provisioning. That makes repeatable, vendor-curated installs harder than they
need to be.

[ADR 0064](0064-deprecate-customized-directory-overlay.md) deprecates the
`customized/` directory overlay; `config.base.yaml` is the successor mechanism
for distributing a shared baseline into each target repo's `.fullsend/`.

This ADR applies only to **per-repo** installation. Per-org installation via a
dedicated `<org>/.fullsend` config repo is deprecated and out of scope
([ADR 0044](0044-deprecate-per-org-installation-mode.md)).

[ADR 0029](0029-central-token-mint-secretless-fullsend.md) already treats
`job_workflow_ref` as the trust binding for mint authorization. Shared-infrastructure
mint workflow pinning and `job_workflow_ref` validation are decided in
[ADR 0059](0059-public-mint-mode-with-wildcard-allowlists.md). How shared
inference backends authorize callers — for example via `job_workflow_ref`,
org/repo allowlists on inference WIF, or streamlined enrollment rather than
full per-repo provisioning — is undecided and left to follow-on ADRs. This
ADR does not presuppose that inference follows the mint public-mode model.

## Options

- **Flags only (status quo):** Flexible for advanced operators, but every
adopter must understand mint and inference provisioning details.
- **Single monolithic `config.yaml`:** Simpler than flags, but mixes
vendor-provided defaults with repo-specific overrides and complicates upgrades
of the preset layer.
- **Layered base + overlay files (chosen):** Separate vendor baseline
(`.fullsend/config.base.yaml`) from repo overrides (`.fullsend/config.yaml`),
resolved through accessor methods. Supports preset distribution and clean
upgrades.

## Decision

Comment thread
ifireball marked this conversation as resolved.
**1. Move installation settings into configuration files.** Mint URL,
inference provider and backend parameters, and other values currently
supplied via CLI flags belong in the per-repo configuration under `.fullsend/`.
The installer reads configuration instead of reconstructing it from flags.
Comment thread
ifireball marked this conversation as resolved.
Decision 1 applies to `fullsend github setup` (single-repo install). The
[ADR 0057](0057-repos-management.md) bulk manifest path (`fullsend repos
install` / `sync`) remains a distinct operator mechanism using GitHub Secrets
and Variables until a follow-on change migrates it to per-repo config files.

**2. Layered configuration with accessor-based lookup.** Configuration is
stored in the target repository as:

Comment thread
ifireball marked this conversation as resolved.
Comment thread
ifireball marked this conversation as resolved.
- `.fullsend/config.base.yaml` — the base layer (vendor preset or repo baseline).
- `.fullsend/config.yaml` — the user overlay for repo-specific customization.

**Relationship to the three-tier model.** [ADR 0003](0003-org-config-repo-convention.md)
and `docs/architecture.md` describe configuration inheritance as upstream
defaults, then org `.fullsend`, then per-repo overrides. Per-repo installation
is the sole supported deployment model; the dedicated org config repo is
deprecated ([ADR 0044](0044-deprecate-per-org-installation-mode.md)).
`config.base.yaml` in each target repo fills the org tier's former
configuration role — not a revival of per-org installs. A vendor preset
committed as `config.base.yaml` can be reused across repos in one org or
distributed unchanged across org boundaries without a separate `<org>/.fullsend`
repository. `config.yaml` remains the per-repo overlay. Lookup order is overlay
→ base → **code defaults** in `internal/config` (and related packages): values
not set in either file still resolve from compiled-in defaults, as today.
Accessor methods implement that full chain; direct struct field access does not.

All runtime and installer lookups go through methods on a configuration
accessor (for example `MintURL()`, `InferenceProvider()`), not direct struct
field access. Each accessor implements its own merge and fallback rules across
layers (scalar override, deep merge, or required-in-overlay semantics as
appropriate). The design must allow additional file layers beyond base + overlay
in the future without changing call sites.

**3. `--config` install flag for ready-made presets.** `fullsend github setup`
Comment thread
ifireball marked this conversation as resolved.
accepts `--config <path-or-url>` and optional `--config-hash <sha256>`. The installer:

1. Fetches or reads the preset document. When `--config-hash` is supplied,
the installer validates fetched content against that hash; signing and
preset URL allowlisting are deferred to a follow-on ADR.
2. Commits it as `.fullsend/config.base.yaml` in the target repository.
3. Writes a stub `.fullsend/config.yaml` containing only comments and empty or
minimal override fields for the adopter to customize.

Presets may be local files or HTTPS URLs. The flag is optional; advanced
Comment thread
ifireball marked this conversation as resolved.
Comment thread
ifireball marked this conversation as resolved.
installs that assemble configuration manually remain supported.

**4. Reduce per-adopter enrollment for shared infrastructure (target state).**
When a preset targets shared infrastructure, the installer should minimize
install-time backend registration. For **mint**, workflow pinning and
`job_workflow_ref` validation are decided in
[ADR 0059](0059-public-mint-mode-with-wildcard-allowlists.md). For
**inference**, follow-on ADRs will choose among authorization models (which
may include `job_workflow_ref` pinning, org/repo-scoped inference WIF
allowlists with streamlined enrollment, or continued explicit provisioning
for self-managed paths). Until those ADRs land, preset-based installs
continue requiring inference enrollment and WIF provisioning where applicable.

Comment thread
qodo-code-review[bot] marked this conversation as resolved.
## Consequences

- Common installs become a single command with a preset URL instead of a long
flag list plus separate mint and inference enrollment steps.
- The `internal/config` package gains a layered accessor API; direct field reads
outside that package become a lint or review violation.
- Preset upgrades can refresh `.fullsend/config.base.yaml` while preserving
repo edits in `.fullsend/config.yaml`, provided merge semantics are
documented per field.
Comment thread
ifireball marked this conversation as resolved.
Comment thread
ifireball marked this conversation as resolved.
- Existing installations without `config.base.yaml` remain valid — accessors
treat a missing base file as an empty layer, falling through to code defaults.
- Preset URLs are a supply-chain trust surface; signing and preset URL
allowlisting are follow-on concerns (`--config-hash` validation is in scope
for `--config` installs).
- Self-managed and air-gapped deployments keep working via hand-authored
configuration or flags that bypass shared presets.
- Mint operators shift from per-repo onboarding to backend policy (workflow
allowlists per [ADR 0059](0059-public-mint-mode-with-wildcard-allowlists.md)).
Inference operator policy and install-time enrollment shape remain open;
security review for shared presets covers preset curation regardless of
which inference authorization model is chosen.
41 changes: 35 additions & 6 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ The compute and orchestration layer that runs agent workloads. Responsible for p

This is the "where do agents physically run" question — whether that's a managed platform, internal Kubernetes, CI runners repurposed for agent work, or something purpose-built.

Infrastructure platform choice and configuration are specified in the adopting organization's **`.fullsend`** repository. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)
Infrastructure platform choice and configuration live in each target
Comment thread
ifireball marked this conversation as resolved.
repository's **`.fullsend/`** directory. Per-repo installation is the sole
supported deployment model ([ADR 0033](ADRs/0033-per-repo-installation-mode.md));
the dedicated org-level `<org>/.fullsend` config repo is deprecated
([ADR 0044](ADRs/0044-deprecate-per-org-installation-mode.md)).

**Decided:**

Expand All @@ -47,6 +51,7 @@ Infrastructure platform choice and configuration are specified in the adopting o
- Event-driven stage dispatch: eliminate `workflow_dispatch` + `gh workflow run` fan-out from `dispatch.yml` in favor of synchronous `workflow_call` so the dispatched run stays linked to the caller ([ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)).
Comment thread
ifireball marked this conversation as resolved.
- Multi-repo management: a `fullsend repos` subcommand group with a declarative `repos.yaml` manifest for managing per-repo installations at scale — bulk install, status, sync, upgrade, and removal across repos and orgs ([ADR 0057](ADRs/0057-repos-management.md)).
- Dispatch version-skew resolution: per-repo `reusable-dispatch.yml` inlines stage workflow jobs directly, eliminating `@v0` references to `reusable-{stage}.yml` ([ADR 0062](ADRs/0062-dispatch-version-skew.md)).
- Ready-made configuration presets: `fullsend github setup --config <path-or-url>` installs a vendor preset as `.fullsend/config.base.yaml` and a stub `.fullsend/config.yaml` overlay in the target repository; mint URL, inference backend, and related settings live in configuration files resolved through accessor methods, not CLI flags. Shared-infrastructure presets will reduce per-adopter enrollment (target state): mint via `job_workflow_ref` trust per [ADR 0059](ADRs/0059-public-mint-mode-with-wildcard-allowlists.md); inference authorization model undecided ([ADR 0069](ADRs/0069-ready-made-configuration-presets.md)); enrollment remains required until follow-on ADRs land.
- GitLab event dispatch: two-path model — native CI triggers (`merge_request_event`) for MR events, cron-based polling for issues/comments/labels. No external infrastructure (no webhook bridge). Bot PAT via OIDC/WIF from Secret Manager or protected CI/CD variable. Per-repo only ([ADR 0067](ADRs/0067-gitlab-cron-polling-event-dispatch.md)).

**Open questions:**
Expand All @@ -64,7 +69,9 @@ The sandbox is a security primitive. Its job is containment: if an agent is comp

Ecosystem projects reuse the word *sandbox* for different workload shapes. For example, [Kubernetes SIG Agent Sandbox](https://github.com/kubernetes-sigs/agent-sandbox) targets **stateful, singleton** agent runtimes (long-lived sessions), whereas many fullsend-style workflows emphasize **short-lived, task-scoped** runs with tight isolation and observability. How those patterns compare is discussed in [agent-infrastructure.md](problems/agent-infrastructure.md#kubernetes-sig-agent-sandbox).

Sandbox defaults (network policy, filesystem restrictions) are configured in the adopting organization's **`.fullsend`** repository and can be overridden per-repo. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)
Sandbox defaults (network policy, filesystem restrictions) are configured in
each target repository's **`.fullsend/`** directory
([ADR 0033](ADRs/0033-per-repo-installation-mode.md)).

**Open questions:**

Expand All @@ -83,7 +90,11 @@ The configuration and context layer that prepares an agent for its task. Respons

The harness is what makes a generic LLM into a specific agent with a specific role. It assembles what the agent needs to know and what it's allowed to do before the agent starts working.

The harness draws its configuration from the adopting organization's **`.fullsend`** repository — skills, workflow definitions, and agent behavioral instructions are assembled from the layered config (fullsend defaults, then org config, then per-repo overrides). (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)
The harness draws its configuration from each target repository's
**`.fullsend/`** directory — skills, workflow definitions, and agent behavioral
instructions are assembled from the layered config (fullsend defaults, then
repo baseline and overrides)
([ADR 0033](ADRs/0033-per-repo-installation-mode.md)).

**Decided:**

Expand Down Expand Up @@ -205,7 +216,10 @@ Where agent behavioral rules live. Responsible for holding autonomy levels, revi

Policy is distinct from the harness (which configures *how* an agent works) and from intent (which defines *what* work is authorized). Policy defines the *boundaries* of agent behavior — what an agent is allowed to do regardless of what it's asked to do.

The adopting organization's **`.fullsend`** repository is the natural home for policy configuration — org-wide guardrails, per-repo autonomy levels, and escalation rules all live there, governed by the org's own CODEOWNERS and review process. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)
Each target repository's **`.fullsend/`** directory holds policy
configuration — guardrails, autonomy levels, and escalation rules governed by
the repo's CODEOWNERS and review process
([ADR 0033](ADRs/0033-per-repo-installation-mode.md)).

**Open questions:**

Expand All @@ -219,7 +233,10 @@ The system that provides authorized intent for agent work. Responsible for repre

Intent answers the question "should this change exist?" before anyone asks "is this change correct?" Without authorized intent, an agent has no basis for deciding what to work on or whether its output matches what was asked for.

The adopting organization's **`.fullsend`** repository holds the pointer to the intent source (for example, `intent_repo: your-org/features`), so tooling discovers where intent lives without hardcoding. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)
Each target repository's **`.fullsend/`** directory holds the pointer to the
intent source (for example, `intent_repo: your-org/features`), so tooling
discovers where intent lives without hardcoding
([ADR 0033](ADRs/0033-per-repo-installation-mode.md)).

**Open questions:**

Expand Down Expand Up @@ -254,7 +271,12 @@ The catalog of available agent roles and their configurations. Responsible for d

The registry is the bridge between the abstract roles defined in [agent-architecture.md](problems/agent-architecture.md) (correctness sub-agent, intent & coherence sub-agent, security sub-agent, etc.) and the concrete runtime configurations that the harness uses to set up each agent.

Fullsend provides a base set of agent definitions. The adopting organization's **`.fullsend`** repository extends this with org-specific agents in its `agents/` directory, following the inheritance model: fullsend defaults, then org config, then per-repo overrides. (See [ADR 0003](ADRs/0003-org-config-repo-convention.md).)
Fullsend provides a base set of agent definitions. Each target repository's
**`.fullsend/`** directory extends this with repo-specific agents, following
the inheritance model: fullsend defaults, then repo baseline (`config.base.yaml`
/ harness `base:` references), then repo overrides
([ADR 0033](ADRs/0033-per-repo-installation-mode.md),
[ADR 0058](ADRs/0058-agent-registration.md)).

**Decided:**

Expand Down Expand Up @@ -390,6 +412,13 @@ Fullsend uses a three-tier configuration inheritance model for all configuration
(base) (extend/override) (extend/tighten)
```

In per-repo installation the middle tier is replaced by files inside the
target repo: `.fullsend/config.base.yaml` (vendor preset or baseline) and
`.fullsend/config.yaml` (repo overlay), with code defaults below both. The
org-tier box above describes the historical per-org model, now deprecated
([ADR 0044](ADRs/0044-deprecate-per-org-installation-mode.md),
[ADR 0069](ADRs/0069-ready-made-configuration-presets.md)).

Skills flow downward through this stack. A repo-level skill might encode domain knowledge ("this repo uses a custom ORM — here's how queries work"). An org-level skill might encode org conventions ("all services use structured logging via zerolog"). Upstream fullsend provides foundational skills (code implementation, triage coordination, testing conventions).

AGENTS.md files follow the same layering. A repo's `.fullsend/AGENTS.md` gives agents repo-specific instructions (build commands, test patterns, architectural constraints). The org's `.fullsend/agents/` directory provides role-specific agent definitions that apply across all enrolled repos.
Expand Down
2 changes: 1 addition & 1 deletion docs/problems/governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Agent configuration is itself a security-critical attack surface. If someone can
- Where does agent policy live? In the repos it governs (as CLAUDE.md, agent config files)? In a separate policy repo? In a central configuration system?
- If policy lives in a separate repo, how does it get applied to target repos? Push-based (policy repo pushes to targets) or pull-based (agents read from policy repo at runtime)?
- How do we audit changes to agent configuration? Git history helps if policy is in git, but we also need to detect unauthorized runtime changes.
- How do we handle the bootstrap problem — who sets up the initial agent configuration for a new repo, and how is that initial setup secured?
- How do we handle the bootstrap problem — who sets up the initial agent configuration for a new repo, and how is that initial setup secured? (Preset-based install and `config.base.yaml` / `config.yaml` layering decided in [ADR 0069](../ADRs/0069-ready-made-configuration-presets.md); workflow pinning and backend policy remain open.)

### 3. Decision process

Expand Down
Loading