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
8 changes: 7 additions & 1 deletion .envrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
use nix
export CODEX_HOME=$PWD/.codex

if ! has nix_direnv_version || ! nix_direnv_version 3.1.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.1.0/direnvrc" \
"sha256-yMJ2OVMzrFaDPn7q8nCBZFRYpL/f0RcHzhmw/i6btJM="
fi

use flake
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# core-ops Development Guidelines

Auto-generated from all feature plans. Last updated: 2026-03-19
Auto-generated from all feature plans. Last updated: 2026-03-20

## Active Technologies
- Rust (stable toolchain) + Git (CLI), systemd (systemctl), Quadlet generator, clap, thiserror, miette, journald logger (002-systemd-agent)
- Files on disk (Quadlet unit files + optional reconciliation state) (002-systemd-agent)
- Files on disk (repository layout + evaluated desired state in memory) (003-layered-overrides)

- Rust (stable toolchain) + Git (CLI), systemd (systemctl), Podman/Quadlet generator (001-gitops-quadlet-controller)

Expand All @@ -24,8 +25,8 @@ cargo test [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES][ONLY COMMANDS FOR ACTIVE TECH
Rust (stable toolchain): Follow standard conventions

## Recent Changes
- 003-layered-overrides: Added Rust (stable toolchain) + Git (CLI), systemd (systemctl), Quadlet generator, clap, thiserror, miette, journald logger
- 002-systemd-agent: Added Rust (stable toolchain) + Git (CLI), systemd (systemctl), Quadlet generator, clap, thiserror, miette, journald logger

- 001-gitops-quadlet-controller: Added Rust (stable toolchain) + Git (CLI), systemd (systemctl), Podman/Quadlet generator

<!-- MANUAL ADDITIONS START -->
Expand Down
29 changes: 29 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ edition = "2021"

[dependencies]
clap = { version = "4.5.4", features = ["derive"] }
libc = "0.2.153"
log = { version = "0.4", features = ["kv"] }
miette = { version = "7.2.0", features = ["fancy"] }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9.34"
systemd-journal-logger = "2.2.2"
tempfile = "3.10.1"
thiserror = "1.0.58"
Expand Down
15 changes: 15 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,18 @@ Timer enablement example:
```
systemctl enable --now core-ops.timer
```

## Layered Overrides Development

Use the layered overrides fixture in `tests/fixtures/layered_overrides/` for
local testing. The repository layout should include:

- `services/<service>/` for base artifacts and base drop-ins
- `hosts/<host>/host.yaml` with explicit service selection
- `hosts/<host>/overrides/` for host-specific drop-ins

Override host selection during development with:

```
CORE_OPS_HOST=<host> core-ops plan --repo <repo> --rev <rev>
```
63 changes: 63 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
description = "Project dev shell with recent Codex";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
codex.url = "github:openai/codex/rust-v0.89.0";
};

outputs = { self, nixpkgs, codex, ... }:
let
system = "x86_64-linux"; # change as needed
pkgs = import nixpkgs { inherit system; };
in {
devShells.${system}.default = pkgs.mkShell {
packages = with pkgs; [
codex.packages.${system}.default
yaml-language-server
cargo
rustc
rust-analyzer
rustfmt
clippy
pkg-config
git
uv
python314
podman
systemd
jq
];

RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
};
};
}
27 changes: 0 additions & 27 deletions shell.nix

This file was deleted.

34 changes: 34 additions & 0 deletions specs/003-layered-overrides/checklists/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Specification Quality Checklist: Layered Overrides for Reusable Desired State

**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-03-20
**Feature**: /home/outergod/code/github.com/outergod/core-ops/specs/003-layered-overrides/spec.md

## Content Quality

- [x] No implementation details (languages, frameworks, APIs)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed

## Requirement Completeness

- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Success criteria are technology-agnostic (no implementation details)
- [x] All acceptance scenarios are defined
- [x] Edge cases are identified
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified

## Feature Readiness

- [x] All functional requirements have clear acceptance criteria
- [x] User scenarios cover primary flows
- [x] Feature meets measurable outcomes defined in Success Criteria
- [x] No implementation details leak into specification

## Notes

- All checklist items passed on 2026-03-20 after adding host-level service selection.
42 changes: 42 additions & 0 deletions specs/003-layered-overrides/contracts/repo-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Repository Layout Contract

## Purpose
Define the repository structure and host selection inputs used for layered overrides.

## Required Structure

- `services/<service>/` contains base artifacts and base drop-ins.
- `hosts/<host>/host.yaml` declares host identity and explicit service selection.
- `hosts/<host>/overrides/` contains host-specific drop-ins layered after base drop-ins.

## Host Declaration Schema

`hosts/<host>/host.yaml`:

```yaml
host: <host-id>
services:
- <service-name>
- <service-name>
```

### Rules

- `host` must match the `<host>` directory name.
- `services` must reference existing `services/<service>/` directories.
- No groups/roles are supported; selection is an explicit list.

## Drop-in Rules

- Quadlet drop-ins: `artifact.container.d/*.conf`, `artifact.volume.d/*.conf`.
- Systemd socket drop-ins: `artifact.socket.d/*.conf`.
- Drop-ins are applied in lexicographic order by filename.
- Host overrides are applied after base drop-ins.
- For socket drop-ins, host override filenames must sort after base filenames
for the same target, or evaluation fails.

## Validation Failures

- Undefined service selection → evaluation fails.
- Drop-in targets nonexistent artifact → evaluation fails.
- Unsupported file types/extensions → evaluation fails.
44 changes: 44 additions & 0 deletions specs/003-layered-overrides/data-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Data Model: Layered Overrides for Reusable Desired State

## Entities

### Service Catalog
- **Purpose**: Shared base definitions under `services/`.
- **Fields**:
- `service_name` (string)
- `artifacts` (list of Quadlet/systemd unit files)
- `base_dropins` (list of drop-in files by artifact)

### Host Declaration
- **Purpose**: Per-host selection and identity in `hosts/<host>/host.yaml`.
- **Fields**:
- `host` (string)
- `services` (list of service names)

### Host Overlay Set
- **Purpose**: Host-specific drop-ins under `hosts/<host>/overrides/`.
- **Fields**:
- `host` (string)
- `overrides` (list of drop-in files by artifact)

### Evaluated Artifact
- **Purpose**: Concrete artifact after base + drop-in evaluation.
- **Fields**:
- `artifact_name` (string)
- `artifact_type` (container, volume, socket)
- `contents` (string)
- `source_layers` (list of files applied in order)

## Relationships

- A **Service Catalog** contains many base artifacts and base drop-ins.
- A **Host Declaration** selects services from the Service Catalog.
- A **Host Overlay Set** provides drop-ins applied after base drop-ins.
- **Evaluated Artifacts** are produced by applying base artifacts + base drop-ins + host overlays.

## Validation Rules

- Host-selected services must exist in the Service Catalog.
- Drop-ins must target an existing base artifact.
- Drop-ins are applied in lexicographic order; host overlays are applied after base drop-ins.
- Evaluation must be deterministic and side-effect free.
Loading