docs: add client lifecycle plan, cleanup stale files, document repo for 3 audiences
Problem: Repo had no developer guide, no client onboarding doc, no agent dev instructions. Stale files (675KB SQL dump, one-off convert script, legacy MCP builder) cluttered the tree. Client enrollment was a documented intention with no Go implementation. Changes: - New docs: CONTRIBUTING.md (dev setup), CLIENTS.md (client onboarding), .agents/dev/CONTRIBUTING.md (agent codebase map) - New plan: plans/2026-07-07-client-lifecycle-in-go.md — full client lifecycle (planned→provisioning→active→deprecated→destroyed) in Go, replacing archived Python secrets-issuance, adding client API endpoints and 6 missing MCP tools - Cleanup: deleted archive/convert-wiki.py (one-off), archive/mcp/ build_host_files.py (legacy), backups/pre-deploy-7f7d039.sql (local) - Fixes: plans/index.md duplicate row removed, README.md repo layout updated for current state, AGENTS.md header points to new guides Risk: low. Docs only + stale file deletion. No code changes. New plan is proposal, not implementation. Verification: git diff reviewed, all changes are prose/docs/plans.
This commit is contained in:
155
CONTRIBUTING.md
Normal file
155
CONTRIBUTING.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Contributing to Oikos
|
||||
|
||||
Developer guide for the Oikos codebase. If you are a homelab client consuming
|
||||
Oikos, see [CLIENTS.md](CLIENTS.md). If you are an AI agent working on the
|
||||
repo, see [.agents/dev/CONTRIBUTING.md](.agents/dev/CONTRIBUTING.md).
|
||||
|
||||
## Dev setup
|
||||
|
||||
- **Go 1.26+** (see `go.mod` for pinned version)
|
||||
- **PostgreSQL with TimescaleDB** — the compose stack includes `timescale/timescaledb:2.17.2-pg16`
|
||||
- **Docker** for the full dev stack
|
||||
|
||||
```bash
|
||||
# Start dependencies (Postgres + Redis)
|
||||
docker compose --profile dev up -d
|
||||
|
||||
# Run all tests
|
||||
make test
|
||||
|
||||
# Run integration tests (needs compose Postgres)
|
||||
make test-db
|
||||
|
||||
# Build the binary
|
||||
make build
|
||||
```
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
cmd/oikos/ Single-binary entry point
|
||||
cmd/hermes/ Hermes MCP client gateway
|
||||
internal/ All Go packages
|
||||
httpapi/ REST + MCP server (OpenAPI-generated)
|
||||
mcp/ MCP tool implementations
|
||||
db/ Connection pool, migrations, seeds, sqlc queries
|
||||
scheduler/ Observe loop, probes, signals
|
||||
actuator/ SSH execution
|
||||
learning/ Pattern recognition, anomaly detection
|
||||
notifier/ Matrix notifications, approval tokens
|
||||
policy/ Risk classifier
|
||||
secrets/ Infisical + SOPS backend
|
||||
domain/ Core types: entities, approvals, signals, patterns
|
||||
ontology/ Type hierarchy, relationship validation
|
||||
knowledge/ Knowledge YAML seed ingestion
|
||||
api/openapi.yaml API contract — the source of truth for endpoints
|
||||
migrations/ Forward-only SQL migrations (TimescaleDB)
|
||||
seeds/ Bootstrap YAML: ontology, inventory, policy, knowledge
|
||||
compose/ Dockerfiles + Caddy config
|
||||
scripts/ Deploy, watchdog, rollback
|
||||
hermes/ Hermes config, persona, skills
|
||||
.agents/ Agent instruction files + skills
|
||||
plans/ Design documents
|
||||
docs/adr/ Architecture decision records
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `make build` | Build `oikos` binary |
|
||||
| `make test` | Run all tests with race detection |
|
||||
| `make test-db` | Run integration tests against compose Postgres |
|
||||
| `make lint` | `go vet` + `golangci-lint` |
|
||||
| `make generate` | Regenerate OpenAPI + sqlc code |
|
||||
| `make generate-check` | CI drift guard — fail if generated code is stale |
|
||||
| `make migrate` | Apply DB migrations |
|
||||
| `make seed` | Ingest seeds into DB |
|
||||
| `make export` | Export DB state to YAML seeds |
|
||||
| `make dev` | Start compose dev stack |
|
||||
| `make clean` | Remove binary + test cache |
|
||||
|
||||
## Conventions
|
||||
|
||||
### APIs are OpenAPI-first
|
||||
|
||||
The REST API is defined in `api/openapi.yaml`. Server code is generated with
|
||||
`oapi-codegen` into `internal/httpapi/gen/`. To add an endpoint:
|
||||
|
||||
1. Add the path + schema to `api/openapi.yaml`
|
||||
2. Run `make generate`
|
||||
3. Implement the handler in `internal/httpapi/impl.go`
|
||||
4. Add tests in `internal/httpapi/api_test.go`
|
||||
|
||||
Never hand-edit `internal/httpapi/gen/api.gen.go`.
|
||||
|
||||
### Database access is sqlc-first
|
||||
|
||||
SQL queries live in `internal/db/queries/*.sql`. Go code is generated with
|
||||
`sqlc` into `internal/db/sqlcgen/`. Config in `sqlc.yaml`.
|
||||
|
||||
- Queries target pgx/v5 with UUID + timestamptz overrides
|
||||
- Never hand-edit generated sqlc code
|
||||
|
||||
### Migrations are forward-only
|
||||
|
||||
SQL migrations live in `migrations/` as `NNN_name.up.sql`. There are no down
|
||||
migrations (see [ADR 0008](docs/adr/0008-forward-only-migrations.md)).
|
||||
Migrations are idempotent where possible (`IF NOT EXISTS`, `DO $$` blocks).
|
||||
|
||||
To add a migration:
|
||||
|
||||
1. Create `migrations/NNN_name.up.sql` with the next sequence number
|
||||
2. Write the DDL
|
||||
3. Run `make migrate` to apply
|
||||
|
||||
### Seeds are DB-generated
|
||||
|
||||
`seeds/*.yaml` are the bootstrap files used by `oikos seed`. After making
|
||||
changes via the API, run `make export` to regenerate the seed files. These
|
||||
files are version-controlled and serve as DR fallback.
|
||||
|
||||
### Writing style
|
||||
|
||||
Follow [.agents/shared/writing-style.md](.agents/shared/writing-style.md).
|
||||
Documentation is reference prose, not marketing. Banned vocabulary includes
|
||||
"robust", "seamless", "leverage", "utilize", "delve", "cutting-edge".
|
||||
|
||||
### Risk classification
|
||||
|
||||
Every mutation is classified against `seeds/policy.yaml` before execution.
|
||||
Four risk classes: `read_only`, `reversible_low`, `config_mutation`,
|
||||
`destructive`. The classifier can only lower autonomy relative to policy,
|
||||
never raise it. When in doubt, escalate.
|
||||
|
||||
## CI
|
||||
|
||||
Gitea Actions runs on push to `main` and pull requests (`ci.yml`):
|
||||
|
||||
1. `go vet` + `golangci-lint` + `govulncheck`
|
||||
2. Generated code drift check (`make generate-check`)
|
||||
3. Build (`go build ./...`)
|
||||
4. Test with race detector + coverage
|
||||
5. Docker build verification (no push)
|
||||
|
||||
Coverage gates: policy + learning packages ≥ 80%, others ≥ 60%.
|
||||
|
||||
## PR workflow
|
||||
|
||||
1. Create a branch from `main`
|
||||
2. Make changes, write tests
|
||||
3. Run `make lint test generate-check`
|
||||
4. Commit with a message following: problem → change → risk → verification
|
||||
5. Push to Gitea; CI gates PRs on green
|
||||
|
||||
## Secrets
|
||||
|
||||
Secrets are managed by Infisical (primary) with SOPS as DR fallback. Never
|
||||
hardcode secrets. Use environment variables from `.env` for local dev.
|
||||
The `.env` and `.infisical-credentials` files are gitignored.
|
||||
|
||||
## Related
|
||||
|
||||
- [OIKOS.md](.agents/OIKOS.md) — operating model, OODA loop, ontology
|
||||
- [CLIENTS.md](CLIENTS.md) — for homelab clients consuming Oikos
|
||||
- [docs/adr/](docs/adr/) — architecture decision records
|
||||
Reference in New Issue
Block a user