From a89686d059d09325e01958e46a39f93e222d13af Mon Sep 17 00:00:00 2001
From: Shaurya K Sharma
Date: Fri, 9 Oct 2026 00:08:21 +0100
Subject: [PATCH 1/2] docs: align setup and supported workflows with current
contracts (#551)
---
README.md | 27 ++++++++++++++-----
apps/backend/app/extraction/support_matrix.py | 4 +--
.../features/landing/components/StoryCard.tsx | 1 +
apps/frontend/src/features/landing/faq.ts | 6 ++---
.../src/components/landing/StoryCard.tsx | 1 +
apps/marketing/src/data/faq.ts | 6 ++---
apps/marketing/src/data/site.ts | 6 ++---
docs/CAPABILITIES.md | 2 +-
8 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/README.md b/README.md
index 7a3e75e8..5ec7db14 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
·
Contributing
·
- Discord
+ Support
@@ -21,7 +21,7 @@
-
+
**PARTHA turns one repository revision into a sealed, queryable intelligence model, and serves architecture, dependencies, engineering review, insights, documentation, and AI context from that one model.**
@@ -157,7 +157,7 @@ Supported structural facts retain evidence and provenance back to their reposito
| Tool | Version | Needed for |
| --- | --- | --- |
| Python | 3.12 or 3.13 | Backend |
-| Node.js | 22 | Frontend and workflow scripts |
+| Node.js | 22.22.2+ in the 22.x line | Frontend and workflow scripts |
| Git | recent | Checkout and public GitHub import |
Development uses SQLite, an in-memory rate limiter, and local filesystem storage. No container runtime or external database is required, and no `.env` file is needed.
@@ -168,15 +168,28 @@ cd PARTHA
# 1. Backend — http://localhost:8000 (OpenAPI at /docs, readiness at /ready)
cd apps/backend
-python3.13 -m venv .venv && source .venv/bin/activate
+python3.13 -m venv .venv
+source .venv/bin/activate
pip install -e .
-cd ../.. && npm run dev:backend
+cd ../..
+npm run dev:backend
# 2. Frontend — http://localhost:5173 (second terminal)
npm ci --prefix apps/frontend
npm run dev:frontend
```
+On Windows PowerShell, use the same checkout and frontend commands, with this backend setup in the first terminal:
+
+```powershell
+cd apps/backend
+py -3.13 -m venv .venv
+.\.venv\Scripts\python.exe -m pip install -e .
+.\.venv\Scripts\python.exe -m uvicorn app.main:app --reload --port 8000
+```
+
+Python 3.12 is also supported (`python3.12` or `py -3.12`). The Node minimum reflects the locked test tooling, including jsdom.
+
Open `http://localhost:5173`, register a local account, add a repository, and start analysis.
### Or run it with Docker
@@ -201,7 +214,7 @@ The [development guide](docs/DEVELOPMENT.md) covers the full test / lint / build
- **Whole-repository analysis.** Every analysis re-reads the whole repository. There is no incremental re-analysis.
- **No cross-revision comparison.** Lineage preserves revision history; it does not diff two snapshots, detect renames or moves, or compute a historical blast radius. Change-impact analysis is single-snapshot structural traversal only.
- **Optional AI can be external.** Depending on configuration, AI calls a configured provider; only local providers keep everything on the host. See the [egress policy](docs/security/AI_PROVIDER_EGRESS.md).
-- **In-process worker.** One daemon worker thread inside the API process handles one analysis job at a time; there is no separate worker service or job queue.
+- **In-process worker.** One daemon worker thread inside the API process handles one analysis job at a time; a durable DB-backed `analysis_jobs` queue stores work, leases, retries and cancellation. There is no separate worker service.
Non-auth product routes require authentication, repository access is owner-scoped, provider keys are Fernet-encrypted at rest, and AI egress is validated against a deployment-owned allowlist with DNS pinning — meaningful controls, but not a claim of production hardening. Registration does not verify email ownership, and in the default `development` environment any address may register. See [SECURITY.md](SECURITY.md) and [`docs/CAPABILITIES.md`](docs/CAPABILITIES.md) for the details.
@@ -221,7 +234,7 @@ Issues and pull requests are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.
## Community
-- [Discord](https://discord.gg/qvk9DcxDA) — questions, progress, and discussion with maintainers
+- [GitHub support issues](https://github.com/Second-Origin/PARTHA/issues) — questions, progress, and discussion with maintainers
- [Issues](https://github.com/Second-Origin/PARTHA/issues) — bugs and feature requests
## Releases
diff --git a/apps/backend/app/extraction/support_matrix.py b/apps/backend/app/extraction/support_matrix.py
index a5172f3f..3a58fc42 100644
--- a/apps/backend/app/extraction/support_matrix.py
+++ b/apps/backend/app/extraction/support_matrix.py
@@ -747,7 +747,7 @@ def _product_capability(
"repository-lineage",
SupportStatus.PARTIAL,
"Durable lineage grouping repeated imports of the same repository (RFC-0002).",
- "The `repository_lineages` table, owner-scoped grouping, and duplicate-revision detection run on every import; `GET /repositories/{id}/lineage` and the repository detail page expose the ordered history. Refresh and cross-revision comparison on top of a lineage are not built.",
+ "The `repository_lineages` table, owner-scoped grouping, and duplicate-revision detection run on every import; `GET /repositories/{id}/lineage` and the repository detail page expose the ordered history. GitHub branch re-analysis refreshes the remote branch head and retains a new revision in the lineage when it changes. Whole-repository analysis is rerun; cross-revision comparison is not built.",
),
_product_capability(
"service-interactions",
@@ -873,7 +873,7 @@ def _code_list(items: tuple[str, ...]) -> str:
"repository-lineage",
"Repository lineage",
PublicStatus.IMPLEMENTED_WITH_DISCLOSED_LIMITS,
- "Repeated imports of the same repository and branch are grouped into a durable, owner-scoped lineage with duplicate-revision detection (RFC-0002). `GET /repositories/{id}/lineage` returns the ordered history and the repository detail page renders it. Refresh and cross-revision comparison on top of a lineage are not built.",
+ "Repeated imports of the same repository and branch are grouped into a durable, owner-scoped lineage with duplicate-revision detection (RFC-0002). `GET /repositories/{id}/lineage` returns the ordered history and the repository detail page renders it. GitHub branch re-analysis refreshes the remote branch head and retains a new revision in the lineage when it changes. Whole-repository analysis is rerun; cross-revision comparison is not built.",
("product.repository-lineage",),
),
PublicCapability(
diff --git a/apps/frontend/src/features/landing/components/StoryCard.tsx b/apps/frontend/src/features/landing/components/StoryCard.tsx
index 6ee83b55..54028159 100644
--- a/apps/frontend/src/features/landing/components/StoryCard.tsx
+++ b/apps/frontend/src/features/landing/components/StoryCard.tsx
@@ -316,6 +316,7 @@ export function StoryCard({ className }: { className?: string }) {
onFocusCapture={hold}
onBlurCapture={release}
>
+ Illustrative architecture; framework labels are not a semantic support claim.
{VARIANTS.map((variant, i) => (
diff --git a/apps/frontend/src/features/landing/faq.ts b/apps/frontend/src/features/landing/faq.ts
index 2c515c42..4ea0a6c9 100644
--- a/apps/frontend/src/features/landing/faq.ts
+++ b/apps/frontend/src/features/landing/faq.ts
@@ -23,8 +23,8 @@ export const faqAnswers = [
'No. PARTHA is a deterministic extractor. There is no model that hallucinates and no temperature parameter. The same repo at the same revision produces a byte-identical ri.v1 artifact.',
'They\u2019re flagged, not guessed. Each unresolved call site has a confidence field and provenance. You see exactly what PARTHA could and could not statically resolve.',
// Not yet exported from the design; PARTHA wording, pending the real copy.
- 'Language support is determined by the extractors available for the selected repository. The sealed snapshot records exactly what was assessed.',
- 'PARTHA analyses a repository at a specific revision and retains a reproducible model for the workspace.',
- 'Connect a repository, select a revision, then use the generated evidence and exports in the engineering workflow that suits your team.',
+ 'Python and TypeScript/JavaScript have the strongest semantic extraction. Other languages contribute file inventory; supported manifests and lockfiles contribute dependency declarations. The snapshot reports assessment limits.',
+ 'Run PARTHA locally or self-host it in a trusted environment. The public website is a scripted demonstration; repository analysis runs on your installation.',
+ 'CI integration is manual: run your installation and use authenticated APIs or exported evidence in your own workflow. PARTHA does not install a hosted CI app or provide automated pull-request review.',
'ri.v1 is PARTHA\u2019s sealed repository-intelligence snapshot format. It records the exact revision, extracted facts, and available evidence.',
] as const;
diff --git a/apps/marketing/src/components/landing/StoryCard.tsx b/apps/marketing/src/components/landing/StoryCard.tsx
index f0c96846..d950cd2b 100644
--- a/apps/marketing/src/components/landing/StoryCard.tsx
+++ b/apps/marketing/src/components/landing/StoryCard.tsx
@@ -316,6 +316,7 @@ export function StoryCard({ className }: { className?: string }) {
onFocusCapture={hold}
onBlurCapture={release}
>
+ Illustrative architecture; framework labels are not a semantic support claim.
{VARIANTS.map((variant, i) => (
diff --git a/apps/marketing/src/data/faq.ts b/apps/marketing/src/data/faq.ts
index 2c515c42..4ea0a6c9 100644
--- a/apps/marketing/src/data/faq.ts
+++ b/apps/marketing/src/data/faq.ts
@@ -23,8 +23,8 @@ export const faqAnswers = [
'No. PARTHA is a deterministic extractor. There is no model that hallucinates and no temperature parameter. The same repo at the same revision produces a byte-identical ri.v1 artifact.',
'They\u2019re flagged, not guessed. Each unresolved call site has a confidence field and provenance. You see exactly what PARTHA could and could not statically resolve.',
// Not yet exported from the design; PARTHA wording, pending the real copy.
- 'Language support is determined by the extractors available for the selected repository. The sealed snapshot records exactly what was assessed.',
- 'PARTHA analyses a repository at a specific revision and retains a reproducible model for the workspace.',
- 'Connect a repository, select a revision, then use the generated evidence and exports in the engineering workflow that suits your team.',
+ 'Python and TypeScript/JavaScript have the strongest semantic extraction. Other languages contribute file inventory; supported manifests and lockfiles contribute dependency declarations. The snapshot reports assessment limits.',
+ 'Run PARTHA locally or self-host it in a trusted environment. The public website is a scripted demonstration; repository analysis runs on your installation.',
+ 'CI integration is manual: run your installation and use authenticated APIs or exported evidence in your own workflow. PARTHA does not install a hosted CI app or provide automated pull-request review.',
'ri.v1 is PARTHA\u2019s sealed repository-intelligence snapshot format. It records the exact revision, extracted facts, and available evidence.',
] as const;
diff --git a/apps/marketing/src/data/site.ts b/apps/marketing/src/data/site.ts
index ba46e6f5..5d8d4a07 100644
--- a/apps/marketing/src/data/site.ts
+++ b/apps/marketing/src/data/site.ts
@@ -5,7 +5,7 @@
export const GITHUB_URL = 'https://github.com/Second-Origin/PARTHA';
const REPO_BLOB = `${GITHUB_URL}/blob/dev`;
-export const DISCORD_URL = 'https://discord.gg/qvk9DcxDA';
+export const SUPPORT_URL = `${GITHUB_URL}/issues`;
export const LINKEDIN_URL = 'https://www.linkedin.com/in/parthrohit';
export type FooterLink = {
@@ -43,7 +43,7 @@ export const FOOTER_COLUMNS: { heading: string; links: FooterLink[] }[] = [
links: [
{ label: 'About', href: `${REPO_BLOB}/README.md`, external: true },
{ label: 'Security', href: `${REPO_BLOB}/SECURITY.md`, external: true },
- { label: 'Contact', href: DISCORD_URL, external: true },
+ { label: 'Contact', href: SUPPORT_URL, external: true },
{ label: 'Legal', href: `${REPO_BLOB}/LICENSE`, external: true },
],
},
@@ -51,7 +51,7 @@ export const FOOTER_COLUMNS: { heading: string; links: FooterLink[] }[] = [
heading: 'Connect',
links: [
{ label: 'LinkedIn', href: LINKEDIN_URL, external: true },
- { label: 'X', href: DISCORD_URL, external: true },
+ { label: 'Support', href: SUPPORT_URL, external: true },
{ label: 'GitHub', href: GITHUB_URL, external: true },
],
},
diff --git a/docs/CAPABILITIES.md b/docs/CAPABILITIES.md
index 3d2341b7..b7addd18 100644
--- a/docs/CAPABILITIES.md
+++ b/docs/CAPABILITIES.md
@@ -34,7 +34,7 @@ release; `dev` carries active development.
| Authentication and owner isolation | **Implemented** | Email/password, Argon2, short-lived access tokens, rotating refresh tokens with reuse detection. Google and GitHub OAuth sign-in and account linking are implemented but inert until provider credentials are configured, and never create an account. Registration is gated by an admin-managed email allowlist in every environment except `development` (the default when running from source), where any address may register, and except the first account on an empty instance, which becomes its owner. Registration does not verify email ownership, so an approved address can be claimed by whoever registers it first; there is no admin role or in-app approval. Protected resources are owner-scoped; non-owner access returns 404. |
| Analysis lifecycle | **Implemented** | Database-backed, cancellable job with progress, bounded retry, lease renewal, and stale-worker recovery. |
| Repository Intelligence | **Implemented with disclosed limits** | Immutable, revision-addressed `ri.v1` snapshots with normalized facts, evidence, query APIs, and a total canonical graph hash. Semantic extraction is strongest for supported Python and TypeScript/JavaScript constructs. |
-| Repository lineage | **Implemented with disclosed limits** | Repeated imports of the same repository and branch are grouped into a durable, owner-scoped lineage with duplicate-revision detection (RFC-0002). `GET /repositories/{id}/lineage` returns the ordered history and the repository detail page renders it. Refresh and cross-revision comparison on top of a lineage are not built. |
+| Repository lineage | **Implemented with disclosed limits** | Repeated imports of the same repository and branch are grouped into a durable, owner-scoped lineage with duplicate-revision detection (RFC-0002). `GET /repositories/{id}/lineage` returns the ordered history and the repository detail page renders it. GitHub branch re-analysis refreshes the remote branch head and retains a new revision in the lineage when it changes. Whole-repository analysis is rerun; cross-revision comparison is not built. |
| Architecture and authentication explanation | **Implemented with disclosed limits** | Interactive snapshot-backed graph. Module/layer classification is heuristic. The cited authentication subgraph covers supported Python/FastAPI patterns only. |
| Dependency Graph | **Implemented with disclosed limits** | Direct declarations from `package.json`, `pyproject.toml`, and `requirements.txt` plus resolved pins from `package-lock.json` and `poetry.lock`, merged onto one dependency identity with repeated workspace declarations and exact spans. A lockfile pin is recorded as a resolution, never as a direct dependency edge, so transitive resolution is still not claimed. |
| Service-interaction discovery | **Implemented with disclosed limits** | Outbound HTTP call sites on `requests`, `httpx`, `fetch`, and `axios` resolve to a service node identified by its absolute origin, with the literal method and path on the call's own observation. A computed, relative, or shadowed destination is a diagnostic, never an edge. |
From b9758c5522e2fa85625f208d707ec2ffc42c9a5c Mon Sep 17 00:00:00 2001
From: Shaurya K Sharma
Date: Fri, 9 Oct 2026 00:19:45 +0100
Subject: [PATCH 2/2] docs(auth): remove implied first-account administrator
privilege
---
README.md | 2 +-
docs/DEVELOPMENT.md | 4 ++--
docs/architecture/SYSTEM_OVERVIEW.md | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 5ec7db14..249f87d7 100644
--- a/README.md
+++ b/README.md
@@ -202,7 +202,7 @@ cd PARTHA
docker compose up --build
```
-Open `http://localhost:8000`. The first account you register becomes the owner of the instance; approve anyone else with `docker compose exec partha python scripts/approve_email.py --email them@example.com`. Data and generated secrets live in the `partha-data` volume, and the port is bound to `127.0.0.1` only. See [`docker-compose.yml`](docker-compose.yml) for the details.
+Open `http://localhost:8000`. Initial setup permits the first account without prior approval; this grants no administrator role. Approve later emails with `docker compose exec partha python scripts/approve_email.py --email them@example.com`. Data and generated secrets live in the `partha-data` volume, and the port is bound to `127.0.0.1` only. See [`docker-compose.yml`](docker-compose.yml) for the details.
The [development guide](docs/DEVELOPMENT.md) covers the full test / lint / build / benchmark / Docker / E2E commands and the local database and API-contract failures you are most likely to hit. Review the [AI provider egress policy](docs/security/AI_PROVIDER_EGRESS.md) before configuring any custom or local provider endpoint.
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
index b15aac09..501a015d 100644
--- a/docs/DEVELOPMENT.md
+++ b/docs/DEVELOPMENT.md
@@ -22,7 +22,7 @@ processes, described below. To *use* PARTHA rather than work on it, the root
[`Dockerfile`](../Dockerfile) (the built frontend served by the same FastAPI
process) with SQLite and storage in a volume: `docker compose up --build`, then
`http://localhost:8000`. It runs with `APP_ENV=production`, so the first
-account registered becomes the owner and later ones need
+account registered is permitted without prior approval, receives no administrator role, and later ones need
`docker compose exec partha python scripts/approve_email.py --email ...`.
## 1. Clone and start the backend
@@ -61,7 +61,7 @@ npm run dev:frontend
Open `http://localhost:5173`. There is no seeded account or sample
repository (and no pre-approved email address) — register a new local account through the UI
(in the default `APP_ENV=development` any address is accepted; anywhere else the first account
-on an empty instance becomes its owner and every later one must be added with
+on an empty instance is permitted without prior approval and every later email must be added with
`apps/backend/scripts/approve_email.py`), then add a
repository (upload an archive or import a public GitHub repository over
HTTPS) and start analysis.
diff --git a/docs/architecture/SYSTEM_OVERVIEW.md b/docs/architecture/SYSTEM_OVERVIEW.md
index a702c07f..67f2113c 100644
--- a/docs/architecture/SYSTEM_OVERVIEW.md
+++ b/docs/architecture/SYSTEM_OVERVIEW.md
@@ -154,7 +154,7 @@ contract. Running analysis in a separate process is not implemented today.
| --- | --- | --- |
| Relational DB | `users`, `refresh_tokens`, `repositories`, `repository_lineages`, `analysis_jobs`, `ai_provider_configs`, `ai_conversation_messages`, the account-access tables (`approved_emails`, `invite_tokens`, `oauth_identities`, `oauth_flow_states`, `oauth_pending_links`, `account_deletion_audits`), `waitlist_entries`, and the normalized `ri_*` snapshot tables | SQLite by default for local development; PostgreSQL is supported through `DATABASE_URL`. Analysis jobs and their worker leases are durable database state. |
| `account_deletion_audits` | A minimal, **non-PII** record that an account deletion happened: the deleted user id, status, timestamps, and any failure reason. | Retained after the user row and its data are removed, so a deletion remains auditable without preserving the account. |
-| `approved_emails` | The registration gate: which email addresses may create an account. | Registration is allowlisted in every environment **except `development`** (the default `APP_ENV` when running from source), where any address is auto-approved so local use stays frictionless. Outside development the one exception is a genuinely empty instance: the first account registered is auto-approved and becomes that instance's owner. No address is pre-approved by a migration (the seed row `0016` once inserted was removed in #465). Registration does **not verify email ownership**, so an approved address can be claimed by whoever registers it first, and there is no admin role: rows are added with `scripts/approve_email.py`. Account requests accept private-network domains such as `corp.local`. `invite_tokens` is the superseded invite-code table, retained for historical continuity and no longer a gate. |
+| `approved_emails` | The registration gate: which email addresses may create an account. | Registration is allowlisted in every environment **except `development`** (the default `APP_ENV` when running from source), where any address is auto-approved so local use stays frictionless. Outside development the one exception is a genuinely empty instance: the first account registered is auto-approved; this grants no administrator role or access to other users' repositories. No address is pre-approved by a migration (the seed row `0016` once inserted was removed in #465). Registration does **not verify email ownership**, so an approved address can be claimed by whoever registers it first, and there is no admin role: rows are added with `scripts/approve_email.py`. Account requests accept private-network domains such as `corp.local`. `invite_tokens` is the superseded invite-code table, retained for historical continuity and no longer a gate. |
| `oauth_identities`, `oauth_flow_states`, `oauth_pending_links` | Linked Google/GitHub provider identities, in-flight authorization state, and pending link confirmations. | OAuth is inert unless provider credentials are configured. It never creates an account — an unknown identity is returned to the invite-gated registration flow. |
| `repository_lineages` | Owner-scoped grouping of repeated imports of the same repository and branch, with 1-based never-reused sequence allocation (RFC-0002). | Uploads and unresolved GitHub imports stay unlineaged: their lineage fields are null and no synthetic lineage is created. |
| `waitlist_entries` | Landing-page waitlist signups: normalized email and optional name. | Written by `POST /waitlist`, the one **public write route** in the API. Deliberately unauthenticated; guarded by the `auth` rate-limit class and an existence-concealing response. |