Skip to content

Artifact publishing foundations (slug, artifacts table, DNS + Caddy TLS)#52

Open
obaid wants to merge 1 commit into
mainfrom
feature/artifact-foundations
Open

Artifact publishing foundations (slug, artifacts table, DNS + Caddy TLS)#52
obaid wants to merge 1 commit into
mainfrom
feature/artifact-foundations

Conversation

@obaid

@obaid obaid commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Feature 1, PR 1 of ~5. Foundations only — no publishing happens yet. Sets up the irreversible/infra pieces the rest builds on so they can be reviewed in isolation.

Recap of the agreed design: agents publish web artifacts (static or running apps) to a per-agent subdomain {agent.slug}.provisionagents.com, each artifact public or gated.

What's in this PR

Piece Detail
agents.slug Globally-unique subdomain key (handle is only unique per team). Generated on create, backfilled for existing agents.
agent_artifacts Table + model + enums: type (static|app), visibility (public|gated), source dir / start command / port, status, public_url.
CloudflareDnsService Idempotent A-record create / repoint / delete for an agent's subdomain. DNS-only (not proxied) so Caddy can complete Let's Encrypt HTTP-01. No-ops/throws clearly when unconfigured.
Caddy on-demand TLS Server setup writes a global on_demand_tls block gated by a new GET /api/caddy/ask endpoint that only returns 200 for hosts mapping to a live artifact — prevents open-ended cert issuance. Per-agent site blocks import from /etc/caddy/sites; the sslip.io host keeps its path-based conf.d snippets.

Config (set on Forge before it goes live)

CLOUDFLARE_API_TOKEN (Zone.DNS edit), CLOUDFLARE_ZONE_ID, ARTIFACT_DOMAIN=provisionagents.com. Until set, CloudflareDnsService::isConfigured() is false and nothing DNS-related runs.

Tests

tests/Feature/Artifacts/ — slug uniqueness + subdomain helper, the DNS client (mocked HTTP: create/idempotent/repoint/delete/unconfigured), the ask endpoint (live vs pending vs unknown vs off-domain), and the Caddyfile output. Full suite green (736 passed).

Next PRs

  1. static publish E2E (publish API + write Caddy site files + DNS + dashboard tab) · 3) running apps · 4) gated access · 5) agent publish tool.

⚠️ The migration adds agents.slug and backfills it — safe, but it's a write over every agent row.

…addy TLS

Groundwork for serving agent-published web artifacts at
{agent.slug}.provisionagents.com. No publishing yet — that's the next PR.

- agents.slug: globally-unique subdomain key (handle is only unique per team),
  generated on create and backfilled for existing agents.
- agent_artifacts table + model + enums (static|app, public|gated).
- CloudflareDnsService: idempotent A-record create/repoint/delete for an
  agent's subdomain, DNS-only so Caddy can do HTTP-01. Gated by config
  (CLOUDFLARE_API_TOKEN / CLOUDFLARE_ZONE_ID / ARTIFACT_DOMAIN).
- Caddy: server setup now writes a global on_demand_tls block (gated by a new
  GET /api/caddy/ask endpoint that only allows hosts with a live artifact) and
  imports per-agent site blocks from /etc/caddy/sites; the sslip.io host keeps
  its path-based conf.d snippets.

Tests cover slug uniqueness, the DNS client (mocked), the ask endpoint, and the
Caddyfile output. Full suite green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant