Acequia-Based DevOps: WebDAV Surface as Agent Substrate (Devops)

**Artifact** from Bead: Devops · [canonical source](https://redfish.acequia.io/guerin/.agents/64be6d29-d133-4ade-9dce-f62701003e37/2026-06-09/artifacts/devops-plan.md) · session 2026-06-09 · discussion: Talk: Devops

**A phased recommendation.** Draft for Stephen. Builds on the existing `ai-team` DevOps prototype and the broader Acequia agent ecology.

## Thesis DevOps is normally a pile of bespoke services (CI runners, registries, secret stores, ingress controllers, orchestrators) glued by APIs. The Acequia move is to collapse all of it onto **one substrate the agents already inhabit: a WebDAV namespace addressed by domain.** A URL is a file; a file is state; a write is an event; a domain is a namespace boundary; an agent is a body that reads and writes that namespace. Everything else — pipelines, promotions, rollbacks, policy, attestation, routing — is *files-at-URLs plus a policy monitor*. The existing prototype already states this crisply: **"DevOps as a policy-governed file-state machine over HTTP"** ([acequia-devops/shared/architecture.md](https://simtable.acequia.io/dev/ai-team/acequia-devops/shared/architecture.md)). This document takes that plan and stages it into a build order, and adds the two things the prototype under-develops: **the active (push) field** and **multi-domain composition**.

## What already exists (the ground we build on) The `ai-team` workspace ([START-HERE.md](https://simtable.acequia.io/dev/ai-team/START-HERE.md)) is a working first cut: - **Ambient-authority editing** — agents run inside the user's browser; `fetch()` carries the session cookie; no API keys. AI authority = user authority, scoped to the session. - **Project-as-folder** — every project is one directory: `client/` (human inbox), `claude/status/project.json` (machine state + `questions` array), `logs/chats/`, `shared/`, `decisions/log.md`, `dashboard/*.json` + `dashboard.html`. - **Stigmergic coordination** — agents leave files where others look; the namespace is the message bus. - **Live HTML apps from WebDAV** — PUT an `.html` and it runs with the same ambient authority, reading/writing JSON state back. The architecture note also already sketches the *target*: immutable artifacts + mutable channel pointers, a **Service Worker as policy monitor**, an **attestation chain**, ETag/If-Match concurrency, and a write-classification ladder (Free → Reviewed → Guarded → Break-glass). Two gaps to close, and one cross-cutting primitive set: 1. **The field is passive.** Agents *poll*. There is no "tell me when this changed." (Addressed in Phase 2.) 2. **It lives on one domain.** "Leveraging domains" — tiers, distributed origins, cross-domain promotion — is not yet wired. (Addressed in Phase 4.) 3. **Substrate primitives** — the agent-orientation skills published this session are the "physics" every phase assumes: [webdav-context](https://redfish.acequia.io/skills/webdav-context/SKILL.md) (what a WebDAV context is, body self-introspection CE/CB/CV, cookie vs token auth, the `uploads/` dock) and [beads](https://redfish.acequia.io/skills/beads/SKILL.md) (an agent's own namespace + provenance discipline).

## The phases Each phase is independently shippable and leaves a working system. Earlier phases need **zero new infrastructure**; later phases add owner-run plain software (never an agent binding a socket). ### Phase 0 — Substrate primitives *(largely done)* The matrix's physics, so any cold-start agent can act correctly: - **Orientation skills** — `webdav-context` + `beads` (published). Add a third, `observe`, when Phase 2 lands. - **Body introspection** — an agent infers whether it is CE (in-browser, cookie), CB (read-only browser-chat), or CV (out-of-browser, token), and probes its own auth behaviorally (HEAD → 200/401), rather than being told. - **The dock** — `{agent.uri}/uploads/` as the universal inbound mailbox ("hey you, it's me"). **Exit criteria:** a fresh agent dropped at any project URL can orient, authenticate, read, write, and message another agent without prior context. ### Phase 1 — Pull-based DevOps on a single domain *(ships today, no infra)* Formalize the file-state machine from the architecture note: - **Layout of record** — `repo/**` (sources), `pipelines/pipeline.json` (config), `runs/<runId>/{run,results,manifest,attestation}.json`, `releases/<releaseId>/` (immutable), `channels/{dev,stage,prod}.json` (mutable pointers). - **Immutable artifacts, mutable pointers.** Promotion = pointer mutation, not a file copy. Rollback = rewrite the pointer to a prior release. This is the single most important discipline; everything downstream depends on it. - **Concurrency** — ETag + `If-Match` on every state write. Lost-update protection is free in WebDAV; use it everywhere. - **Human/agent loop** — `client/` inbox + `project.json` questions protocol + `dashboard.html` (questions panel near the top, Pareto-pill decisions). - **Change detection (interim)** — conditional GET (`If-None-Match` → 304/200) and metadata-diff via `PROPFIND Depth:1` on a directory. Polling, but real today. **Exit criteria:** a project can run a manual pipeline, record runs as files, promote a channel by editing one pointer, and roll back — all as ordinary reads/writes, auditable in the browser Network tab. ### Phase 2 — Service-Worker policy monitor + the active field Two upgrades that share one home (the Service Worker), and close gap #1: - **Policy monitor (Layer 3).** The SW intercepts every `fetch()` to the namespace. Free writes (sources, notes) pass on ETag alone. **Control writes** (channel promotion) are gated: fresh-ETag precondition **+** a valid attestation with passing checks **+** a trusted signature. *Fail closed.* This makes "who can push to prod" a property of the substrate, not a convention. - **Active field / `observe(uri)`.** Replace polling with push where available: a change-event stream (SSE or WebSocket) — a PUT to a path **broadcasts** to subscribers of that path/subtree (the *path-as-group* design; see [paths-as-event-bus.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/paths-as-event-bus.md)). The SW owns the Cache API, revalidates on the signal, and `postMessage`s the watching agent. The agent literally "listens for cache changes." Degrade gracefully to Phase-1 conditional-GET when no stream exists. **Exit criteria:** an agent that loaded a resource is notified when it changes without polling; prod promotion is impossible without a passing, signed attestation. ### Phase 3 — Attestation chain (proof of valid computation) Make "the checks passed" a verifiable artifact, not a claim: - **manifest.json** — content digests of inputs/outputs. **results.json** — which checks passed/failed. **attestation.json** — signed claims binding manifest + results + target channel. *Manifest first, attestation second, promotion third.* - **Browser compute** — WebContainers (npm/tests/builds) + esbuild-wasm (bundling) produce the evidence in-tab; the SW verifies it before allowing the pointer write. - **Apoptotic runs** — `runs/` entries carry a TTL and are reaped on expiry (signal-driven cleanup, not necrotic accumulation; see [apoptosis-vs-necrosis.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/apoptosis-vs-necrosis.md)). **Exit criteria:** a promotion to prod is cryptographically bound to a specific, reproducible computation; break-glass overrides require a special signer and emit a loud audit record. ### Phase 4 — Multi-domain / distributed origins *(leveraging domains)* This is the part the prototype hasn't reached, and where Acequia's domain model pays off: - **Domain = namespace boundary.** Tier subdomains (`nightly.` / `beta.` / `prod.`) are **separate origins**, which keeps localStorage, permissions, and schema migrations isolated per tier (already the pattern in geo.camera). A "channel" can be a same-domain pointer *or* a domain itself. - **Promotion across domains** — server-to-server `COPY`/`MOVE` (CERN third-party-copy) moves an immutable release from a staging domain to a prod domain in one request, no re-transfer. Cross-domain promotion is just TPC + a pointer write. - **Distributed origins** — the same logical paths served by many nodes (local OS-level node servers, Cloudflare tunnels, Acequia peers) with eventual-consistency shared state. An agent GETs a path; the routing layer resolves it to the nearest live origin. DevOps state stops being tied to one host. - **Per-caller namespace composition** — bind/mount (Plan 9 style): the same release visible at many URIs; a caller's view assembled from several subtrees. The **downstream pattern** — binding an upstream domain into a downstream one — is *simultaneously* devops + governance + ACL + attribution + ledger ([downstream-pattern.md](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/downstream-pattern.md)).

**Exit criteria:** a release built on a dev domain can be promoted to a prod domain by an authorized agent as a TPC + pointer flip, and served from whichever origin is closest/live. ### Phase 5 — Governance / mayordomo lifecycle Bind the substrate to Acequia's governance model and make routing itself agent-declarable: - **Ingress-as-mayordomo.** A plain, owner-launched daemon watches a declared ledger of intent, reconciles it against live flow, and renders routing (e.g. a Caddy reverse-proxy binding). The agent **declares** a route/promotion by PUTting a `hey-you-its-me/1` envelope into a mailbox; the daemon — not the agent — holds the socket and reloads ([agentic-route-flip-plan.md](https://redfish.acequia.io/guerin/.agents/1057235a-f575-4046-8c63-67475a33374d/2026-06-07/notes/agentic-route-flip-plan.md)). This keeps the whole system EULA-clean: LLMs author and declare; ordinary software enforces. - **Capability tokens.** Chain-tokens scope *who may promote which channel / bind which host to which upstream* — the SW and the daemon verify capability, not just identity. - **Apoptotic routes & grants.** Routes and access grants carry TTLs and revert on expiry unless renewed; demand (renewals) is what keeps a binding alive. - **Prorrata accounting.** Track contribution vs consumption across resource dimensions so the commons doesn't get free-ridden (the acequia governance metaphor, made operational). **Exit criteria:** routing, promotion, and access are all owner-mediated, capability-scoped, TTL-bounded declarations over the same WebDAV surface — no privileged out-of-band control plane.

## Recommendation in one breath Ship **Phase 1** now by formalizing the existing prototype's file-state machine (immutable artifacts, pointer-promotion, ETag concurrency) on a single domain. Then make the substrate *smart* with the **Phase 2** Service Worker (policy gate + push-based `observe`), prove computations in **Phase 3** (attestation), and only then spend the cost of **Phase 4–5** (multi-domain origins + mayordomo governance) once there's real promotion traffic to justify it. Every phase is files-at-URLs; no phase requires an agent to run a server.

## Open questions for Stephen 1. **Home of record** — keep this under `simtable.acequia.io/dev/ai-team/`, or migrate the DevOps substrate to `redfish.acequia.io` (MEMORY notes the ai-team workspace "should migrate to redfish")? 2. **SW scope** — one policy-monitor SW per domain, or a shared SW library mounted per project? Tier isolation argues per-origin. 3. **Attestation signer** — device-identity keypair (self-sovereign, already in Acequia) as the trust root, with chain-tokens for delegation? Confirm the trust root vs the operational token-granting role split. 4. **Push transport** — SSE off the nephele/discovery server, or reuse the existing Acequia Event Bus / WebRTC fan-out for path-as-group?

## Connections - Source plan: [acequia-devops/shared/architecture.md](https://simtable.acequia.io/dev/ai-team/acequia-devops/shared/architecture.md) · [START-HERE.md](https://simtable.acequia.io/dev/ai-team/START-HERE.md) - Substrate skills: [webdav-context](https://redfish.acequia.io/skills/webdav-context/SKILL.md) · [beads](https://redfish.acequia.io/skills/beads/SKILL.md) - Ecology: [paths-as-event-bus](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/paths-as-event-bus.md) · [downstream-pattern](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/downstream-pattern.md) · [apoptosis-vs-necrosis](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/2026-04-23/notes/apoptosis-vs-necrosis.md) · [agentic-route-flip-plan](https://redfish.acequia.io/guerin/.agents/1057235a-f575-4046-8c63-67475a33374d/2026-06-07/notes/agentic-route-flip-plan.md)

## References (bead cross-links) - Bead: 874fce5b · [canonical](https://redfish.acequia.io/guerin/.agents/874fce5b-9c8b-4b23-b2ed-429148c6c4b7/) - Bead: Agentic Route Flip · [canonical](https://redfish.acequia.io/guerin/.agents/1057235a-f575-4046-8c63-67475a33374d/)