Skip to content

Commit faa2ae3

Browse files
geekypunkclaude
andcommitted
chore: establish OSS contribution infrastructure
Phase 1 ("safety net") of the Open Source Repository Process: the pieces that must exist before the repository is made public. CI (.github/workflows/ci.yml) gates on four checks that are green today -- frontend build, backend compile+package, MCP syntax across all 63 files, and a docker compose build. The backend test suite and eslint run as advisory jobs instead, because both are red on main right now (77 of 1293 tests fail; eslint reports 41 errors, including 6 react-hooks/rules-of-hooks). A required check that always fails is indistinguishable from a broken merge queue, so each is promoted to required the day its suite goes green. CODEOWNERS routes the vault, authentication, SQL-execution, SSH tunnelling, dashboard-bridge and MCP paths to @DeepSQLAI/security. Two paths named in the process document do not exist (backend/**/vault/, backend/**/sql/execution/); these map to the real files instead. Note that CODEOWNERS cannot require a larger number of approvals on specific paths -- GitHub carries one repo-wide count -- so the two-approval rule is documented as a maintainer convention in both CODEOWNERS and SECURITY.md rather than implied to be enforced. Dependabot covers maven, npm (root and mcp/), docker and github-actions. The document's docker directory of /docker contains no Dockerfile; the images build from /Dockerfile and /backend/Dockerfile. CodeQL is guarded on repository visibility. Code scanning requires GitHub Advanced Security on a private repository, so without the guard every run would fail with a 403 until the repository is public. The Maven wrapper required removing backend/.mvn/ from .gitignore. Left in place, the scripts would have been committed without the properties file that pins the version -- the one thing the wrapper exists to provide. Branch protection, secret scanning, push protection and private vulnerability reporting are not in this commit: GitHub refuses all four on a private repository under a free plan. They are applied immediately after the visibility flip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 0f99014 commit faa2ae3

9 files changed

Lines changed: 898 additions & 1 deletion

File tree

.github/CODEOWNERS

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Code owners for DeepSQL.
2+
#
3+
# GitHub applies LAST MATCH WINS — only the final matching pattern's owners are
4+
# requested. Order therefore matters: the catch-all is first and the narrow
5+
# security paths are last, so a change under backend/.../security/ is routed to
6+
# @DeepSQLAI/security and not merely to the maintainers.
7+
#
8+
# A caveat worth stating in the file itself, because the process document implies
9+
# otherwise: CODEOWNERS cannot require a DIFFERENT NUMBER of approvals for
10+
# particular paths. Branch protection carries one repo-wide approval count. What
11+
# CODEOWNERS does guarantee is WHO must approve. The two-approval rule on the
12+
# vault, auth and SQL-execution paths is therefore a reviewer convention here,
13+
# not a machine-enforced gate — see the note in SECURITY.md.
14+
#
15+
# Teams, not usernames, on purpose: a permissions change is then one edit to the
16+
# team roster rather than a sweep across this file.
17+
18+
* @DeepSQLAI/maintainers
19+
20+
# ── Build, packaging and self-host surface ──────────────────────────────────
21+
# A broken first run is a severe defect for us: the product is distributed as
22+
# "clone and build", so these files are the install experience.
23+
/Dockerfile @DeepSQLAI/maintainers
24+
/docker/ @DeepSQLAI/maintainers
25+
/docker-compose.yml @DeepSQLAI/maintainers
26+
/backend/Dockerfile @DeepSQLAI/maintainers
27+
/backend/pom.xml @DeepSQLAI/maintainers
28+
/backend/mvnw @DeepSQLAI/maintainers
29+
/backend/mvnw.cmd @DeepSQLAI/maintainers
30+
/backend/.mvn/ @DeepSQLAI/maintainers
31+
/scripts/self-host/ @DeepSQLAI/maintainers
32+
/.github/ @DeepSQLAI/maintainers
33+
34+
# Renaming anything here silently breaks every operator's .env on upgrade.
35+
/.env.example @DeepSQLAI/maintainers
36+
37+
# ── Security-critical: convention is two maintainer approvals ───────────────
38+
# Credential vault, encryption key handling, authentication and JWT. The vault
39+
# holds an AES-GCM key whose loss is unrecoverable.
40+
/backend/src/main/java/com/dbaagent/security/ @DeepSQLAI/security
41+
/backend/src/main/java/com/dbaagent/service/security/ @DeepSQLAI/security
42+
43+
# Read-only SQL execution enforcement. This is the guardrail standing between a
44+
# generated statement and a customer's production database.
45+
/backend/src/main/java/com/dbaagent/service/McpSqlGuardService.java @DeepSQLAI/security
46+
/backend/src/main/java/com/dbaagent/service/QueryExecutionContext.java @DeepSQLAI/security
47+
/backend/src/main/java/com/dbaagent/service/QueryExecutionPolicyService.java @DeepSQLAI/security
48+
/backend/src/main/java/com/dbaagent/service/QueryExecutionPolicyException.java @DeepSQLAI/security
49+
/backend/src/main/java/com/dbaagent/model/McpReadOnlyQueryRequest.java @DeepSQLAI/security
50+
/backend/src/main/java/com/dbaagent/model/McpReadOnlyExplainRequest.java @DeepSQLAI/security
51+
/backend/src/main/java/com/dbaagent/model/QueryExecutionOrigin.java @DeepSQLAI/security
52+
/backend/src/main/java/com/dbaagent/provider/api/QueryExecutionProvider.java @DeepSQLAI/security
53+
54+
# SSH tunnelling: reaches into networks the operator has not otherwise exposed.
55+
/backend/src/main/java/com/dbaagent/service/SshTunnelService.java @DeepSQLAI/security
56+
57+
# The dashboard sandbox and its read-only query bridge. The public controller is
58+
# reachable unauthenticated for as long as a dashboard is shared.
59+
/backend/src/main/java/com/dbaagent/controller/DashboardQueryController.java @DeepSQLAI/security
60+
/backend/src/main/java/com/dbaagent/controller/PublicDashboardController.java @DeepSQLAI/security
61+
/src/components/DashboardArtifact.jsx @DeepSQLAI/security
62+
63+
# The MCP tool surface and its authorisation: an agent-facing remote surface.
64+
/mcp/ @DeepSQLAI/security

.github/dependabot.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
version: 2
2+
3+
# Directories here are the ones that actually contain a manifest — verified
4+
# against the tree rather than assumed. In particular there is no Dockerfile
5+
# under /docker (it holds nginx and postgres config only); the images build from
6+
# /Dockerfile and /backend/Dockerfile.
7+
updates:
8+
# ── Java backend ────────────────────────────────────────────────────────────
9+
- package-ecosystem: maven
10+
directory: /backend
11+
schedule:
12+
interval: weekly
13+
open-pull-requests-limit: 5
14+
commit-message:
15+
prefix: "chore(deps)"
16+
17+
# ── Frontend ────────────────────────────────────────────────────────────────
18+
- package-ecosystem: npm
19+
directory: /
20+
schedule:
21+
interval: weekly
22+
open-pull-requests-limit: 5
23+
commit-message:
24+
prefix: "chore(deps)"
25+
groups:
26+
# Dev tooling moves constantly and carries no runtime risk. Grouping it
27+
# keeps this to one PR a week instead of a dozen nobody reviews properly —
28+
# review fatigue is how a real security bump gets rubber-stamped.
29+
dev-dependencies:
30+
dependency-type: development
31+
32+
# ── MCP server / DeepSQL CLI ────────────────────────────────────────────────
33+
# A separately published npm package, so its manifest is not covered by the
34+
# root entry above.
35+
- package-ecosystem: npm
36+
directory: /mcp
37+
schedule:
38+
interval: weekly
39+
open-pull-requests-limit: 5
40+
commit-message:
41+
prefix: "chore(deps)"
42+
43+
# ── Container base images ───────────────────────────────────────────────────
44+
- package-ecosystem: docker
45+
directory: /
46+
schedule:
47+
interval: weekly
48+
commit-message:
49+
prefix: "chore(deps)"
50+
51+
- package-ecosystem: docker
52+
directory: /backend
53+
schedule:
54+
interval: weekly
55+
commit-message:
56+
prefix: "chore(deps)"
57+
58+
# ── GitHub Actions ──────────────────────────────────────────────────────────
59+
# Monthly is enough: actions change slowly, and a pinned action is a supply
60+
# chain dependency like any other.
61+
- package-ecosystem: github-actions
62+
directory: /
63+
schedule:
64+
interval: monthly
65+
commit-message:
66+
prefix: "ci"

.github/workflows/ci.yml

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
name: ci
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
7+
8+
# A force-push or a rapid second push should not leave two runs racing; the older
9+
# one is cancelled rather than burning a runner on a commit nobody will merge.
10+
concurrency:
11+
group: ci-${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
# Read-only by default. Nothing here writes to the repository, and a fork-based
15+
# pull request must never hold a writable token.
16+
permissions:
17+
contents: read
18+
19+
jobs:
20+
# ── Required checks ────────────────────────────────────────────────────────
21+
# Everything in this group passes on main today. Only checks that are green
22+
# from the first run belong here: a required check that always fails is
23+
# indistinguishable from a broken merge queue and teaches people to ignore CI.
24+
25+
frontend:
26+
name: frontend (build)
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v4
30+
- uses: actions/setup-node@v4
31+
with:
32+
node-version: '22'
33+
cache: npm
34+
- run: npm ci
35+
- run: npm run build
36+
37+
backend:
38+
name: backend (compile + package)
39+
runs-on: ubuntu-latest
40+
steps:
41+
- uses: actions/checkout@v4
42+
- uses: actions/setup-java@v4
43+
with:
44+
distribution: temurin
45+
java-version: '25'
46+
cache: maven
47+
# No database service here on purpose: with tests skipped nothing opens a
48+
# connection, so this job stays fast and has exactly one failure mode —
49+
# the code does not compile, or does not package.
50+
- run: ./mvnw -B -ntp -DskipTests verify
51+
working-directory: backend
52+
53+
mcp:
54+
name: mcp (syntax)
55+
runs-on: ubuntu-latest
56+
steps:
57+
- uses: actions/checkout@v4
58+
- uses: actions/setup-node@v4
59+
with:
60+
node-version: '22'
61+
# Every JS file in the package, not just the entrypoint: the server is a
62+
# thin shim over lib and command modules, and a syntax error in any of them
63+
# surfaces only when an agent loads that path at runtime.
64+
- name: Syntax-check MCP sources
65+
run: find mcp -name '*.js' -not -path '*/node_modules/*' -print0 | xargs -0 -n1 node --check
66+
67+
compose-build:
68+
name: docker compose build
69+
runs-on: ubuntu-latest
70+
steps:
71+
- uses: actions/checkout@v4
72+
# Catches the case where the code compiles but the image does not. Our
73+
# distribution path is "clone and build", so an unbuildable image is a
74+
# total outage for a new user even when every test passes.
75+
- name: Synthesize .env
76+
run: |
77+
cp .env.example .env
78+
printf 'SECURITY_JWT_SECRET=%s\n' "$(openssl rand -base64 64 | tr -d '\n')" >> .env
79+
printf 'ENCRYPTION_KEY=%s\n' "$(openssl rand -base64 32)" >> .env
80+
- run: docker compose build
81+
82+
# ── Advisory checks ────────────────────────────────────────────────────────
83+
# These run on every pull request and report, but do not block. They are staged
84+
# this way because both are red on main right now (backend: 77 of 1293 tests
85+
# failing; frontend: 41 eslint errors). Promote each to a required check in
86+
# branch protection the day its suite goes green — that promotion is the point
87+
# of running them, not an afterthought.
88+
89+
backend-tests:
90+
name: backend tests (advisory)
91+
runs-on: ubuntu-latest
92+
continue-on-error: true
93+
services:
94+
postgres:
95+
# pgvector, not stock postgres: rag_documents.embedding is vector(3072)
96+
# and the schema will not create against an image without the extension.
97+
image: pgvector/pgvector:pg18
98+
env:
99+
POSTGRES_USER: postgres
100+
POSTGRES_PASSWORD: postgres
101+
POSTGRES_DB: dba_agent
102+
ports:
103+
- 5432:5432
104+
options: >-
105+
--health-cmd "pg_isready -U postgres"
106+
--health-interval 10s
107+
--health-timeout 5s
108+
--health-retries 10
109+
steps:
110+
- uses: actions/checkout@v4
111+
- uses: actions/setup-java@v4
112+
with:
113+
distribution: temurin
114+
java-version: '25'
115+
cache: maven
116+
# Generated per run and discarded with the runner, rather than written into
117+
# this file or held as a repository secret. Nothing in the test suite needs
118+
# a key that outlives the job, so nothing should own one. The id must be
119+
# local-2025-01: application-test.properties pins ENCRYPTION_KEY_ID to it.
120+
- name: Generate ephemeral encryption key
121+
run: echo "ENCRYPTION_KEYS=local-2025-01:$(openssl rand -base64 32)" >> "$GITHUB_ENV"
122+
- run: ./mvnw -B -ntp test
123+
working-directory: backend
124+
env:
125+
TEST_DB_URL: jdbc:postgresql://localhost:5432/dba_agent?sslmode=disable
126+
TEST_DB_USERNAME: postgres
127+
TEST_DB_PASSWORD: postgres
128+
AZURE_SEARCH_API_KEY: dummy-test-key
129+
- name: Publish test summary
130+
if: always()
131+
run: |
132+
echo '### Backend test results' >> "$GITHUB_STEP_SUMMARY"
133+
echo '```' >> "$GITHUB_STEP_SUMMARY"
134+
grep -ho 'Tests run:.*' backend/target/surefire-reports/*.txt 2>/dev/null \
135+
| tail -5 >> "$GITHUB_STEP_SUMMARY" \
136+
|| echo 'no surefire reports produced' >> "$GITHUB_STEP_SUMMARY"
137+
echo '```' >> "$GITHUB_STEP_SUMMARY"
138+
139+
lint:
140+
name: frontend lint (advisory)
141+
runs-on: ubuntu-latest
142+
continue-on-error: true
143+
steps:
144+
- uses: actions/checkout@v4
145+
- uses: actions/setup-node@v4
146+
with:
147+
node-version: '22'
148+
cache: npm
149+
- run: npm ci
150+
- run: npm run lint

.github/workflows/codeql.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: codeql
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
schedule:
9+
# Weekly, so a newly published query catches an old vulnerability that was
10+
# not a finding on the day the code merged. Scanning only on change would
11+
# never re-examine code that has stopped being touched.
12+
- cron: '27 4 * * 1'
13+
14+
permissions:
15+
contents: read
16+
17+
jobs:
18+
analyze:
19+
name: analyze (${{ matrix.language }})
20+
runs-on: ubuntu-latest
21+
# Code scanning is free on public repositories; on a private one it requires
22+
# GitHub Advanced Security, which this organisation's free plan does not
23+
# include. Without this guard every run fails with a 403 until the repository
24+
# is public, and a permanently red workflow trains people to stop reading CI.
25+
# DELETE THIS LINE once the repository is public — from then on a failure
26+
# here is a real finding rather than a billing state.
27+
if: github.event.repository.visibility == 'public'
28+
permissions:
29+
# Required to upload results to the code-scanning API.
30+
security-events: write
31+
contents: read
32+
actions: read
33+
strategy:
34+
fail-fast: false
35+
matrix:
36+
include:
37+
- language: java-kotlin
38+
- language: javascript-typescript
39+
steps:
40+
- uses: actions/checkout@v4
41+
42+
- name: Initialize CodeQL
43+
uses: github/codeql-action/init@v3
44+
with:
45+
languages: ${{ matrix.language }}
46+
# `none` extracts from source instead of observing a compiler. Chosen
47+
# deliberately for the Java half: an autobuild would have to reproduce
48+
# the JDK 25 toolchain and full Maven dependency resolution, so it
49+
# fails for build reasons far more often than it finds a vulnerability.
50+
# The JavaScript half never has a build mode.
51+
build-mode: none
52+
53+
- name: Perform CodeQL analysis
54+
uses: github/codeql-action/analyze@v3
55+
with:
56+
category: /language:${{ matrix.language }}

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ backend/target/
4545
# deployment profiles must never be committed:
4646
backend/src/main/resources/application-*prod-local.properties
4747
backend/src/main/resources/application-azprod.properties
48-
backend/.mvn/
48+
# backend/.mvn/ is deliberately NOT ignored: it carries the Maven wrapper
49+
# properties that pin CI and every contributor to one Maven version. Ignoring it
50+
# would make `commit mvnw` silently half-complete — the scripts would land and the
51+
# version pin would not, which is the failure the wrapper exists to prevent.
52+
# Ignore only the local state Maven writes into that directory itself.
53+
backend/.mvn/timing.properties
4954
# large test data (over GitHub 100MB limit)
5055
backend/test_data_inserts.sql
5156
backend/comprehensive_test_data_mysql.sql

0 commit comments

Comments
 (0)