diff --git a/README.md b/README.md index 50cfc1b..126027f 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,75 @@ -# coreci/executor-config — coreci-executor (Write Executor, Design v1.0) +# coreci/executor-config — approval-request queue (repurposed, REQ-27) -Single governed write rail from Open WebUI agents to Gitea. -- `allowlist.yaml` — policy engine config (AUTO_RUN vs NEEDS_APPROVAL; fail-closed) -- `compose.yaml` + `executor.env.example` — deployment (secrets in .env only) -- `app/` — coreci-executor v0.1.1 (FastAPI) -- `docs/` — approval-UI spec, runbook, Open WebUI registration guide -- `logs/` — git-durable audit JSONL (one line per request event) +Governance lane for CoreCI's executor rail (LXC 116 coreci-executor + +LXC 117 coreci-broker — BOTH STAY RUNNING). The rail is REPURPOSED as an +approval-request queue ONLY: operational requests from acting employees' +pipelines are parked here, routed across the chain of command, decided by +the resolved approver at the executor UI, mirrored to a Gitea issue lane, +and POLLED by the requesting pipeline. The queue NEVER executes anything +against production. This repo is FROZEN: the one-way config change below +(a PR) is the only change channel — direct pushes are denied, no apply +pipeline lives here, and there is no CI: the deploy step is the on-host, +operator-gated reconcile in `docs/approval-queue-runbook.md`. -Governance: agent authors -> executor gates -> PO approves (NEEDS_APPROVAL) -> -executor runs as `coreci-executor` (non-admin; collaborator-write ONLY on the -repos granted in the deployment pack) -> audit + Discord notify. -Secrets never in chat, repos, or tool calls — executor env vars only. +## What this repo carries (post-repurpose) + +- `allowlist.yaml` — policy engine config, v5.0 (`mode: approval_queue_only`) + — every legacy AUTO_RUN grant is REVOKED; failure mode is NEEDS_APPROVAL + for everything (fail-closed). The revoked grants are enumerated inline. +- `routing.json` — GENERATED approval-routing table (manager edges, + system owners, C-09 chairman-direct seat set; source: + coreci/company `org/systems-ownership.md` v1.2 + org-chart.json; + generator: coreci/sre `scripts/p04-executor/gen-routing-table.py`). + Do not hand-edit — regenerate. +- `compose.yaml` + `executor.env.example` — deployment; secrets in `.env` + only (never committed). +- `app/` — legacy classifier module (v0.1.1 history kept for the audit + trail). Stale vs the live rail (0.3.0 server, built on-host): do NOT + "restore" it — the 0.4.0 decision-only server is built from the live + source, per the runbook. +- `docs/` — approval-queue runbook (this repurpose), legacy approval-ui + spec (kept for history), Open WebUI registration, legacy runbook. +- `logs/` — git-durable audit JSONL (one line per queue event; see the + event vocabulary in the mirror contract). + +## The NEVER-EXECUTES guarantee (REQ-27) + +The queue path contains no execution of any kind: +- the legacy job runner (pack execution on approve) is DISABLED in + approval-queue mode; approve/deny are decision-RECORD operations; +- no script execution, no host execution, no work-runner container — + `WORK_ROOT` remains only as legacy-compat storage, never a run surface; +- the executor's own credentials (below) are scoped to the queue's WRITE + surface: meeting-lane issues + audit logs, nothing else; +- the v4.1 mailbox-path AUTO_RUN exemption was app-code-level; in + approval-queue mode it can no longer reach an execution path (nothing + executes). v5.0 records its revocation inline. + +Routing semantics: manager-first (one chain-of-command hop) + system owner +when an owned system is touched (both when both). Chairman-direct lane +per C-09 (acting C-suite, CEO, coreci-sre → Chairman decides directly). +Unresolvable chain → CEO → Chairman queue (sanctioned skip-path 2). +Full audit: every request event is append-only JSONL under `logs/` and +mirrored to `coreci/meetings` (labels `approval-request`, +`approval:L2|L3`, `dept:`). + +## Decision surface + +Approvers decide at the executor UI (passcode-gated `/ui/*`) and/or read +the mirror issue in coreci/meetings; the requesting pipeline polls +`GET /request_status?request_id=…` (Bearer EXECUTOR_API_KEY). Requests are +CREDENTIAL-FREE envelopes; the executor injects nothing anywhere — the +requestor keeps its own credentials, the queue only carries their +REQUEST for approval. + +## Freeze discipline + +- `allowlist.yaml`, `routing.json`, `executor.env.example`, `README.md`, + `docs/` change ONLY via PRs into this repo's `main` (one-way channel). +- `coreci/broker` (LXC 117) is frozen on the same one-way-PR discipline. +- No redeploy pipeline reads this repo; deployment is operator-gated + (runbook §"Apply the change"). + +Executor identity: `coreci-executor` (non-admin Gitea account; its PAT +carries only what the mirror + audit need — see +`docs/approval-queue-runbook.md`). \ No newline at end of file diff --git a/allowlist.yaml b/allowlist.yaml index 9c9c42a..4a8c02a 100644 --- a/allowlist.yaml +++ b/allowlist.yaml @@ -1,35 +1,60 @@ -version: 4.1 -# v4.1 (2026-10-04): -# - Append-only over v4. No schema breaks. -# - New MAILBOX_PATH_RE exemption in app/main.py: per-home mailbox writes -# (outbox/ + inbox/ under /home/mailbox/) classify AUTO_RUN -# when ALL targets are own-home mailbox paths. Encodes Decision 6 [1]. -# - Cross-agent inbox mirror (CAIRO writes to coreci-coo/home/mailbox/inbox/) -# is still NEEDS_APPROVAL — explicit cross-agent grants land in v4.2. -# - Naming convention v2 preserved: agent = coreci-. +version: 5.0 +mode: approval_queue_only +# allowlist v5.0 — approval-request queue repurpose (REQ-27, P04-04). +# +# CHANGE SHAPE (one-way PR into the FROZEN executor-config repo): +# v4.x classified packs and auto-ran granted targets. The rail is now an +# approval-request queue ONLY — it routes, records, mirrors, and reports; +# it NEVER executes against production. +# +# REVOKED in v5.0 (the complete v4.1 grant set — nothing else ever existed): +# - coreci-coo: bash_pack auto_run coreci-coo/home (revoked) +# - coreci-cairo: bash_pack auto_run coreci-cairo/home (revoked) +# - coreci-cpo: bash_pack auto_run coreci-cpo/home (revoked) +# - coreci-executor: bash_pack auto_run coreci/executor-config (revoked) +# - defaults read_targets (coreci/company) kept UNCHANGED: the queue still +# allows the org records as a READ surface for request context only. +# +# SEMANTICS under mode: approval_queue_only: +# - defaults.decision stays NEEDS_APPROVAL (fail-closed) and there are no +# agent rows: the v4.1 classifier can never return AUTO_RUN again. +# - The v4.1 mailbox-path exemption is APP-CODE-level (not config) and +# cannot reach an execution path here — approval-queue mode has none +# (see README.md "The NEVER-EXECUTES guarantee"). +# - approval_queue.* below is consumed by the 0.4.0 decision-only server +# build; the legacy 0.3.0 server ignores unknown top-level keys (its +# loader picks only defaults/agents), so this file is backward-safe. +# +# Routing for approvals comes from routing.json (GENERATED from +# coreci/company org/systems-ownership.md v1.2 + org-chart.json — do not +# hand-edit either side of that chain; regenerate instead). defaults: decision: NEEDS_APPROVAL - timeout_s: 900 + timeout_s: 900 # legacy field, retained for schema compat only read_targets: - coreci/company -agents: - coreci-coo: - kinds: - bash_pack: - auto_run_targets: - - coreci-coo/home - coreci-executor: - kinds: - bash_pack: - auto_run_targets: - - coreci/executor-config - coreci-cpo: - kinds: - bash_pack: - auto_run_targets: - - coreci-cpo/home - coreci-cairo: - kinds: - bash_pack: - auto_run_targets: - - coreci-cairo/home + +agents: {} # v5.0: NO auto-run grants remain (see REVOKED above) + +approval_queue: + enabled: true + never_execute: true # the queue is a decision-record surface, full stop + routing_table: /config/routing.json + request_id_prefix: ar # queue ids: ar-- + decision_surface: executor_ui # + Gitea issue mirror (coreci/meetings) + mirror: + repo: coreci/meetings + actor: coreci-executor # executor app account; PAT scoped to writes below + labels: + - approval-request + - approval:L2 # emitted alongside approval:L3 per request class + - dept: # resolved from the requestor's org-chart ancestor + lanes: + - chairman_direct # C-09: acting C-suite, CEO, coreci-sre requests + - manager_owner # manager one hop + system owner (both when both) + - skip_path # unresolvable -> CEO -> Chairman + statuses: + - open + - routed + - decided # decided (approved|rejected, decided_by, decided_at) + - withdrawn # requestor abort before decision \ No newline at end of file diff --git a/docs/approval-queue-runbook.md b/docs/approval-queue-runbook.md new file mode 100644 index 0000000..1038a19 --- /dev/null +++ b/docs/approval-queue-runbook.md @@ -0,0 +1,104 @@ +# approval-queue runbook — executor rail as approval-request queue (REQ-27, P04-04) + +The executor rail (LXC 116 coreci-executor + LXC 117 coreci-broker) stays +RUNNING at all times; its job is to park, route, decide, mirror and report +approval requests. It never executes anything (README "The NEVER-EXECUTES +guarantee"). This repo is frozen: the change that repurposes it IS the PR +holding this file + `allowlist.yaml` v5.0 + `routing.json`. + +## Queue model + +- Request: a credential-free envelope from an acting employee's pipeline + (`POST /submit_request`, EXECUTOR_API_KEY auth). Fields: `id`, + `requestor` (Gitea username = seat), `system_id` (optional — a + systems-ownership row id), `title`, `class` (L1|L2|L3), `justification` + (+ legacy-compat `kind`/`targets`/`content` for the UI display). +- Routing: resolved at intake from `/config/routing.json` (GENERATED from + coreci/company org records — never hand-edited here): + lane `chairman-direct` (C-09: acting C-suite + CEO + coreci-sre → + Chairman decides), lane `manager:owner` (requestor's manager one hop + + the touched system's owner; both when both, deduped, manager listed + first), lane `skip-path` (unresolvable chain → approver CEO, queue + Chairman — sanctioned skip-path 2). No ownership-table row for a + submitted `system_id` → request REFUSED at intake (fail-closed). + Full trail (rule-by-rule, with timestamps) is stored on the request + and mirrored to the Gitea issue. +- Approval: the resolved approver decides at the executor UI + (`/ui/request/{rid}/approve|deny`, passcode session). Approve/deny is a + DECISION-RECORD only — the legacy approve-triggers-run path is disabled + in approval-queue mode (0.4.0 decision-only server build; see "Apply"). +- Result: `GET /request_status?request_id=…` returns + `{status: open|routed|decided, decision, decided_by, decided_at, …}` — + the requesting pipeline polls this, never the queue's internals. +- Audit: every event is appended to `logs/audit-YYYY-MM-DD.jsonl` + (append-only, git-durable) with the vocabulary + `request.created, route.resolved, decision.posted, mirror.updated`. + `/ui/audit` renders recent rows for humans. + +## Issue mirror (coreci/meetings) + +The queue posts one issue per request into coreci/meetings — the same +lane the meeting machinery's approval-requests already live in — labels +`approval-request` + `approval:L2|L3` + `dept:`; body carries the +machine-notes block (`requestor: / system: / owner: / lane: / status:`). +Decisions are posted as comments by the EXECUTOR APP ACCOUNT +(`coreci-executor`, its own PAT) and the body flips to +`status: decided (…)`. Idempotency: the mirror dedups on the request id +token in the issue body (`ar-…`); a mirror-retry can never double-post a +request or a decision. Full contract: +coreci/sre `scripts/p04-executor/mirror-contract.md`. + +## Apply the change (operator-gated, on-host — NO pipeline does this) + +The rail hot-reads this repo's config ONLY through its bind mount — +there is no redeploy pipeline watching this repo; nothing applies until +the operator runs the steps below (read-only from SRE's side: the sre +repo only AUTHORS the patch and opens the PR). + +1. PR merged into executor-config:main (merge = the operator's + confirmation; the merge itself changes the frozen repo's files). +2. On LXC 116, in the executor-config working copy mounted at + /config (and the container's own clone): + + git fetch --all && git pull --ff-only + - `allowlist.yaml` v5.0 takes effect on the NEXT classification pass + (the legacy classifier hot-reads per call — `current_allowlist()` + opens the file every time: NO restart needed), so the last auto-run + grants die the moment main updates. +3. Server build to 0.4.0 (decision-only / never-executes). IMPORTANT + recon fact: the LIVE server (0.3.0) is NOT built from this repo's + stale `app/main.py` (repo app = v0.1.1 classifier module only). The + 0.4.0 build must be produced from the on-host source of truth, wire + it: read `ALLOWLIST_PATH=/config/allowlist.yaml` (repo-mounted) and + `EXECUTOR_ROUTING_TABLE=/config/routing.json`, honor + `mode: approval_queue_only` (refuse to boot without it or without + `never_execute: true` — fail-closed), run the routing + mirror half + from this runbook + the mirror contract. Then: + + podman compose up -d --build # or docker compose + curl -s http://127.0.0.1:8765/health + -> expect {"status":"ok","version":"0.4.0","mode":"approval_queue_only",...} +4. LXC 117 (coreci/broker) is UNTOUCHED by this repurpose (broker repo + frozen; its change channel is a separate one-way PR when needed). +5. Post-apply asserts (all must be GREEN): `GET /health` version 0.4.0; + `GET /request_status?request_id=probe` → 404-with-id (queue reachable, + no phantom request); executor identity can create/label issues in + coreci/meetings; executor identity CANNOT write any other repo + (negative assert — try a write via the API and expect 403); audit + JSONL gains the 4-event vocabulary on a test request; mirror issue + appears with the machine-notes block; decision on the test request + mirrors correctly and body flips status. + +## Rollback + +Revert the merged PR (one-way channel: a revert PR), keep the 0.4.0 +server: it boots fail-closed WITHOUT `mode: approval_queue_only` — with +the v4.1 allowlist restored the legacy classification semantics return, +and nothing auto-runs (all grants were revoked in this repurpose; that +revocation stands until org records say otherwise via new org-record PRs). + +## Escalation + +Executor unreachable → notify-ladder (bao KV) as usual; queue outages +NEVER auto-approve: pipelines wait on `request_status`, and an outage +shows as `routed`/`open` with a heartbeat gap in the audit trail. \ No newline at end of file diff --git a/executor.env.example b/executor.env.example index 40d64fa..34073f4 100644 --- a/executor.env.example +++ b/executor.env.example @@ -1,8 +1,19 @@ -EXECUTOR_API_KEY=change-me-long-random # tool-endpoint auth (Open WebUI) -EXECUTOR_PASSCODE=change-me-web-ui-passcode # approval UI +EXECUTOR_MODE=approval_queue_only # REQ-27: the rail is an approval-queue ONLY +EXECUTOR_ROUTING_TABLE=/config/routing.json # GENERATED routing table (do not hand-edit) +EXECUTOR_MIRROR_REPO=coreci/meetings # Gitea issue mirror lane (see mirror contract) +EXECUTOR_MIRROR_LABELS=approval-request # + approval:L2|L3 + dept: per request + +# --- executor app account (Gitea) — mirror/audit writer identity ONLY ----- GITEA_URL=https://git.coreci.dev -GITEA_USER=coreci-executor -GITEA_TOKEN=paste-token-from-pack-output-here # write:repository ONLY +GITEA_USER=coreci-executor # non-admin; write:repository scope ONLY +GITEA_TOKEN=paste-token-from-pack-output-here # executor's own PAT; NEVER a seat's personal token +# Scope contract for the PAT (enforced by review, audited monthly): +# read: executor-config (queue config), meetings (issue mirror lane) +# write: meetings (issues for the approval lane + label ensure) — NOTHING else +# Rotation: docs/runbook.md (legacy "Token rotation" section applies unchanged). + +EXECUTOR_API_KEY=change-me-long-random # requestor pipelines poll auth (Bearer or X-Executor-Key) +EXECUTOR_PASSCODE=change-me-web-ui-passcode # approver UI passcode (decision surface) DISCORD_WEBHOOK_URL= # optional: approvals + outcomes -MAX_OUTPUT_TAIL=4000 -REQUEST_TIMEOUT_S=900 +MAX_OUTPUT_TAIL=4000 # legacy: kept for schema compat (no run tail exists) +REQUEST_TIMEOUT_S=900 # legacy: kept for schema compat \ No newline at end of file diff --git a/routing.json b/routing.json new file mode 100644 index 0000000..61d0a53 --- /dev/null +++ b/routing.json @@ -0,0 +1,440 @@ +{ + "chairman_direct_seats": [ + "coreci-cairo", + "coreci-ceo", + "coreci-cfo", + "coreci-ciso", + "coreci-coo", + "coreci-cpo", + "coreci-cto", + "coreci-sre", + "jonathan" + ], + "chart_version": "1.2", + "custodian": "CEO from seat (Chairman pre-seat) \u2014 approval-routing row", + "drift": [ + { + "kind": "extra_chart_claim", + "org_chart_claimants": [ + "cto", + "sre" + ], + "resolution": "table wins; co-claimants ['cto'] recorded for the p06 assert (routing resolves to the row Owner only)", + "system_id": "gitea-instance", + "table_owner_seat": "sre" + }, + { + "kind": "chart_claim_without_table_row", + "org_chart_claimants": [ + "chairman" + ], + "resolution": "queue refuses this system-id at intake until a table row lands (fail-closed)", + "system_id": "ollama-mint" + }, + { + "kind": "extra_chart_claim", + "org_chart_claimants": [ + "cto", + "sre" + ], + "resolution": "table wins; co-claimants ['cto'] recorded for the p06 assert (routing resolves to the row Owner only)", + "system_id": "pve-estate", + "table_owner_seat": "sre" + } + ], + "generated_by": "scripts/p04-executor/gen-routing-table.py (stdlib; deterministic \u2014 no wall-clock fields)", + "lanes": { + "chairman_direct": "C-09 lane \u2014 Chairman (jonathan) is the sole decision authority; owning seat is audit-notified", + "manager_owner": "normal lane \u2014 requestor manager (one hop) + system owner when an owned system is touched (both listed, deduped)", + "skip_path": "unresolvable chain \u2014 approver CEO (coreci-ceo), queue Chairman (sanctioned skip-path 2)" + }, + "manager_edges": { + "coreci-cairo": "coreci-ceo", + "coreci-ceo": "jonathan", + "coreci-cfo": "coreci-ceo", + "coreci-chat-po": "coreci-hap", + "coreci-ciso": "coreci-ceo", + "coreci-clo": "coreci-ceo", + "coreci-cmo": "coreci-ceo", + "coreci-content-lead": "coreci-cmo", + "coreci-contracts-lead": "coreci-clo", + "coreci-coo": "coreci-ceo", + "coreci-cpo": "coreci-ceo", + "coreci-cto": "coreci-ceo", + "coreci-fpa-lead": "coreci-cfo", + "coreci-hap": "coreci-cpo", + "coreci-hbo": "coreci-coo", + "coreci-hep": "coreci-cpo", + "coreci-hfp": "coreci-cpo", + "coreci-hip": "coreci-cpo", + "coreci-hpe": "coreci-cto", + "coreci-nextcraft-po": "coreci-hep", + "coreci-nova-po": "coreci-hip", + "coreci-openyield-po": "coreci-hfp", + "coreci-researchx-po": "coreci-hap", + "coreci-secops-lead": "coreci-ciso", + "coreci-spec-dns": "coreci-sre", + "coreci-spec-edge": "coreci-sre", + "coreci-spec-mail": "coreci-sre", + "coreci-spec-monitors": "coreci-sre", + "coreci-spec-sop": "coreci-sre", + "coreci-sre": "coreci-cto" + }, + "manager_edges_unresolvable": [ + { + "reason": "username null (seat unminted; mint at requisition)", + "seat_node": "spec-content-writer" + }, + { + "reason": "username null (seat unminted; mint at requisition)", + "seat_node": "spec-finance-analyst" + }, + { + "reason": "username null (seat unminted; mint at requisition)", + "seat_node": "spec-legal-researcher" + }, + { + "reason": "username null (seat unminted; mint at requisition)", + "seat_node": "spec-onboarding" + }, + { + "reason": "username null (seat unminted; mint at requisition)", + "seat_node": "spec-sec-analyst" + }, + { + "reason": "username null (seat unminted; mint at requisition)", + "seat_node": "spec-sre-ops" + } + ], + "never_execute": "the queue NEVER executes anything against production \u2014 decision-record only (REQ-27; scripts/p04-executor/DESIGN.md)", + "ownership_table_version": "v1.2", + "schema": "coreci.approval_queue.routing/1", + "seats": { + "coreci-cairo": { + "level": 2, + "node": "cairo", + "status": "active" + }, + "coreci-ceo": { + "level": 1, + "node": "ceo", + "status": "active" + }, + "coreci-cfo": { + "level": 2, + "node": "cfo", + "status": "active" + }, + "coreci-chat-po": { + "level": 4, + "node": "chat-po", + "status": "planned" + }, + "coreci-ciso": { + "level": 2, + "node": "ciso", + "status": "active" + }, + "coreci-clo": { + "level": 2, + "node": "clo", + "status": "planned" + }, + "coreci-cmo": { + "level": 2, + "node": "cmo", + "status": "planned" + }, + "coreci-content-lead": { + "level": 4, + "node": "content-lead", + "status": "planned" + }, + "coreci-contracts-lead": { + "level": 4, + "node": "contracts-lead", + "status": "planned" + }, + "coreci-coo": { + "level": 2, + "node": "coo", + "status": "active" + }, + "coreci-cpo": { + "level": 2, + "node": "cpo", + "status": "active" + }, + "coreci-cto": { + "level": 2, + "node": "cto", + "status": "active" + }, + "coreci-fpa-lead": { + "level": 4, + "node": "fpa-lead", + "status": "planned" + }, + "coreci-hap": { + "level": 3, + "node": "hap", + "status": "planned" + }, + "coreci-hbo": { + "level": 3, + "node": "hbo", + "status": "planned" + }, + "coreci-hep": { + "level": 3, + "node": "hep", + "status": "planned" + }, + "coreci-hfp": { + "level": 3, + "node": "hfp", + "status": "planned" + }, + "coreci-hip": { + "level": 3, + "node": "hip", + "status": "planned" + }, + "coreci-hpe": { + "level": 3, + "node": "hpe", + "status": "planned" + }, + "coreci-nextcraft-po": { + "level": 4, + "node": "nextcraft-po", + "status": "planned" + }, + "coreci-nova-po": { + "level": 4, + "node": "nova-po", + "status": "on-hold" + }, + "coreci-openyield-po": { + "level": 4, + "node": "openyield-po", + "status": "planned" + }, + "coreci-researchx-po": { + "level": 4, + "node": "researchx-po", + "status": "planned" + }, + "coreci-secops-lead": { + "level": 4, + "node": "secops-lead", + "status": "planned" + }, + "coreci-spec-dns": { + "level": 5, + "node": "zz-dns", + "status": "bench" + }, + "coreci-spec-edge": { + "level": 5, + "node": "zz-edge", + "status": "bench" + }, + "coreci-spec-mail": { + "level": 5, + "node": "zz-mail", + "status": "bench" + }, + "coreci-spec-monitors": { + "level": 5, + "node": "zz-monitors", + "status": "bench" + }, + "coreci-spec-sop": { + "level": 5, + "node": "zz-sop", + "status": "bench" + }, + "coreci-sre": { + "level": 3, + "node": "sre", + "status": "active" + }, + "jonathan": { + "level": 0, + "node": "chairman", + "status": "active" + } + }, + "sources": { + "org_chart": "company/org/org-chart.json (workspace submodule, read-only)", + "systems_ownership": [ + "docs/company/org/systems-ownership.md (this repo, authoritative)", + "company/org/systems-ownership.md (coreci/company byte-copy, equality asserted at generation)" + ] + }, + "systems": { + "agent-definitions": { + "co_owners": [], + "owned_system": "coreci/agent-definitions", + "owner": "coreci-cairo", + "owner_cell": "CAIRO", + "owner_seat": "cairo", + "routing_note": "agent-read-only; self-mod denied everywhere" + }, + "approval-routing": { + "co_owners": [], + "owned_system": "this table + org-chart.json edges", + "owner": "coreci-ceo", + "owner_cell": "CEO from seat (Chairman pre-seat)", + "owner_seat": "ceo", + "routing_note": "" + }, + "company-records": { + "co_owners": [], + "owned_system": "coreci/company (constitution, registry, org, standards)", + "owner": "coreci-ceo", + "owner_cell": "CEO from seat (Chairman pre-seat)", + "owner_seat": "ceo", + "routing_note": "registry maintenance RACI = CAIRO (standards/registry-maintenance.md)" + }, + "edge-haproxy": { + "co_owners": [], + "owned_system": "haproxy-1 SNI/TCP frontends + LE TLS", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "" + }, + "employee-homes-standard": { + "co_owners": [], + "owned_system": "home-repo scaffold + opencode.json canonicals + drift monitors", + "owner": "coreci-cairo", + "owner_cell": "CAIRO", + "owner_seat": "cairo", + "routing_note": "per-home operational state owned by the employee" + }, + "employee-runner-fleet": { + "co_owners": [], + "owned_system": "employee-* runner LXCs + opencode image", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "digest pin D-112; label changes SRE-owned" + }, + "executor-service": { + "co_owners": [], + "owned_system": "executor.coreci.dev approval queue (LXC 116/117)", + "owner": "coreci-sre", + "owner_cell": "coreci-sre (service)", + "owner_seat": "sre", + "routing_note": "routing-map custody = CEO (Chairman pre-seat); repos frozen" + }, + "gitea-instance": { + "co_owners": [], + "owned_system": "git.coreci.dev (Gitea 1.26.1)", + "owner": "coreci-sre", + "owner_cell": "coreci-sre (CTO at seat)", + "owner_seat": "sre", + "routing_note": "instance admin class = Chairman-direct for coreci-sre requests" + }, + "meetings": { + "co_owners": [], + "owned_system": "coreci/meetings (transcripts, labels, issues)", + "owner": "coreci-coo", + "owner_cell": "COO", + "owner_seat": "coo", + "routing_note": "transcript freshness + action-item aging monitors" + }, + "models-catalog": { + "co_owners": [ + "jonathan" + ], + "owned_system": "agent-definitions/models/catalog.json + ollama keys", + "owner": "coreci-cairo", + "owner_cell": "CAIRO (catalog + quarterly rotation); Chairman (wave mints)", + "owner_seat": "cairo", + "routing_note": "spend-jump rows escalate to Chairman (D-169)" + }, + "notify-ladder": { + "co_owners": [], + "owned_system": "Matrix + SMTP + ntfy alert ladder", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "URLs live in Bao KV" + }, + "observability": { + "co_owners": [], + "owned_system": "Kuma (LXC 118) + Pomerium (LXC 120)", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "" + }, + "openbao": { + "co_owners": [], + "owned_system": "bao.coreci.dev (IDP + secrets)", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "AppRole/KV schema changes = CAIRO + SRE joint" + }, + "products": { + "co_owners": [], + "owned_system": "product repos (researchx, nextcraft, coreci-chat, nova-platform, openyield, acdl)", + "owner": "coreci-cpo", + "owner_cell": "CPO + product POs (post-hire ratification)", + "owner_seat": "cpo", + "routing_note": "portfolio actions = owner approval per constitution #3" + }, + "pve-estate": { + "co_owners": [], + "owned_system": "Proxmox VE + LXC estate", + "owner": "coreci-sre", + "owner_cell": "coreci-sre (CTO at seat)", + "owner_seat": "sre", + "routing_note": "pipeline-only mutations (operator mandate)" + }, + "security-posture": { + "co_owners": [], + "owned_system": "security/compliance posture + incident policy", + "owner": "coreci-ciso", + "owner_cell": "CISO at seat (coreci-sre interim)", + "owner_seat": "ciso", + "routing_note": "RED-class skips path \u2192 CISO + CEO + Chairman" + }, + "sre-repo": { + "co_owners": [], + "owned_system": "coreci/sre (SOPs, workflows, IaC)", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "" + }, + "stalwart": { + "co_owners": [], + "owned_system": "stalwart-1 mail (cloudinit.dev + coreci.dev internal-only)", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "D-086 assert monthly; policy row Chairman-direct" + }, + "technitium-dns": { + "co_owners": [], + "owned_system": "dns.coreci.dev authoritative zones", + "owner": "coreci-sre", + "owner_cell": "coreci-sre", + "owner_seat": "sre", + "routing_note": "coreci.dev zone policy = Chairman veto (D-086: never external MX)" + }, + "workforce-ledger": { + "co_owners": [], + "owned_system": "company/org/workforce/ (dossiers, skill matrix)", + "owner": "coreci-cairo", + "owner_cell": "CAIRO", + "owner_seat": "cairo", + "routing_note": "" + } + } +}