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
20 changes: 10 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: "1.26"
- name: golangci-lint
uses: golangci/golangci-lint-action@v7
uses: golangci/golangci-lint-action@9fae48acfc02a90574d7c304a1758ef9895495fa # v7
with:
version: v2.11.4

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: "1.26"
- name: Run tests
Expand All @@ -36,24 +36,24 @@ jobs:
exit 1
fi
- name: Upload coverage
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
with:
file: coverage.out

vet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: "1.26"
- run: go vet ./...

dashboard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
- name: Build dashboard
Expand Down
28 changes: 25 additions & 3 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,38 @@ on:
branches: [main, staging]

jobs:
ci-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: "1.26"
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
- name: Lint
uses: golangci/golangci-lint-action@9fae48acfc02a90574d7c304a1758ef9895495fa # v7
with:
version: v2.11.4
- name: Test
run: go test -race ./...
- name: Vet
run: go vet ./...
- name: Dashboard build
run: cd dashboard/svelte && npm ci && npm run build && npm run check

docker:
needs: [ci-gate]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Log in to GHCR
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -29,7 +51,7 @@ jobs:
fi

- name: Build and push to GHCR
uses: docker/build-push-action@v5
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
with:
context: .
push: true
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,36 @@ jobs:
contents: write
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: "1.26"
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"

- name: Build dashboard
run: cd dashboard/svelte && npm ci && npm run build

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6
with:
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to GHCR
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
Expand All @@ -53,7 +53,7 @@ jobs:
echo "minor=$MINOR" >> $GITHUB_OUTPUT

- name: Build and push Docker image
uses: docker/build-push-action@v5
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
with:
context: .
push: true
Expand Down
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,24 @@ Thumbs.db
# Environment
.env
.env.local
*.key

# Coverage (explicit)
coverage.out

# Node
node_modules/

# Dashboard build output
dashboard/svelte/build/
dashboard/svelte/node_modules/
dashboard/svelte/.svelte-kit/

# Temporary files
tmp/
.tools/

# Runtime data
.oberwatch/
oberwatch
*.db
*.db-shm
Expand Down
16 changes: 9 additions & 7 deletions BRANCHING.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Branching Strategy

Oberwatch uses GitHub Flow with a protected `staging` branch in front of `main`.
Oberwatch uses a protected `staging` branch in front of `main`.

## Branch Overview

- `main` is the production-ready branch. Every merge to `main` should be stable and eligible for release.
- `main` is the beta / pre-production branch. Every merge to `main` should be stable enough for preview testing and eligible for a tagged release.
- `staging` is the integration branch. Feature work lands here first for combined testing.
- `feature/*` branches are short-lived branches created from `staging` for normal work.
- `hotfix/*` branches are short-lived branches created from `main` for urgent production fixes.
- `hotfix/*` branches are short-lived branches created from `main` for urgent fixes that must be promoted quickly toward the next beta or tagged release.

## Feature Workflow

Expand All @@ -32,18 +32,18 @@ Every pull request to `staging` must pass CI before merge.
When `staging` is stable, open a pull request from `staging` to `main`.

- Merge to `main` only after CI passes.
- Use squash merge to keep history clean.
- Treat every merge to `main` as production-ready.
- Use a merge commit so `main` preserves the exact tested integration state from `staging`.
- Treat every merge to `main` as beta / pre-production ready, not as the final stable release.

Merges to `main` publish the `latest` container image. Merges to `staging` publish the `staging` container image.
Merges to `main` publish the `beta` container image. Merges to `staging` publish the `staging` container image.

## Tagged Releases

Tagged releases are created from `main` only.

- Create a tag like `v0.1.0` on `main`.
- Pushing the tag runs the release workflow.
- The release workflow publishes binaries plus container images to GHCR and Docker Hub.
- The release workflow publishes binaries plus stable container images to GHCR and Docker Hub.
- Container tags include the full version, the minor version alias, and `latest`.

## Hotfix Workflow
Expand All @@ -62,6 +62,8 @@ Open the hotfix pull request against `main`. After it merges, cherry-pick the sa

- Create `feature/*` branches from `staging`.
- Open normal pull requests into `staging`.
- Use squash merge for normal feature PRs into `staging`.
- Promote `staging` into `main` when the integration branch is stable.
- Use a merge commit for `staging` -> `main` promotion PRs.
- Create release tags from `main` only.
- Create `hotfix/*` branches from `main`, merge them to `main`, then backport to `staging`.
31 changes: 25 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.1.0] - 2026-03-30

### Added
- Initial project scaffolding
- Go module setup (`github.com/OberWatch/oberwatch`)
- Package structure: proxy, budget, trace, eval, config, dashboard, alert, provider, pricing
- Makefile with build, test, lint targets
- CI/CD pipeline configuration
- Community files (CONTRIBUTING, CODE_OF_CONDUCT, SECURITY)
- Reverse proxy for OpenAI, Anthropic, Google, and Ollama APIs
- Streaming (SSE) passthrough with accurate token counting
- Agent auto-registration on first proxied request via X-Oberwatch-Agent header
- Per-agent budget enforcement with configurable actions: reject, downgrade, alert, kill
- Model auto-downgrade chains when budget threshold is reached
- Global budget cap with configurable period (hourly, daily, weekly, monthly)
- Runaway detection with configurable request rate window and auto-kill
- Emergency stop with resume — pauses all agent proxy traffic without affecting dashboard or API
- Agent management via dashboard: rename, edit budgets, kill, enable, reset
- Budget persistence in SQLite with periodic in-memory to disk flush
- Webhook and Slack alert integrations with deduplication
- Dashboard: Overview, Agents, Costs, and Settings pages
- Real-time dashboard updates via Server-Sent Events
- First-run onboarding wizard with admin account creation
- Session-based authentication with 24h expiry and password change
- Built-in model pricing tables for OpenAI, Anthropic, and Google models
- One-line install script for Linux and macOS with systemd service setup
- Docker support with named volume persistence
- Docker Compose template with commented enterprise service placeholders
- GHCR image publishing: beta (from main), staging (from staging branch)
- Docker Hub image publishing on tagged releases
- CI/CD: lint, test, 80% coverage gate, dashboard build, automated releases via GoReleaser
- Docker volume mount detection with startup warning when data is not persisted
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ RUN CGO_ENABLED=1 go build -ldflags="-s -w -X main.channel=${CHANNEL} -X main.co

# Runtime stage
FROM alpine:3.20
RUN apk add --no-cache ca-certificates sqlite-libs
RUN apk add --no-cache ca-certificates sqlite-libs && \
addgroup -S oberwatch && adduser -S oberwatch -G oberwatch && \
mkdir -p /data && chown oberwatch:oberwatch /data
COPY --from=builder /app/oberwatch /usr/local/bin/oberwatch

EXPOSE 8080
VOLUME ["/data"]

USER oberwatch
ENTRYPOINT ["oberwatch"]
CMD ["serve"]
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,12 @@ Then open `http://localhost:8080` to complete setup.
### Docker

```bash
docker run -d -p 8080:8080 -v oberwatch-data:/data ghcr.io/oberwatch/oberwatch:latest
docker run -d -p 8080:8080 -v oberwatch-data:/data ghcr.io/oberwatch/oberwatch:beta
```

For preview testing, use the beta channel instead of the staging channel:


### Docker Compose (for Enterprise Edition)

```bash
Expand Down
Loading
Loading