Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
- package-ecosystem: npm
directory: "/web"
schedule:
interval: weekly
- package-ecosystem: npm
directory: "/mobile"
schedule:
interval: weekly
- package-ecosystem: cargo
directory: "/engine"
schedule:
interval: weekly
- package-ecosystem: cargo
directory: "/voice"
schedule:
interval: weekly
- package-ecosystem: docker
directory: "/"
schedule:
interval: weekly
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ jobs:
build-args: |
VOGT_SOURCE_REF=main
VOGT_SOURCE_SHA=${{ github.sha }}
VOGT_PRODUCT_VERSION=0.6.2
VOGT_PRODUCT_VERSION=0.7.0
cache-from: |
type=registry,ref=${{ env.CACHE_IMAGE }}:stack-main
type=registry,ref=${{ env.CACHE_IMAGE }}:demo-main
Expand Down Expand Up @@ -532,7 +532,7 @@ jobs:
build-args: |
VOGT_SOURCE_REF=main
VOGT_SOURCE_SHA=${{ github.sha }}
VOGT_PRODUCT_VERSION=0.6.2
VOGT_PRODUCT_VERSION=0.7.0
provenance: true
sbom: true
cache-from: |
Expand Down Expand Up @@ -666,7 +666,7 @@ jobs:
CORE_IMAGE=${{ env.IMAGE }}@${{ needs.image.outputs.digest }}
VOGT_SOURCE_REF=${{ github.ref_name }}
VOGT_SOURCE_SHA=${{ github.sha }}
VOGT_PRODUCT_VERSION=0.6.2
VOGT_PRODUCT_VERSION=0.7.0
INSTALL_AI_CLIENTS=true
# Layer cache on the operator's registry, its own tag so the
# stack and core streams cannot evict each other.
Expand Down Expand Up @@ -716,7 +716,7 @@ jobs:
CORE_IMAGE=${{ env.IMAGE }}@${{ needs.image.outputs.digest }}
VOGT_SOURCE_REF=${{ github.ref_name }}
VOGT_SOURCE_SHA=${{ github.sha }}
VOGT_PRODUCT_VERSION=0.6.2
VOGT_PRODUCT_VERSION=0.7.0
INSTALL_AI_CLIENTS=true
provenance: true
sbom: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ jobs:
- run: uv sync --locked

- name: canonical product version is aligned
run: uv run --no-sync python scripts/check_product_version.py 0.6.2
run: uv run --no-sync python scripts/check_product_version.py 0.7.0

- name: ruff (lint)
run: uv run --no-sync ruff check .
Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/security-alerts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: security alert triage

on:
schedule:
- cron: "17 4 * * *"
workflow_dispatch:

permissions:
contents: read
issues: write
security-events: read

jobs:
triage:
name: track open security alerts
runs-on: [self-hosted]
steps:
- name: create or update tracking issues
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
api="repos/$REPOSITORY"
alerts="$(gh api --paginate "$api/dependabot/alerts?state=open" 2>/dev/null || printf '[]')"
codeql="$(gh api --paginate "$api/code-scanning/alerts?state=open" 2>/dev/null || printf '[]')"
create_issue() {
local marker="$1" title="$2" body="$3"
if ! gh issue list --state open --search "in:body $marker" --json number --jq 'length' | grep -q '^0$'; then return; fi
gh issue create --title "$title" --body "$body" --label security
}
while IFS=$'\t' read -r number summary; do
[ -n "$number" ] || continue
marker="<!-- vogt-dependabot:$number -->"
create_issue "$marker" "Security alert: $summary" "$marker

Dependabot alert **#$number** is open. Review the advisory, affected dependency, and remediation PR; close this issue after verification.

Source: GitHub Dependabot alerts."
done < <(printf '%s' "$alerts" | jq -r '.[] | [(.number|tostring), (.security_advisory.summary // .dependency.package.name)] | @tsv')
while IFS=$'\t' read -r number rule; do
[ -n "$number" ] || continue
marker="<!-- vogt-codeql:$number -->"
create_issue "$marker" "CodeQL alert: $rule" "$marker

CodeQL alert **#$number** is open. Triage the finding, record the disposition, and close this issue once fixed or documented.

Source: GitHub code scanning alerts."
done < <(printf '%s' "$codeql" | jq -r '.[] | [(.number|tostring), (.rule.description // .rule.id)] | @tsv')
29 changes: 29 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,35 @@ of scope unless you can show real impact.

## CI and self-hosted runners

### Automated dependency and code scanning

GitHub dependency graph and Dependabot security updates are enabled for every
manifest Vogt ships (`.github/dependabot.yml`). Pull requests run the
`dependency review` workflow, which blocks a change introducing a high or
critical severity dependency advisory. CodeQL scans Python, TypeScript,
JavaScript, and Rust on pull requests, pushes to `main`, and weekly.

The scheduled `security alert triage` workflow reads open Dependabot and
CodeQL alerts and creates one labelled `security` issue per alert. The issue
contains the alert number as a stable marker, so reruns update the queue
without creating duplicates. Maintainers record remediation or disposition in
that issue before closing it.

After enabling these workflows, configure repository Settings → Rules → Rulesets
(or branch protection for `main`) with these required checks:

- `ci`
- `dependency review`
- `analyze (python)`
- `analyze (javascript-typescript)`
- `analyze (rust)`
- `runner-policy`

Also enable **Dependency graph**, **Dependabot alerts**, and **Dependabot
security updates** under Settings → Advanced Security. These are repository
settings and therefore cannot be represented in tracked files; verify them
after a repository transfer or visibility change.

This is a public repository, and `pull_request`-triggered jobs run on the
project's self-hosted runner pool (`ci.yml`, `codeql.yml`,
`runner-policy.yml`, `docs.yml`, `mirror-base-images.yml`). Those jobs run
Expand Down
2 changes: 1 addition & 1 deletion deploy/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ VOGT_BIND_IP=127.0.0.1

# The image to run. Pin a digest in anything you would call a deployment.
# Ignored when you add deploy/vogt.build.yml, which builds from the checkout.
# VOGT_IMAGE=ghcr.io/thedancingdeveloper-org/vogt:0.6.2
# VOGT_IMAGE=ghcr.io/thedancingdeveloper-org/vogt:0.7.0

# The uid the container runs as. The gid is always 0 — that is what makes the
# data directory writable at any uid. Set this to whoever owns the files this
Expand Down
2 changes: 1 addition & 1 deletion deploy/engine.overlay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ services:
# container carries both halves. Defaults to the same public image the
# base would run, so the embedded core matches it; pin a digest for a
# real deployment. The Dockerfile already carries a public default too.
CORE_IMAGE: "${VOGT_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt:0.6.2}"
CORE_IMAGE: "${VOGT_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt:0.7.0}"
# Optional image-managed agent CLIs. When enabled, versions come from
# engine/agent-versions.env unless an operator deliberately overrides
# one with a reproducible build arg.
Expand Down
2 changes: 1 addition & 1 deletion deploy/examples/custom-stack/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# it is validating; the default is a real published digest so the file builds
# as-is. Resolve the current one with:
#
# docker buildx imagetools inspect ghcr.io/thedancingdeveloper-org/vogt-stack:0.6.2
# docker buildx imagetools inspect ghcr.io/thedancingdeveloper-org/vogt-stack:0.7.0
#
ARG STACK_IMAGE=ghcr.io/thedancingdeveloper-org/vogt-stack@sha256:31cda6daa29442d37d128d1bb10959ddf5cc7128a3e443ecde3f6ef1ea0616b0
FROM ${STACK_IMAGE}
Expand Down
4 changes: 2 additions & 2 deletions deploy/stack.compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ services:
# `prod-<sha>` tags in the same repository are the maintainer's own pods:
# same CLIs, plus estate integrations that address one estate's
# infrastructure and mean nothing outside it. See DEPLOYMENT.md.
image: ${VOGT_STACK_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt-stack:0.6.2}
image: ${VOGT_STACK_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt-stack:0.7.0}
restart: unless-stopped

# tini as PID 1 reaps the processes agent sessions leave behind. The
Expand Down Expand Up @@ -225,7 +225,7 @@ services:
# Digest-pin this for a real deployment, exactly as the stack
# image above. Pin the release family (`X.Y.Z`, `latest`); the default is a
# tag so the file is runnable as-is.
image: ${VOGT_VOICE_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt-voice:0.6.2}
image: ${VOGT_VOICE_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt-voice:0.7.0}
restart: unless-stopped
# It only reads its baked models and writes audio to tmpfs, so it can run
# locked down even though the pod beside it cannot.
Expand Down
2 changes: 1 addition & 1 deletion deploy/vogt.compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ services:
# digest — publishing an image and moving a deployment are separate acts,
# and a digest is the only form of "which image is this" a
# rebuild cannot silently change.
image: ${VOGT_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt:0.6.2}
image: ${VOGT_IMAGE:-ghcr.io/thedancingdeveloper-org/vogt:0.7.0}
restart: unless-stopped

# The image runs as any uid so long as the gid is 0: `/var/lib/vogt` is
Expand Down
2 changes: 1 addition & 1 deletion docs/CUSTOMISATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ pattern: a Dockerfile a few lines long that starts `FROM` the published
`vogt-stack` digest and adds what your sessions need. Keep it in your fork,
build it in your CI, deploy it by digest.

The core image (`ghcr.io/thedancingdeveloper-org/vogt:0.6.2`) is a build
The core image (`ghcr.io/thedancingdeveloper-org/vogt:0.7.0`) is a build
input to the stack image rather than something to deploy on its own. It is
also built to be a base — `USER root`, install, `USER 1000:0`, keeping
`ENTRYPOINT ["vogt"]` and the `root:0`-owned data directory — so extend it
Expand Down
10 changes: 5 additions & 5 deletions docs/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ sidecar, released as a pair and run by one Compose file,
on by default (`COMPOSE_PROFILES=voice`).

The engine is not optional: it is the only way in. The core image,
`ghcr.io/thedancingdeveloper-org/vogt:0.6.2`, is also published at every
`ghcr.io/thedancingdeveloper-org/vogt:0.7.0`, is also published at every
release because the stack image is built from it by digest and the release
manifest records both — it is a build input, not a deployment target.
`deploy/vogt.compose.yml` and `deploy/engine.overlay.yml` run a core and an
Expand Down Expand Up @@ -105,8 +105,8 @@ Everything an operator chooses lives in `deploy/.env`, read by
| `ENGINE_BIND` | no | `127.0.0.1` | Host interface the port is published on. Loopback until you mean to expose it. |
| `ENGINE_PORT` | no | `8910` | Host port the container's 8910 is published on. |
| `ENGINE_PUBLIC_URL` | no | — | The URL clients reach the stack at. Set it once there is a stable one (§4). |
| `VOGT_STACK_IMAGE` | no | `ghcr.io/thedancingdeveloper-org/vogt-stack:0.6.2` | The image to run. Pin a digest (§6). |
| `VOGT_VOICE_IMAGE` | no | `ghcr.io/thedancingdeveloper-org/vogt-voice:0.6.2` | The sidecar. Pin the same release as the stack. |
| `VOGT_STACK_IMAGE` | no | `ghcr.io/thedancingdeveloper-org/vogt-stack:0.7.0` | The image to run. Pin a digest (§6). |
| `VOGT_VOICE_IMAGE` | no | `ghcr.io/thedancingdeveloper-org/vogt-voice:0.7.0` | The sidecar. Pin the same release as the stack. |
| `COMPOSE_PROFILES` | no | `voice` | Clear it to run without the sidecar; the voice controls stay present but inert. |
| `VOGT_BOOTSTRAP_CORE_TOKEN_ACTOR` | no | `agent:engine` | Who the adopted core token acts as. |
| `VOGT_BOOTSTRAP_CORE_TOKEN_SCOPES` | no | `read,work.write,project.write` | What it may do. Everything in the pod can read the file, so this is the blast radius. |
Expand Down Expand Up @@ -301,9 +301,9 @@ a deployment are separate acts, and the digest line is what moves one.
Resolve the digests of a release:

```console
docker buildx imagetools inspect ghcr.io/thedancingdeveloper-org/vogt-stack:0.6.2 \
docker buildx imagetools inspect ghcr.io/thedancingdeveloper-org/vogt-stack:0.7.0 \
| grep -m 1 Digest
docker buildx imagetools inspect ghcr.io/thedancingdeveloper-org/vogt-voice:0.6.2 \
docker buildx imagetools inspect ghcr.io/thedancingdeveloper-org/vogt-voice:0.7.0 \
| grep -m 1 Digest
```

Expand Down
2 changes: 1 addition & 1 deletion mobile/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vogt-mobile",
"version": "0.6.2",
"version": "0.7.0",
"license": "AGPL-3.0-only",
"private": true,
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "vogt"
version = "0.6.2"
version = "0.7.0"
description = "A product development environment for the AI era"
readme = "README.md"
requires-python = ">=3.11"
Expand Down
2 changes: 1 addition & 1 deletion scripts/clean_consumer_smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# credential, no knowledge of the maintainer estate.
#
# scripts/clean_consumer_smoke.sh
# VOGT_STACK_IMAGE=…/vogt-stack:0.6.2 VOGT_VOICE_IMAGE=…/vogt-voice:0.6.2 \
# VOGT_STACK_IMAGE=…/vogt-stack:0.7.0 VOGT_VOICE_IMAGE=…/vogt-voice:0.7.0 \
# scripts/clean_consumer_smoke.sh
#
# It differs from `e2e_stack_smoke.sh` (which walks a *running* stack somebody
Expand Down
2 changes: 1 addition & 1 deletion src/vogt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

from __future__ import annotations

__version__ = "0.6.2"
__version__ = "0.7.0"

__all__ = ["__version__"]
4 changes: 2 additions & 2 deletions tests/test_product_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

def test_product_version_contract_is_in_sync() -> None:
result = subprocess.run(
[sys.executable, "scripts/check_product_version.py", "0.6.2"],
[sys.executable, "scripts/check_product_version.py", "0.7.0"],
cwd=ROOT,
capture_output=True,
text=True,
Expand All @@ -28,6 +28,6 @@ def test_product_version_contract_is_in_sync() -> None:
def test_android_version_name_is_derived_from_the_canonical_mobile_manifest() -> None:
package = (ROOT / "mobile/package.json").read_text(encoding="utf-8")
gradle = (ROOT / "mobile/android/app/build.gradle").read_text(encoding="utf-8")
assert '"version": "0.6.2"' in package
assert '"version": "0.7.0"' in package
assert "new JsonSlurper().parse(file('../../package.json'))" in gradle
assert "versionName androidVersionName" in gradle
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vogt-web",
"version": "0.6.2",
"version": "0.7.0",
"license": "AGPL-3.0-only",
"private": true,
"type": "module",
Expand Down
Loading