Compare commits
1 commit
main
...
fix/issue-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4270be36a |
19 changed files with 36 additions and 129 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Disinto — Agent Instructions
|
# Disinto — Agent Instructions
|
||||||
|
|
||||||
## What this repo is
|
## What this repo is
|
||||||
|
|
@ -39,7 +39,7 @@ disinto/ (code repo)
|
||||||
│ hooks/ — Claude Code session hooks (on-compact-reinject, on-idle-stop, on-phase-change, on-pretooluse-guard, on-session-end, on-stop-failure)
|
│ hooks/ — Claude Code session hooks (on-compact-reinject, on-idle-stop, on-phase-change, on-pretooluse-guard, on-session-end, on-stop-failure)
|
||||||
│ init/nomad/ — cluster-up.sh, install.sh, vault-init.sh, lib-systemd.sh (Nomad+Vault Step 0 installers, #821-#825); wp-oauth-register.sh (Forgejo OAuth2 app + Vault KV seeder for Woodpecker, S3.3); deploy.sh (dependency-ordered Nomad job deploy + health-wait, S4)
|
│ init/nomad/ — cluster-up.sh, install.sh, vault-init.sh, lib-systemd.sh (Nomad+Vault Step 0 installers, #821-#825); wp-oauth-register.sh (Forgejo OAuth2 app + Vault KV seeder for Woodpecker, S3.3); deploy.sh (dependency-ordered Nomad job deploy + health-wait, S4)
|
||||||
├── nomad/ server.hcl, client.hcl (allow_privileged for woodpecker-agent, S3-fix-5), vault.hcl — HCL configs deployed to /etc/nomad.d/ and /etc/vault.d/ by lib/init/nomad/cluster-up.sh
|
├── nomad/ server.hcl, client.hcl (allow_privileged for woodpecker-agent, S3-fix-5), vault.hcl — HCL configs deployed to /etc/nomad.d/ and /etc/vault.d/ by lib/init/nomad/cluster-up.sh
|
||||||
│ jobs/ — Nomad jobspecs: forgejo.hcl (Vault secrets via template, S2.4); woodpecker-server.hcl + woodpecker-agent.hcl (host-net, docker.sock, Vault KV, S3.1-S3.2); agents.hcl (7 roles, llama, Vault-templated bot tokens, S4.1); vault-runner.hcl (parameterized batch dispatch, S5.3); staging.hcl (Caddy file-server, dynamic port — edge discovers via service registration, S5.2); chat.hcl (Claude chat UI, tmpfs via mount block, Vault OAuth secrets, S5.2); edge.hcl (Caddy proxy + dispatcher sidecar, S5.1)
|
│ jobs/ — Nomad jobspecs: forgejo.hcl (Vault secrets via template, S2.4); woodpecker-server.hcl + woodpecker-agent.hcl (host-net, docker.sock, Vault KV, S3.1-S3.2); agents.hcl (7 roles, llama, Vault-templated bot tokens, S4.1); vault-runner.hcl (parameterized batch dispatch, S5.3); staging.hcl (Caddy file-server, S5.2); chat.hcl (Claude chat UI, Vault OAuth secrets, S5.2); edge.hcl (Caddy proxy + dispatcher sidecar, S5.1)
|
||||||
├── projects/ *.toml.example — templates; *.toml — local per-box config (gitignored)
|
├── projects/ *.toml.example — templates; *.toml — local per-box config (gitignored)
|
||||||
├── formulas/ Issue templates (TOML specs for multi-step agent tasks)
|
├── formulas/ Issue templates (TOML specs for multi-step agent tasks)
|
||||||
├── docker/ Dockerfiles and entrypoints: reproduce, triage, edge dispatcher, chat (server.py, entrypoint-chat.sh, Dockerfile, ui/)
|
├── docker/ Dockerfiles and entrypoints: reproduce, triage, edge dispatcher, chat (server.py, entrypoint-chat.sh, Dockerfile, ui/)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Architect — Agent Instructions
|
# Architect — Agent Instructions
|
||||||
|
|
||||||
## What this agent is
|
## What this agent is
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Dev Agent
|
# Dev Agent
|
||||||
|
|
||||||
**Role**: Implement issues autonomously — write code, push branches, address
|
**Role**: Implement issues autonomously — write code, push branches, address
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
# disinto-chat — minimal HTTP backend for Claude chat UI
|
# disinto-chat — minimal HTTP backend for Claude chat UI
|
||||||
#
|
#
|
||||||
# Small Debian slim base with Python runtime and Node.js.
|
# Small Debian slim base with Python runtime.
|
||||||
# Chosen for simplicity and small image size (~100MB).
|
# Chosen for simplicity and small image size (~100MB).
|
||||||
#
|
#
|
||||||
# Image size: ~100MB (well under the 200MB ceiling)
|
# Image size: ~100MB (well under the 200MB ceiling)
|
||||||
#
|
#
|
||||||
# Claude CLI is baked into the image — same pattern as the agents container.
|
# The claude binary is mounted from the host at runtime via docker-compose,
|
||||||
|
# not baked into the image — same pattern as the agents container.
|
||||||
|
|
||||||
FROM debian:bookworm-slim
|
FROM debian:bookworm-slim
|
||||||
|
|
||||||
# Install Node.js (required for Claude CLI) and Python
|
# Install Python (no build-time network access needed)
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
nodejs npm python3 \
|
python3 \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Install Claude Code CLI — chat backend runtime
|
|
||||||
RUN npm install -g @anthropic-ai/claude-code@2.1.84
|
|
||||||
|
|
||||||
# Non-root user — fixed UID 10001 for sandbox hardening (#706)
|
# Non-root user — fixed UID 10001 for sandbox hardening (#706)
|
||||||
RUN useradd -m -u 10001 -s /bin/bash chat
|
RUN useradd -m -u 10001 -s /bin/bash chat
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -234,13 +234,6 @@ fi
|
||||||
rm -f "$_fetch_log"
|
rm -f "$_fetch_log"
|
||||||
done) &
|
done) &
|
||||||
|
|
||||||
# Nomad template renders Caddyfile to /local/Caddyfile via service discovery;
|
|
||||||
# copy it into the expected location if present (compose uses the mounted path).
|
|
||||||
if [ -f /local/Caddyfile ]; then
|
|
||||||
cp /local/Caddyfile /etc/caddy/Caddyfile
|
|
||||||
echo "edge: using Nomad-rendered Caddyfile from /local/Caddyfile" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Caddy as main process — run in foreground via wait so background jobs survive
|
# Caddy as main process — run in foreground via wait so background jobs survive
|
||||||
# (exec replaces the shell, which can orphan backgrounded subshells)
|
# (exec replaces the shell, which can orphan backgrounded subshells)
|
||||||
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile &
|
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile &
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Gardener Agent
|
# Gardener Agent
|
||||||
|
|
||||||
**Role**: Backlog grooming — detect duplicate issues, missing acceptance
|
**Role**: Backlog grooming — detect duplicate issues, missing acceptance
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"issue":850,"group":"lib/generators.sh","title":"compose dup-detection smoke CI failures","reason":"4+ consecutive ci_exhausted failures across PRs #872 #908 #971; planner flagged for human re-scope","ts":"2026-04-19T00:00:00Z"}
|
{"issue":915,"group":"lib/generators.sh","title":"remove no-op sed in generate_compose --build mode","reason":"sed replaces agents: with itself — no behavior change; single-line removal","ts":"2026-04-17T01:04:05Z"}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,12 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"action": "edit_body",
|
"action": "edit_body",
|
||||||
"issue": 1025,
|
"issue": 996,
|
||||||
"body": "## Goal\nVerify that Forgejo, Woodpecker, and chat all function correctly when served\nunder /forge/, /ci/, and /chat/ subpaths on a single domain. Catch redirect\nloops, OAuth callback failures, and asset 404s before they hit production.\n\n## Sprint\nPart of sprint [edge-subpath-chat](https://forgejo:3000/disinto-admin/disinto-ops/pulls/37) — vision issue #623.\n\n## Acceptance criteria\n- [ ] Forgejo login at /forge/ completes without redirect loops\n- [ ] Forgejo OAuth callback for Woodpecker succeeds under subpath\n- [ ] Woodpecker dashboard loads all assets at /ci/ (no 404s on JS/CSS)\n- [ ] Chat OAuth login flow works at /chat/login\n- [ ] Forward_auth on /chat/* rejects unauthenticated requests with 401\n- [ ] Staging content loads at /staging/\n- [ ] Root / redirects to /forge/\n- [ ] CI pipeline added to .woodpecker/ to run this test on edge-related changes\n\n## Affected files\n- `nomad/jobs/edge.hcl` — edge Caddy routing config under test\n- `docker/edge/` — edge container and Caddyfile template\n- `tools/edge-control/register.sh` — route registration\n- `.woodpecker/` — CI pipeline for edge smoke test\n\n## Dependencies\nNone — first issue in sprint.\n"
|
"body": "Flagged by AI reviewer in PR #993.\n\n## Problem\n\nThe consul-template with/else/end pattern using aggressive whitespace trimming (e.g. `{{- with secret ... -}}` / `{{- else -}}` / `{{- end }}` then immediately `{{- with`) strips all newlines between consecutive single-variable env blocks at parse time. This would render the secrets env file as one concatenated line (`GITHUB_TOKEN=valCODEBERG_TOKEN=val...`), which Nomad's `env = true` cannot parse correctly.\n\n## Why not blocked\n\nagents.hcl has been runtime-tested (S4-fix-6 and S4-fix-7 made observable runtime fixes). If the env file were broken, all bot tokens would be absent — a loud, observable failure. This suggests consul-template may handle whitespace trimming differently from raw Go text/template. Needs runtime verification.\n\n## Verification\n\nDeploy either job and inspect the rendered secrets file:\n```\nnomad alloc exec <alloc-id> cat /secrets/bots.env\n```\nConfirm each KEY=VALUE pair is on its own line.\n\n---\n*Auto-created from AI review*\n\n## Affected files\n- `nomad/jobs/agents.hcl` — bots.env template (lines 147-189)\n- `nomad/jobs/vault-runner.hcl` — runner.env template (PR #993)\n\n## Acceptance criteria\n- [ ] Deploy `agents` or `vault-runner` job on factory host\n- [ ] Inspect rendered secrets file: `nomad alloc exec <alloc-id> cat /secrets/bots.env`\n- [ ] Confirm each KEY=VALUE pair is on its own line (not concatenated)\n- [ ] If broken: fix whitespace trimming to preserve newlines between blocks; if fine, close as not-a-bug"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": "add_label",
|
"action": "add_label",
|
||||||
"issue": 1025,
|
"issue": 996,
|
||||||
"label": "backlog"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "edit_body",
|
|
||||||
"issue": 1026,
|
|
||||||
"body": "## Goal\nReplace the blocking one-shot claude --print invocation in the chat backend with\na WebSocket connection that streams tokens to the UI as they arrive.\n\n## Sprint\nPart of sprint [edge-subpath-chat](https://forgejo:3000/disinto-admin/disinto-ops/pulls/37) — vision issue #623.\n\n## Acceptance criteria\n- [ ] /chat/ws endpoint accepts WebSocket upgrade with valid session cookie\n- [ ] /chat/ws rejects upgrade if session cookie is missing or expired\n- [ ] Chat backend streams claude output over WebSocket as text frames\n- [ ] UI renders tokens incrementally as they arrive\n- [ ] Rate limiting still enforced on WebSocket messages\n- [ ] Caddy proxies WebSocket upgrade correctly through /chat/ws with forward_auth\n\n## Affected files\n- `docker/chat/server.py` — chat backend WebSocket endpoint\n- `docker/chat/ui/` — frontend WebSocket client rendering\n- `nomad/jobs/edge.hcl` — Caddy WebSocket proxy config\n- `nomad/jobs/chat.hcl` — chat Nomad job\n\n## Dependencies\n- Depends on #1025 — subpath routing smoke test\n"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "add_label",
|
|
||||||
"issue": 1026,
|
|
||||||
"label": "backlog"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "edit_body",
|
|
||||||
"issue": 1027,
|
|
||||||
"body": "## Goal\nGive the chat container Claude session read-write access to the project working\ntree so the operator can inspect, explain, or modify code — scoped to that tree\nonly, with no access to factory internals, secrets, or Docker socket.\n\n## Sprint\nPart of sprint [edge-subpath-chat](https://forgejo:3000/disinto-admin/disinto-ops/pulls/37) — vision issue #623.\n\n## Acceptance criteria\n- [ ] Chat container bind-mounts the project working tree as a named volume\n- [ ] Claude invocation in server.py sets cwd to the workspace directory\n- [ ] Claude permission mode is acceptEdits (not bypassPermissions)\n- [ ] verify-chat-sandbox.sh updated to assert workspace mount exists\n- [ ] Compose generator adds the workspace volume conditionally\n\n## Affected files\n- `docker/chat/server.py` — Claude invocation and cwd setup\n- `tools/edge-control/verify-chat-sandbox.sh` — sandbox verification\n- `lib/generators.sh` — Compose generator workspace volume\n- `nomad/jobs/chat.hcl` — chat container bind-mount config\n\n## Dependencies\n- Depends on #1025 — subpath routing smoke test\n"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "add_label",
|
|
||||||
"issue": 1027,
|
|
||||||
"label": "backlog"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "edit_body",
|
|
||||||
"issue": 1028,
|
|
||||||
"body": "## Goal\nIf the smoke test reveals unfixable subpath issues, automate the pivot to\nper-service subdomains so the switch is a single config change.\n\n## Sprint\nPart of sprint [edge-subpath-chat](https://forgejo:3000/disinto-admin/disinto-ops/pulls/37) — vision issue #623.\n\n## Acceptance criteria\n- [ ] generators.sh _generate_caddyfile_impl accepts EDGE_ROUTING_MODE env var\n- [ ] In subdomain mode, Caddyfile emits four host blocks per edge-routing-fallback.md\n- [ ] register.sh registers additional subdomain routes when EDGE_ROUTING_MODE=subdomain\n- [ ] OAuth redirect URIs in ci-setup.sh respect routing mode\n- [ ] .env template documents EDGE_ROUTING_MODE with a comment referencing the fallback doc\n\n## Affected files\n- `lib/generators.sh` — _generate_caddyfile_impl routing mode switch\n- `tools/edge-control/register.sh` — subdomain route registration\n- `lib/ci-setup.sh` — OAuth redirect URI handling\n- `projects/*.toml.example` — .env template documentation\n\n## Dependencies\n- Depends on #1025 — subpath routing smoke test\n"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "add_label",
|
|
||||||
"issue": 1028,
|
|
||||||
"label": "backlog"
|
"label": "backlog"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Shared Helpers (`lib/`)
|
# Shared Helpers (`lib/`)
|
||||||
|
|
||||||
All agents source `lib/env.sh` as their first action. Additional helpers are
|
All agents source `lib/env.sh` as their first action. Additional helpers are
|
||||||
|
|
|
||||||
|
|
@ -657,6 +657,7 @@ COMPOSEEOF
|
||||||
|
|
||||||
# In build mode, replace image: with build: for locally-built images
|
# In build mode, replace image: with build: for locally-built images
|
||||||
if [ "$use_build" = true ]; then
|
if [ "$use_build" = true ]; then
|
||||||
|
sed -i 's|^\( agents:\)|\1|' "$compose_file"
|
||||||
sed -i '/^ image: ghcr\.io\/disinto\/agents:/{s|image: ghcr\.io/disinto/agents:.*|build:\n context: .\n dockerfile: docker/agents/Dockerfile\n pull_policy: build|}' "$compose_file"
|
sed -i '/^ image: ghcr\.io\/disinto\/agents:/{s|image: ghcr\.io/disinto/agents:.*|build:\n context: .\n dockerfile: docker/agents/Dockerfile\n pull_policy: build|}' "$compose_file"
|
||||||
sed -i '/^ image: ghcr\.io\/disinto\/edge:/{s|image: ghcr\.io/disinto/edge:.*|build: ./docker/edge\n pull_policy: build|}' "$compose_file"
|
sed -i '/^ image: ghcr\.io\/disinto\/edge:/{s|image: ghcr\.io/disinto/edge:.*|build: ./docker/edge\n pull_policy: build|}' "$compose_file"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# nomad/ — Agent Instructions
|
# nomad/ — Agent Instructions
|
||||||
|
|
||||||
Nomad + Vault HCL for the factory's single-node cluster. These files are
|
Nomad + Vault HCL for the factory's single-node cluster. These files are
|
||||||
|
|
@ -19,8 +19,8 @@ see issues #821–#992 for the step breakdown.
|
||||||
| `jobs/woodpecker-server.hcl` | submitted via `lib/init/nomad/deploy.sh` | Woodpecker CI server; host networking, Vault KV for `WOODPECKER_AGENT_SECRET` + Forgejo OAuth creds (S3.1) |
|
| `jobs/woodpecker-server.hcl` | submitted via `lib/init/nomad/deploy.sh` | Woodpecker CI server; host networking, Vault KV for `WOODPECKER_AGENT_SECRET` + Forgejo OAuth creds (S3.1) |
|
||||||
| `jobs/woodpecker-agent.hcl` | submitted via `lib/init/nomad/deploy.sh` | Woodpecker CI agent; host networking, `docker.sock` mount, Vault KV for `WOODPECKER_AGENT_SECRET`; `WOODPECKER_SERVER` uses `${attr.unique.network.ip-address}:9000` (Nomad interpolation) — port binds to LXC alloc IP, not localhost (S3.2, S3-fix-6, #964) |
|
| `jobs/woodpecker-agent.hcl` | submitted via `lib/init/nomad/deploy.sh` | Woodpecker CI agent; host networking, `docker.sock` mount, Vault KV for `WOODPECKER_AGENT_SECRET`; `WOODPECKER_SERVER` uses `${attr.unique.network.ip-address}:9000` (Nomad interpolation) — port binds to LXC alloc IP, not localhost (S3.2, S3-fix-6, #964) |
|
||||||
| `jobs/agents.hcl` | submitted via `lib/init/nomad/deploy.sh` | All 7 agent roles (dev, review, gardener, planner, predictor, supervisor, architect) + llama variant; Vault-templated bot tokens via `service-agents` policy; `force_pull = false` — image is built locally by `bin/disinto --with agents`, no registry (S4.1, S4-fix-2, S4-fix-5, #955, #972, #978) |
|
| `jobs/agents.hcl` | submitted via `lib/init/nomad/deploy.sh` | All 7 agent roles (dev, review, gardener, planner, predictor, supervisor, architect) + llama variant; Vault-templated bot tokens via `service-agents` policy; `force_pull = false` — image is built locally by `bin/disinto --with agents`, no registry (S4.1, S4-fix-2, S4-fix-5, #955, #972, #978) |
|
||||||
| `jobs/staging.hcl` | submitted via `lib/init/nomad/deploy.sh` | Caddy file-server mounting `docker/` as `/srv/site:ro`; no Vault integration; **dynamic host port** (no static 80 — edge owns 80/443, collision fixed in S5-fix-7 #1018); edge discovers via Nomad service registration (S5.2, #989) |
|
| `jobs/staging.hcl` | submitted via `lib/init/nomad/deploy.sh` | Caddy file-server mounting `docker/` as `/srv/site:ro`; no Vault integration; internal-only via edge proxy (S5.2, #989) |
|
||||||
| `jobs/chat.hcl` | submitted via `lib/init/nomad/deploy.sh` | Claude chat UI; custom `disinto/chat:local` image; sandbox hardening (cap_drop ALL, **tmpfs via mount block** not `tmpfs=` arg — S5-fix-5 #1012, pids_limit 128); Vault-templated OAuth secrets via `service-chat` policy (S5.2, #989) |
|
| `jobs/chat.hcl` | submitted via `lib/init/nomad/deploy.sh` | Claude chat UI; custom `disinto/chat:local` image; sandbox hardening (cap_drop ALL, tmpfs, pids_limit 128); Vault-templated OAuth secrets via `service-chat` policy (S5.2, #989) |
|
||||||
| `jobs/edge.hcl` | submitted via `lib/init/nomad/deploy.sh` | Caddy reverse proxy + dispatcher sidecar; routes /forge, /woodpecker, /staging, /chat; uses `disinto/edge:local` image built by `bin/disinto --with edge`; Vault-templated ops-repo creds via `service-dispatcher` policy (S5.1, #988) |
|
| `jobs/edge.hcl` | submitted via `lib/init/nomad/deploy.sh` | Caddy reverse proxy + dispatcher sidecar; routes /forge, /woodpecker, /staging, /chat; uses `disinto/edge:local` image built by `bin/disinto --with edge`; Vault-templated ops-repo creds via `service-dispatcher` policy (S5.1, #988) |
|
||||||
|
|
||||||
Nomad auto-merges every `*.hcl` under `-config=/etc/nomad.d/`, so the
|
Nomad auto-merges every `*.hcl` under `-config=/etc/nomad.d/`, so the
|
||||||
|
|
|
||||||
|
|
@ -89,22 +89,18 @@ job "chat" {
|
||||||
config {
|
config {
|
||||||
image = "disinto/chat:local"
|
image = "disinto/chat:local"
|
||||||
force_pull = false
|
force_pull = false
|
||||||
# Sandbox hardening (#706): cap_drop ALL, pids_limit 128, tmpfs /tmp
|
# Sandbox hardening (#706): cap_drop ALL (no Linux capabilities)
|
||||||
|
# tmpfs /tmp for runtime files (64MB)
|
||||||
|
# pids_limit 128 (prevent fork bombs)
|
||||||
# ReadonlyRootfs enforced via entrypoint script (fails if running as root)
|
# ReadonlyRootfs enforced via entrypoint script (fails if running as root)
|
||||||
cap_drop = ["ALL"]
|
|
||||||
pids_limit = 128
|
|
||||||
mount {
|
|
||||||
type = "tmpfs"
|
|
||||||
target = "/tmp"
|
|
||||||
readonly = false
|
|
||||||
tmpfs_options {
|
|
||||||
size = 67108864 # 64MB in bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# Security options for sandbox hardening
|
# Security options for sandbox hardening
|
||||||
# apparmor=unconfined needed for Claude CLI ptrace access
|
# apparmor=unconfined needed for Claude CLI ptrace access
|
||||||
# no-new-privileges prevents privilege escalation
|
# no-new-privileges prevents privilege escalation
|
||||||
|
cap_drop = ["ALL"]
|
||||||
|
pids_limit = 128
|
||||||
security_opt = ["apparmor=unconfined", "no-new-privileges"]
|
security_opt = ["apparmor=unconfined", "no-new-privileges"]
|
||||||
|
# tmpfs mount via volumes config (Nomad Docker driver)
|
||||||
|
volumes = ["tmpfs:/tmp:size=64m"]
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Volume mounts ──────────────────────────────────────────────────────
|
# ── Volume mounts ──────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -114,58 +114,6 @@ job "edge" {
|
||||||
read_only = false
|
read_only = false
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Caddyfile via Nomad service discovery (S5-fix-7, issue #1018) ────
|
|
||||||
# Renders staging upstream from Nomad service registration instead of
|
|
||||||
# hardcoded staging:80. Caddy picks up /local/Caddyfile via entrypoint.
|
|
||||||
template {
|
|
||||||
destination = "local/Caddyfile"
|
|
||||||
change_mode = "restart"
|
|
||||||
data = <<EOT
|
|
||||||
# Caddyfile — edge proxy configuration (Nomad-rendered)
|
|
||||||
# Staging upstream discovered via Nomad service registration.
|
|
||||||
|
|
||||||
:80 {
|
|
||||||
# Redirect root to Forgejo
|
|
||||||
handle / {
|
|
||||||
redir /forge/ 302
|
|
||||||
}
|
|
||||||
|
|
||||||
# Reverse proxy to Forgejo
|
|
||||||
handle /forge/* {
|
|
||||||
reverse_proxy forgejo:3000
|
|
||||||
}
|
|
||||||
|
|
||||||
# Reverse proxy to Woodpecker CI
|
|
||||||
handle /ci/* {
|
|
||||||
reverse_proxy woodpecker:8000
|
|
||||||
}
|
|
||||||
|
|
||||||
# Reverse proxy to staging — dynamic port via Nomad service discovery
|
|
||||||
handle /staging/* {
|
|
||||||
{{ range nomadService "staging" }} reverse_proxy {{ .Address }}:{{ .Port }}
|
|
||||||
{{ end }} }
|
|
||||||
|
|
||||||
# Chat service — reverse proxy to disinto-chat backend (#705)
|
|
||||||
# OAuth routes bypass forward_auth — unauthenticated users need these (#709)
|
|
||||||
handle /chat/login {
|
|
||||||
reverse_proxy chat:8080
|
|
||||||
}
|
|
||||||
handle /chat/oauth/callback {
|
|
||||||
reverse_proxy chat:8080
|
|
||||||
}
|
|
||||||
# Defense-in-depth: forward_auth stamps X-Forwarded-User from session (#709)
|
|
||||||
handle /chat/* {
|
|
||||||
forward_auth chat:8080 {
|
|
||||||
uri /chat/auth/verify
|
|
||||||
copy_headers X-Forwarded-User
|
|
||||||
header_up X-Forward-Auth-Secret {$FORWARD_AUTH_SECRET}
|
|
||||||
}
|
|
||||||
reverse_proxy chat:8080
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOT
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Non-secret env ───────────────────────────────────────────────────
|
# ── Non-secret env ───────────────────────────────────────────────────
|
||||||
env {
|
env {
|
||||||
FORGE_URL = "http://forgejo:3000"
|
FORGE_URL = "http://forgejo:3000"
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
# served to staging environment users.
|
# served to staging environment users.
|
||||||
#
|
#
|
||||||
# Network:
|
# Network:
|
||||||
# Dynamic host port — edge discovers via Nomad service registration.
|
# No external port exposed — edge proxy routes to it internally.
|
||||||
# No static port to avoid collisions with edge (which owns 80/443).
|
# Service discovery via Nomad native provider for internal routing.
|
||||||
#
|
#
|
||||||
# Not the runtime yet: docker-compose.yml is still the factory's live stack
|
# Not the runtime yet: docker-compose.yml is still the factory's live stack
|
||||||
# until cutover. This file exists so CI can validate it and S5.2 can wire
|
# until cutover. This file exists so CI can validate it and S5.2 can wire
|
||||||
|
|
@ -27,10 +27,11 @@ job "staging" {
|
||||||
|
|
||||||
# No Vault integration needed — no secrets required (static file server)
|
# No Vault integration needed — no secrets required (static file server)
|
||||||
|
|
||||||
# Internal service — dynamic host port. Edge discovers via Nomad service.
|
# Internal service — no external port. Edge proxy routes internally.
|
||||||
network {
|
network {
|
||||||
port "http" {
|
port "http" {
|
||||||
to = 80
|
static = 80
|
||||||
|
to = 80
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Planner Agent
|
# Planner Agent
|
||||||
|
|
||||||
**Role**: Strategic planning using a Prerequisite Tree (Theory of Constraints),
|
**Role**: Strategic planning using a Prerequisite Tree (Theory of Constraints),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Predictor Agent
|
# Predictor Agent
|
||||||
|
|
||||||
**Role**: Abstract adversary (the "goblin"). Runs a 2-step formula
|
**Role**: Abstract adversary (the "goblin"). Runs a 2-step formula
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Review Agent
|
# Review Agent
|
||||||
|
|
||||||
**Role**: AI-powered PR review — post structured findings and formal
|
**Role**: AI-powered PR review — post structured findings and formal
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# Supervisor Agent
|
# Supervisor Agent
|
||||||
|
|
||||||
**Role**: Health monitoring and auto-remediation, executed as a formula-driven
|
**Role**: Health monitoring and auto-remediation, executed as a formula-driven
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- last-reviewed: a467d613a44b9b475a60c14c4162621e846969ea -->
|
<!-- last-reviewed: 8fc3ba5b59cd6cb15bd01ca0658cfea2bcb12068 -->
|
||||||
# vault/policies/ — Agent Instructions
|
# vault/policies/ — Agent Instructions
|
||||||
|
|
||||||
HashiCorp Vault ACL policies for the disinto factory. One `.hcl` file per
|
HashiCorp Vault ACL policies for the disinto factory. One `.hcl` file per
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue