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
6 changes: 0 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,3 @@ ANALYSIS_MAX_DURATION_SECONDS=1800
AI_EGRESS_MODE=hosted
AI_EGRESS_ALLOWED_BASE_URLS=
AI_EGRESS_ALLOWED_CIDRS=

# Docker Compose PostgreSQL defaults. Compose consumes these values; the local
# backend .env example uses SQLite so direct local startup works without services.
POSTGRES_USER=partha
POSTGRES_PASSWORD=partha
POSTGRES_DB=partha
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ body:
id: environment
attributes:
label: Environment
description: Browser, OS, Node/Python versions, Docker availability, branch/commit.
description: Browser, OS, Node/Python versions, and branch/commit.
35 changes: 0 additions & 35 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -280,38 +280,3 @@ jobs:
apps/frontend/test-results
if-no-files-found: warn
retention-days: 14

docker-compose:
name: Docker Compose
needs: repository-hygiene
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Build backend image
run: docker build -t partha-backend:ci apps/backend

- name: Validate Compose configuration
run: docker compose config

- name: Run Compose stack
run: docker compose up --build -d

- name: Verify Compose API readiness
run: |
for attempt in {1..30}; do
if curl -fsS http://127.0.0.1:8000/ready; then
exit 0
fi
docker compose ps
sleep 2
done

docker compose logs api postgres redis
exit 1

- name: Stop Compose stack
if: always()
run: docker compose down -v
17 changes: 0 additions & 17 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,6 @@ jobs:
working-directory: apps/backend
run: python -m pytest

- name: Build backend image
run: docker build -t partha-backend:release apps/backend

- name: Validate Compose runtime
run: |
docker compose up --build -d
for attempt in {1..30}; do
if curl -fsS http://127.0.0.1:8000/ready; then
docker compose down -v
exit 0
fi
sleep 2
done
docker compose logs api postgres redis
docker compose down -v
exit 1

github-release:
name: Publish GitHub Release
needs: validate
Expand Down
6 changes: 0 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,6 @@ tmp/
temp/
.cache/

# ==========================================
# Docker
# ==========================================

docker-compose.override.yml

# ==========================================
# Misc
# ==========================================
Expand Down
7 changes: 2 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

These are the project rules, not a welcome page. If you follow them, your pull request can be reviewed and merged. If you do not, it will be sent back regardless of the quality of the code.

PARTHA is a self-hosted Repository Intelligence Platform. One architectural rule sits above all others:
PARTHA is a Repository Intelligence Platform. One architectural rule sits above all others:

> **Repository Intelligence is the shared repository-understanding layer. Architecture, dependencies, reviews, documentation, exports, and optional AI features consume it. AI must remain a downstream consumer, never an independent interpreter of the repository.**

Expand Down Expand Up @@ -42,7 +42,6 @@ maintainer; do not treat roadmap content as something you may revise.
| Python | 3.12 or 3.13 | Backend |
| Node.js | 22 | Frontend |
| Git | any recent | Everything |
| Docker | any recent | Optional local Compose stack |

### Backend

Expand Down Expand Up @@ -353,8 +352,6 @@ Run the checks relevant to your change. These are what CI runs.
| `npm --prefix apps/frontend run test` | Frontend tests (vitest) |
| `npm run lint:frontend` | ESLint |
| `npm run build:frontend` | `tsc -b && vite build` — type errors surface here, not in lint |
| `npm run docker:config` | `docker compose config` |
| `npm run docker:validate` | Starts the local Compose stack, waits for `/ready`, tears it down |

`npm run build` runs the frontend build plus the backend tests. It does **not** run frontend lint or frontend tests — run those separately.

Expand All @@ -364,7 +361,7 @@ Run the checks relevant to your change. These are what CI runs.
| API request/response shape | `npm run test:backend`, update the frontend client and types, `npm run build:frontend` |
| Database models | Add an Alembic migration, then `npm run test:backend` (migration up/down is covered) |
| Frontend code | `npm run lint:frontend`, `npm --prefix apps/frontend run test`, `npm run build:frontend` |
| Docker, Compose, CI, config, startup, health | `npm run docker:config` and `npm run docker:validate` |
| Local startup, CI, config, health | Smoke-check the affected backend/frontend start command and run the relevant tests above |
| Anything user-visible | Update the documentation **in the same pull request** |

Three backend tests are gated on real PostgreSQL and Redis and skip locally; CI provides both services.
Expand Down
66 changes: 5 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,54 +130,12 @@ Read [Repository Intelligence](docs/architecture/REPOSITORY_INTELLIGENCE.md) for
| Python | 3.12 or 3.13 | Backend |
| Node.js | 22 | Frontend and workflow scripts |
| Git | Recent version | Checkout and public GitHub import |
| Docker Engine with Compose and buildx plugins | Recent version | One-command full stack |

### Preferred: start the full stack
PARTHA currently uses separate backend and frontend development processes. The
development configuration uses SQLite, an in-memory rate limiter, and local
filesystem storage. No container runtime or external database is required.

With Docker Engine running, build and start the frontend, API, PostgreSQL, and
Redis from this checkout:

```bash
npm run partha
```

The command waits for both application services to become healthy, then prints
the frontend URL. Open `http://localhost:5173`, register a local account, add a
repository, and start analysis. Press `Ctrl+C` to stop all four services.

On repeat runs the images are reused from cache, so startup is fast. If you have
already built the images once and only want to restart the existing containers
without the build step, use:

```bash
npm run partha:up
```

To stop the stack without the interactive `Ctrl+C` (for example from another
terminal), use:

```bash
npm run partha:down
```

PostgreSQL data and imported repository storage persist across ordinary stops
and restarts. To permanently delete that local Compose data and return to a
clean state, run:

```bash
docker compose down -v
```

> **Warning:** The reset command permanently deletes the Compose database and
> repository-storage volumes.

### Alternative: start services separately

The standalone development configuration uses SQLite, an in-memory rate
limiter, and local filesystem storage. It requires Python 3.12 or 3.13 and
Node.js 22, but does not require Docker.

#### 1. Start the backend
### 1. Start the backend

No `.env` file is required.

Expand All @@ -196,7 +154,7 @@ npm run dev:backend

The API starts at `http://localhost:8000`; OpenAPI is at `/docs` and readiness is at `/ready`.

#### 2. Start the frontend
### 2. Start the frontend

In a second terminal:

Expand All @@ -209,17 +167,6 @@ npm run dev:frontend
Open `http://localhost:5173`, register a local account, add a repository, and
start analysis.

### Lower-level Compose commands

The launcher wraps these lower-level commands and performs prerequisite and
readiness checks. The Compose stack is local development guidance, not
production deployment guidance.

```bash
npm run docker:config
npm run docker:up
```

See the [AI provider egress policy](docs/security/AI_PROVIDER_EGRESS.md) before
configuring any custom or local provider endpoint.

Expand All @@ -240,9 +187,6 @@ npm run build:frontend

# Disposable fixtures and browser journeys
npm run test:prototype

# Compose configuration and /ready lifecycle
npm run docker:validate
```

The prototype browser suite exercises defined Architecture, Engineering Review, Insights, evidence, and responsive-accessibility journeys. Passing it verifies those journeys; it does not imply complete product maturity.
Expand Down
19 changes: 0 additions & 19 deletions apps/backend/.dockerignore

This file was deleted.

39 changes: 0 additions & 39 deletions apps/backend/Dockerfile

This file was deleted.

19 changes: 5 additions & 14 deletions apps/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Local development defaults to SQLite at `.local/partha.db` and storage at `.loca

### SQLite concurrency (development only)

The durable analysis worker (a background thread) and API request handlers read and write the same SQLite file concurrently. Every SQLite connection is opened with `PRAGMA journal_mode=WAL` and a 5-second `PRAGMA busy_timeout` (`app/core/database.py`, a no-op on PostgreSQL): WAL lets a reader always see the last committed snapshot without waiting on an in-progress writer, and the busy timeout bounds the remaining writer-vs-writer wait instead of failing immediately (#162). This does not extend to multiple *processes* sharing one SQLite file — that remains PostgreSQL's job; Compose already runs Postgres for exactly this reason. The analysis worker's own per-stage transaction boundaries (why a stage's facts are flushed but not committed until the stage checkpoint) are documented directly in `app/workers/analysis_worker.py`'s module docstring and were deliberately left unchanged — restructuring them risks the job-recovery guarantees (leases, retries, stale-worker takeover) that same docstring exists to protect, and WAL removes the actual reader-blocking symptom without needing to.
The durable analysis worker (a background thread) and API request handlers read and write the same SQLite file concurrently. Every SQLite connection is opened with `PRAGMA journal_mode=WAL` and a 5-second `PRAGMA busy_timeout` (`app/core/database.py`, a no-op on PostgreSQL): WAL lets a reader always see the last committed snapshot without waiting on an in-progress writer, and the busy timeout bounds the remaining writer-vs-writer wait instead of failing immediately (#162). This does not extend to multiple *processes* sharing one SQLite file; multi-process deployments should use PostgreSQL. The analysis worker's own per-stage transaction boundaries (why a stage's facts are flushed but not committed until the stage checkpoint) are documented directly in `app/workers/analysis_worker.py`'s module docstring and were deliberately left unchanged — restructuring them risks the job-recovery guarantees (leases, retries, stale-worker takeover) that same docstring exists to protect, and WAL removes the actual reader-blocking symptom without needing to.

`AUTH_SECRET_KEY` falls back to a fixed insecure value when `APP_ENV` is `development` or `test`. Outside those environments the app **refuses to start** without an explicit secret of at least 32 characters:

Expand Down Expand Up @@ -104,7 +104,7 @@ Production/staging are unaffected: this check is a no-op outside `development`/`
| `GET /metrics` | Plain-text counters: request volume, status families, routes, cumulative duration, rate-limit counters. |
| `GET /docs` | OpenAPI / Swagger UI. |

Logs default to human-readable text; set `LOG_FORMAT=json` for structured logs in containers. Structured-log extras are redacted for keys containing `api_key`, `apikey`, `authorization`, `password`, `secret`, or `token`. Every response carries `X-Request-ID`; an inbound `X-Request-ID` is preserved.
Logs default to human-readable text; set `LOG_FORMAT=json` for structured logs. Structured-log extras are redacted for keys containing `api_key`, `apikey`, `authorization`, `password`, `secret`, or `token`. Every response carries `X-Request-ID`; an inbound `X-Request-ID` is preserved.

## Authentication

Expand All @@ -114,15 +114,6 @@ Every non-public API route requires a valid Bearer token. Repository resolution
owner-scoped in the service layer across analysis and all product consumers, so
one account cannot query another account's repository or snapshots.

## Docker

```bash
cd ../..
docker compose up --build
```

Compose runs the API against PostgreSQL and Redis. It does not run the frontend.

## AI provider egress

AI provider traffic is centrally checked at configuration save time and again
Expand All @@ -135,9 +126,9 @@ and provide both an exact `AI_EGRESS_ALLOWED_BASE_URLS` entry and matching

The sender validates every DNS answer, pins the HTTP connection to a validated
IP while preserving the original Host/SNI name, ignores ambient proxy settings,
and rejects redirects. Compose keeps PostgreSQL and Redis on an internal data
network, but production still needs an independent firewall, egress proxy,
cloud egress rule, or mesh policy. See [AI provider egress policy](../../docs/security/AI_PROVIDER_EGRESS.md)
and rejects redirects. A shared or hosted environment still needs an independent
firewall, egress proxy, cloud egress rule, or mesh policy. See
[AI provider egress policy](../../docs/security/AI_PROVIDER_EGRESS.md)
for configuration, rollout, and migration details.

## First import
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Development/test dependencies for PARTHA backend.
# Extends the pinned runtime lockfile (requirements.txt) with the test
# toolchain so CI and local dev can run pytest. The runtime image installs
# only requirements.txt; pytest must never ship in the container (issue #185).
# only requirements.txt; pytest must never ship in runtime dependencies (issue #185).
-r requirements.txt
ast-serialize==0.7.0
iniconfig==2.3.0
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Pinned backend dependency lockfile for reproducible installs and Dependabot
# pip tracking. Abstract version ranges live in pyproject.toml; this file pins the
# concrete resolved set so CI, Docker, and Dependabot all agree.
# concrete resolved set so CI and Dependabot agree.
#
# Regenerate after changing pyproject.toml dependencies:
# python -m venv /tmp/lock && /tmp/lock/bin/pip install ./apps/backend
Expand Down
10 changes: 0 additions & 10 deletions apps/frontend/.dockerignore

This file was deleted.

14 changes: 0 additions & 14 deletions apps/frontend/Dockerfile

This file was deleted.

Loading
Loading