Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ace6263
feat(dashboard): update file picker dialog
krishna-santosh Jun 20, 2026
813e317
chore(dashboard): fix lint issues
krishna-santosh Jun 20, 2026
5e537db
chore: add rustfmt and clippy to rust-toolchain.toml
krishna-santosh Jun 20, 2026
86e078a
chore: set publish = false in Cargo.toml
krishna-santosh Jun 20, 2026
e37137c
ci: add Dependabot, cargo-deny, and release workflow
krishna-santosh Jun 20, 2026
1fe252e
ci: update CI workflow with expanded test matrix
krishna-santosh Jun 20, 2026
97343f9
refactor: box figment error in Config::load
krishna-santosh Jun 20, 2026
8b28d97
refactor: use let-chaining in paths::home
krishna-santosh Jun 20, 2026
2338272
refactor: return bool from RateLimiter::check instead of Result
krishna-santosh Jun 20, 2026
731d9c3
refactor: rename StorageKind::from_str to parse
krishna-santosh Jun 20, 2026
3f1678a
refactor: use ArtifactBundle type alias and let-chaining in backup se…
krishna-santosh Jun 20, 2026
31a9eab
refactor: add parameter structs for repository trait methods
krishna-santosh Jun 20, 2026
9f3fb82
refactor: update SQLite repositories to use parameter structs
krishna-santosh Jun 20, 2026
cd2ee53
refactor: update Postgres repositories to use parameter structs
krishna-santosh Jun 20, 2026
6dc16f6
refactor: update MySQL repositories to use parameter structs
krishna-santosh Jun 20, 2026
f52304a
refactor: update services to use input parameter structs
krishna-santosh Jun 20, 2026
d937952
refactor: update in-memory test helpers to use parameter structs
krishna-santosh Jun 20, 2026
95bd31d
refactor: update HTTP handlers and GraphQL mutation to use service in…
krishna-santosh Jun 20, 2026
8e5d981
refactor: update gRPC layer to use input structs and InvalidToken error
krishna-santosh Jun 20, 2026
a6dd964
refactor: reorganize MCP server module order and use UpdateEntryInput
krishna-santosh Jun 20, 2026
395e81c
chore: suppress clippy::too_many_arguments on GraphQL entries query
krishna-santosh Jun 20, 2026
3c5043d
style: fix doc comment indentation in search schema
krishna-santosh Jun 20, 2026
aa77e18
test: update integration tests for API changes
krishna-santosh Jun 20, 2026
1eb5b34
ci: pass explicit toolchain to dtolnay/rust-toolchain
krishna-santosh Jun 20, 2026
4411029
feat(dashboard): enhance backups section with Field components for be…
krishna-santosh Jun 21, 2026
aaff845
fix(breadcrumb): update mapping logic for breadcrumb items to ensure …
krishna-santosh Jun 21, 2026
3de0175
fix(workflows): add persist-credentials option to checkout step for a…
krishna-santosh Jun 21, 2026
f2bbbf9
fix(tests): include site_id in entry update logic to ensure correct e…
krishna-santosh Jun 21, 2026
09c51da
fix(handlers): replace StatusCode with AppError for storage retrieval…
krishna-santosh Jun 21, 2026
619e02f
style: formatting
krishna-santosh Jun 21, 2026
2d6d0ce
fix(workflows): enhance release workflow for multi-architecture suppo…
krishna-santosh Jun 21, 2026
bf80677
style: sort imports
krishna-santosh Jun 21, 2026
67382ff
fix(ci): replace Biome lint with Biome CI for dashboard and web jobs
krishna-santosh Jun 21, 2026
e382e3e
style(dashboard): formatting
krishna-santosh Jun 21, 2026
235cc61
chore: formatting and biome ci fixes
krishna-santosh Jun 21, 2026
515cc48
rm bun.lockb
krishna-santosh Jun 21, 2026
99e1808
chore(web): allow unoptimized images
krishna-santosh Jun 21, 2026
49cd3d3
fix: replace img with Image from next
krishna-santosh Jun 21, 2026
b1407b5
style(web): sort imports
krishna-santosh Jun 21, 2026
ea38712
Revert "rm bun.lockb"
krishna-santosh Jun 21, 2026
ce42d71
ci: update macOS runner versions in release workflow to 26
krishna-santosh Jun 21, 2026
2644104
ci: optimize caching and update test command to use nextest
krishna-santosh Jun 21, 2026
8b572fa
ci: replace nextest with cargo test for improved testing consistency
krishna-santosh Jun 21, 2026
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
36 changes: 36 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
version: 2
updates:
# Rust backend (workspace). Replaces hand-bumping deps.
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10
groups:
cargo-minor-patch:
update-types:
- minor
- patch

# Frontend + web (bun reads package.json; npm ecosystem covers the workspace).
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10
groups:
npm-minor-patch:
update-types:
- minor
- patch

# Keep the SHA-pinned GitHub Actions current so pinning doesn't rot.
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10
groups:
actions-all:
patterns:
- "*"
31 changes: 31 additions & 0 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Security audit

# Scheduled RustSec advisory scan. Unlike the per-PR cargo-deny job, this catches
# NEW advisories filed against the existing Cargo.lock even when no code changes.
on:
schedule:
# 06:00 UTC every Monday.
- cron: "0 6 * * 1"
workflow_dispatch:
push:
paths:
- "**/Cargo.toml"
- "**/Cargo.lock"
- ".github/workflows/audit.yml"

permissions:
contents: read
issues: write
checks: write
Comment thread
krishna-santosh marked this conversation as resolved.

jobs:
audit:
name: cargo audit (RustSec)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998 # v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
224 changes: 199 additions & 25 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,121 @@ on:
push:
branches: [main]

# Cancel superseded runs on the same ref to save CI minutes.
# Cancel superseded runs on the same ref to save CI minutes. Only cancel on PRs —
# never cancel an in-flight run on main, which could be the one catching a regression.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

# Least privilege: jobs only read the repo (setup-protoc gets the token it needs).
permissions:
contents: read

env:
CARGO_TERM_COLOR: always

jobs:
# Decide which areas changed so we only run the jobs that matter. Pure doc edits
# (README, CLAUDE.md, AGENTS.md, LICENSE, .agents/**, .claude/**) match no filter,
# so every build job below is skipped while the `ci-status` gate stays green.
changes:
name: Detect changes
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
rust: ${{ steps.filter.outputs.rust }}
dashboard: ${{ steps.filter.outputs.dashboard }}
web: ${{ steps.filter.outputs.web }}
other: ${{ steps.filter.outputs.other }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3
id: filter
with:
filters: |
rust:
- 'apps/backend/**'
- 'libs/proto/**'
- 'Cargo.toml'
- 'Cargo.lock'
- 'rust-toolchain.toml'
- 'clippy.toml'
- 'rustfmt.toml'
- 'deny.toml'
- '.github/workflows/**'
dashboard:
- 'apps/dashboard/**'
- 'package.json'
- 'bun.lock'
- 'nx.json'
- '.github/workflows/**'
web:
- 'apps/web/**'
- 'package.json'
- 'bun.lock'
- 'nx.json'
- '.github/workflows/**'
# Catch-all: anything that is NOT purely docs/agent files. Guards against
# the default-skip trap where a change matching none of the area filters
# above (e.g. a new Dockerfile or top-level script) would silently skip all
# build jobs while ci-status stays green. The rust lanes treat `other` as a
# baseline trigger, so non-doc changes always compile + test the core.
other:
- '!**/*.md'
- '!.claude/**'
- '!.agents/**'
- '!LICENSE'
- '!AGENTS.md'

lint:
name: Rust lint (fmt + clippy)
needs: changes
if: needs.changes.outputs.rust == 'true' || needs.changes.outputs.other == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: apps/backend
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- uses: dtolnay/rust-toolchain@stable
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# Toolchain (channel + rustfmt/clippy components) comes from rust-toolchain.toml.
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
toolchain: "1.94"
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: apps/backend
# Share the dependency cache with the linux test lanes (deps are
# identical; clippy's final artifacts differ but the heavy 3rd-party
# layer is reused). rust-cache prunes to deps before saving, so a
# single shared cache serves lint + all 3 db lanes.
shared-key: linux
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --locked -- -D warnings
# --no-default-features drops `embed-dashboard`, whose RustEmbed derive needs
# apps/dashboard/dist at compile time (not built in CI).
- run: cargo clippy --no-default-features --all-targets --locked -- -D warnings

security:
name: Supply-chain (cargo-deny)
needs: changes
if: needs.changes.outputs.rust == 'true' || needs.changes.outputs.other == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: EmbarkStudios/cargo-deny-action@bb137d7af7e4fb67e5f82a49c4fce4fad40782fe # v2
with:
command: check

test:
name: Tests (${{ matrix.db }})
needs: changes
if: needs.changes.outputs.rust == 'true' || needs.changes.outputs.other == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
defaults:
run:
working-directory: apps/backend
Expand Down Expand Up @@ -64,6 +148,8 @@ jobs:
TEST_DATABASE_URL: ${{ matrix.test_database_url }}
# Both services run for every lane; the sqlite lane simply ignores them
# (GitHub Actions can't attach services conditionally per matrix value).
# Service containers are Linux-only, which is why Windows/macOS live in the
# separate `test-os` job (SQLite only).
services:
postgres:
image: postgres:16
Expand All @@ -90,37 +176,125 @@ jobs:
--health-timeout 5s
--health-retries 15
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: "1.94"
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: apps/backend
# All 3 db lanes compile an identical binary (db is chosen at runtime
# via TEST_DATABASE), so one shared cache lets lanes 2 & 3 restore
# fully warm. Shared with the lint job too (deps are identical).
shared-key: linux
# --no-default-features drops `embed-dashboard` (RustEmbed needs a built
# apps/dashboard/dist at compile time, which CI doesn't produce).
- name: cargo test
run: cargo test --no-default-features --locked ${{ matrix.test_args }}

# Cross-platform coverage. The binary ships on Windows/macOS/Linux, so the suite
# must run off Linux too. Service containers don't run on these runners, so only
# the SQLite lane (in-memory, no external server) is exercised here.
test-os:
name: Tests (${{ matrix.os }}, sqlite)
needs: changes
if: needs.changes.outputs.rust == 'true' || needs.changes.outputs.other == 'true'
runs-on: ${{ matrix.os }}
timeout-minutes: 30
defaults:
run:
working-directory: apps/backend
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest]
env:
TEST_DATABASE: sqlite
TEST_DATABASE_URL: ""
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: "1.94"
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: apps/backend
key: ${{ matrix.db }}
shared-key: ${{ matrix.os }}
# --no-default-features drops `embed-dashboard` (no built dashboard/dist in CI).
- name: cargo test
run: cargo test --locked ${{ matrix.test_args }}
run: cargo test --no-default-features --locked

frontend:
name: Frontend (dashboard)
needs: changes
if: needs.changes.outputs.dashboard == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
- run: bun install --frozen-lockfile
- name: Biome lint
run: bunx nx run dashboard:lint
# Persist the Nx local cache so dashboard:build replays across runs.
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .nx/cache
key: nx-${{ runner.os }}-${{ hashFiles('apps/dashboard/**', 'bun.lock', 'package.json', 'nx.json') }}
restore-keys: |
nx-${{ runner.os }}-
- name: Biome CI
run: bunx biome ci
working-directory: apps/dashboard
- name: Typecheck
run: bun run test:dashboard
run: bunx nx run dashboard:typecheck
- name: Build
run: bun run build:dashboard
run: bunx nx run dashboard:build

web:
name: Web (landing + docs)
needs: changes
if: needs.changes.outputs.web == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
- run: bun install --frozen-lockfile
# Persist the Nx local cache so web:build replays across runs.
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .nx/cache
key: nx-${{ runner.os }}-${{ hashFiles('apps/web/**', 'bun.lock', 'package.json', 'nx.json') }}
restore-keys: |
nx-${{ runner.os }}-
- name: Biome CI
run: bunx biome ci
working-directory: apps/web
- name: Typecheck
run: bunx nx run web:typecheck
- name: Build
run: bun run build:web
run: bunx nx run web:build

# Single required status check. Branch protection should require ONLY this job.
# It passes when every needed job either succeeded or was skipped (path filter),
# and fails if any of them actually failed or was cancelled. This avoids the
# "skipped required check stays pending forever" trap of naive path filtering.
ci-status:
name: CI status
needs: [changes, lint, security, test, test-os, frontend, web]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Verify no job failed
run: |
if echo '${{ join(needs.*.result, ',') }}' | grep -Eq 'failure|cancelled'; then
echo "A required job failed or was cancelled: ${{ join(needs.*.result, ',') }}"
exit 1
fi
echo "All jobs succeeded or were skipped: ${{ join(needs.*.result, ',') }}"
Loading
Loading