FossilRepo
Prepare for open source: docs, cleanup, production config - README rewritten as project landing page with features, architecture, quickstart, and configuration reference - CONTRIBUTING.md updated with full dev setup, code style, testing, and PR process specific to fossilrepo - SECURITY.md updated with actual security model (auth, RBAC, encryption) - CHANGELOG.md added with 0.1.0 initial release notes - PR template added - .env.production.example with all production variables documented - Removed dead code: _old_CLAUDE.md, _old_bootstrap.md, fossil-platform/
Commit
b86dcec4f1aadbc8a42a5cdd68c51c689e67c48e49e0a7fdd45634edabcae4fb
Parent
d7c30a9100bcf69…
10 files changed
+40
+17
-22
+49
+130
-24
+145
-51
+36
-11
-57
-84
-29
-65
+40
| --- a/.env.production.example | ||
| +++ b/.env.production.example | ||
| @@ -0,0 +1,40 @@ | ||
| 1 | +# Fossilrepo — Production Environment Variables | |
| 2 | +# | |
| 3 | +# Copy to .env and fill in your values. | |
| 4 | +# NEVER commit the actual .env file. | |
| 5 | + | |
| 6 | +# --- Django --- | |
| 7 | +DJANGO_SECRET_KEY= # REQUIRED — generate with: python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" | |
| 8 | +DJANGO_DEBUG=false | |
| 9 | +DJANGO_ALLOWED_HOSTS=fossilrepo.example.com | |
| 10 | + | |
| 11 | +# --- Database --- | |
| 12 | +POSTGRES_DB=fossilrepo | |
| 13 | +POSTGRES_USER=fossilrepo | |
| 14 | +POSTGRES_PASSWORD= # REQUIRED — use a strong password | |
| 15 | +POSTGRES_HOST=localhost | |
| 16 | +POSTGRES_PORT=5432 | |
| 17 | + | |
| 18 | +# --- Redis --- | |
| 19 | +REDIS_URL=redis://localhost:6379/1 | |
| 20 | +CELERY_BROKER=redis://localhost:6379/0 | |
| 21 | + | |
| 22 | +# --- Email (production: SES or SMTP) --- | |
| 23 | +DJANGO_EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend | |
| 24 | +EMAIL_HOST=email-smtp.us-east-1.amazonaws.com | |
| 25 | +EMAIL_PORT=587 | |
| 26 | +[email protected] | |
| 27 | + | |
| 28 | +# --- S3 / Object Storage (optional — for file attachments and snapshots) --- | |
| 29 | +USE_S3=false | |
| 30 | +AWS_ACCESS_KEY_ID= | |
| 31 | +AWS_SECRET_ACCESS_KEY= | |
| 32 | +AWS_STORAGE_BUCKET_NAME=fossilrepo | |
| 33 | +AWS_S3_ENDPOINT_URL= # Leave empty for AWS S3, set for MinIO/R2/etc. | |
| 34 | + | |
| 35 | +# --- CORS / CSRF --- | |
| 36 | +CORS_ALLOWED_ORIGINS=https://fossilrepo.example.com | |
| 37 | +CSRF_TRUSTED_ORIGINS=https://fossilrepo.example.com | |
| 38 | + | |
| 39 | +# --- Sentry (optional — error tracking) --- | |
| 40 | +SENTRY_DSN= |
| --- a/.env.production.example | |
| +++ b/.env.production.example | |
| @@ -0,0 +1,40 @@ | |
| --- a/.env.production.example | |
| +++ b/.env.production.example | |
| @@ -0,0 +1,40 @@ | |
| 1 | # Fossilrepo — Production Environment Variables |
| 2 | # |
| 3 | # Copy to .env and fill in your values. |
| 4 | # NEVER commit the actual .env file. |
| 5 | |
| 6 | # --- Django --- |
| 7 | DJANGO_SECRET_KEY= # REQUIRED — generate with: python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" |
| 8 | DJANGO_DEBUG=false |
| 9 | DJANGO_ALLOWED_HOSTS=fossilrepo.example.com |
| 10 | |
| 11 | # --- Database --- |
| 12 | POSTGRES_DB=fossilrepo |
| 13 | POSTGRES_USER=fossilrepo |
| 14 | POSTGRES_PASSWORD= # REQUIRED — use a strong password |
| 15 | POSTGRES_HOST=localhost |
| 16 | POSTGRES_PORT=5432 |
| 17 | |
| 18 | # --- Redis --- |
| 19 | REDIS_URL=redis://localhost:6379/1 |
| 20 | CELERY_BROKER=redis://localhost:6379/0 |
| 21 | |
| 22 | # --- Email (production: SES or SMTP) --- |
| 23 | DJANGO_EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend |
| 24 | EMAIL_HOST=email-smtp.us-east-1.amazonaws.com |
| 25 | EMAIL_PORT=587 |
| 26 | [email protected] |
| 27 | |
| 28 | # --- S3 / Object Storage (optional — for file attachments and snapshots) --- |
| 29 | USE_S3=false |
| 30 | AWS_ACCESS_KEY_ID= |
| 31 | AWS_SECRET_ACCESS_KEY= |
| 32 | AWS_STORAGE_BUCKET_NAME=fossilrepo |
| 33 | AWS_S3_ENDPOINT_URL= # Leave empty for AWS S3, set for MinIO/R2/etc. |
| 34 | |
| 35 | # --- CORS / CSRF --- |
| 36 | CORS_ALLOWED_ORIGINS=https://fossilrepo.example.com |
| 37 | CSRF_TRUSTED_ORIGINS=https://fossilrepo.example.com |
| 38 | |
| 39 | # --- Sentry (optional — error tracking) --- |
| 40 | SENTRY_DSN= |
+17
-22
| --- .github/pull_request_template.md | ||
| +++ .github/pull_request_template.md | ||
| @@ -1,22 +1,17 @@ | ||
| 1 | -## What does this PR do? | |
| 2 | - | |
| 3 | -<!-- Brief description of the change --> | |
| 4 | - | |
| 5 | -## Type of change | |
| 6 | - | |
| 7 | -- [ ] Bug fix | |
| 8 | -- [ ] New feature | |
| 9 | -- [ ] Refactor / chore | |
| 10 | -- [ ] Documentation | |
| 11 | - | |
| 12 | -## Checklist | |
| 13 | - | |
| 14 | -- [ ] Lint passes | |
| 15 | -- [ ] Tests pass | |
| 16 | -- [ ] Migrations created for any model/schema changes | |
| 17 | -- [ ] Tests added or updated | |
| 18 | -- [ ] `bootstrap.md` updated if conventions changed | |
| 19 | - | |
| 20 | -## Related issues | |
| 21 | - | |
| 22 | -<!-- Closes #123 --> | |
| 1 | +## Summary | |
| 2 | + | |
| 3 | +<!-- What changed and why? Keep it brief. --> | |
| 4 | + | |
| 5 | +## Changes | |
| 6 | + | |
| 7 | +- | |
| 8 | + | |
| 9 | +## Test Plan | |
| 10 | + | |
| 11 | +- [ ] Tests added/updated | |
| 12 | +- [ ] Lint passes (`ruff check . && ruff format --check .`) | |
| 13 | +- [ ] Tested locally | |
| 14 | + | |
| 15 | +## Related Issues | |
| 16 | + | |
| 17 | +<!-- Link issues: Closes #123, Fixes #456 --> | |
| 23 | 18 | |
| 24 | 19 | ADDED CHANGELOG.md |
| --- .github/pull_request_template.md | |
| +++ .github/pull_request_template.md | |
| @@ -1,22 +1,17 @@ | |
| 1 | ## What does this PR do? |
| 2 | |
| 3 | <!-- Brief description of the change --> |
| 4 | |
| 5 | ## Type of change |
| 6 | |
| 7 | - [ ] Bug fix |
| 8 | - [ ] New feature |
| 9 | - [ ] Refactor / chore |
| 10 | - [ ] Documentation |
| 11 | |
| 12 | ## Checklist |
| 13 | |
| 14 | - [ ] Lint passes |
| 15 | - [ ] Tests pass |
| 16 | - [ ] Migrations created for any model/schema changes |
| 17 | - [ ] Tests added or updated |
| 18 | - [ ] `bootstrap.md` updated if conventions changed |
| 19 | |
| 20 | ## Related issues |
| 21 | |
| 22 | <!-- Closes #123 --> |
| 23 | |
| 24 | DDED CHANGELOG.md |
| --- .github/pull_request_template.md | |
| +++ .github/pull_request_template.md | |
| @@ -1,22 +1,17 @@ | |
| 1 | ## Summary |
| 2 | |
| 3 | <!-- What changed and why? Keep it brief. --> |
| 4 | |
| 5 | ## Changes |
| 6 | |
| 7 | - |
| 8 | |
| 9 | ## Test Plan |
| 10 | |
| 11 | - [ ] Tests added/updated |
| 12 | - [ ] Lint passes (`ruff check . && ruff format --check .`) |
| 13 | - [ ] Tested locally |
| 14 | |
| 15 | ## Related Issues |
| 16 | |
| 17 | <!-- Link issues: Closes #123, Fixes #456 --> |
| 18 | |
| 19 | DDED CHANGELOG.md |
+49
| --- a/CHANGELOG.md | ||
| +++ b/CHANGELOG.md | ||
| @@ -0,0 +1,49 @@ | ||
| 1 | +# Changelog | |
| 2 | + | |
| 3 | +All notable changes to Fossilrepo are documented here. | |
| 4 | + | |
| 5 | +## [0.1.0] - 2026-04-07 | |
| 6 | + | |
| 7 | +Initial open source release. | |
| 8 | + | |
| 9 | +### Features | |
| 10 | + | |
| 11 | +- **Code browser** with directory navigation, syntax highlighting, line numbers, permalinks, blame with age coloring, file history, raw download | |
| 12 | +- **Timeline** with DAG graph (fork/merge connectors, color-coded branches, merge diamonds, leaf indicators), keyboard navigation, HTMX infinite scroll, RSS feed | |
| 13 | +- **Diffs** with unified and side-by-side views, syntax highlighting via highlight.js, line-level permalinks | |
| 14 | +- **Tickets** with full CRUD (create, edit, close/reopen, comment), filters, pagination, CSV export | |
| 15 | +- **Wiki** with Markdown + Fossil markup + Pikchr diagrams, create/edit, right-sidebar TOC | |
| 16 | +- **Forum** with threaded discussions, create threads, post replies (Django-backed + Fossil-native) | |
| 17 | +- **Releases** with versioned tags, markdown changelogs, file attachments, download counts, draft/prerelease support | |
| 18 | +- **Branches, tags, technotes** list views | |
| 19 | +- **Search** across checkins, tickets, and wiki | |
| 20 | +- **Contributor profiles** with activity views | |
| 21 | +- **Repository statistics** with Chart.js visualizations | |
| 22 | +- **Fossil Guide** serving bundled Fossil documentation | |
| 23 | + | |
| 24 | +### Sync & Integration | |
| 25 | + | |
| 26 | +- **Upstream sync** — pull from remote Fossil repositories | |
| 27 | +- **HTTP sync** — clone/push/pull proxied through Django via `fossil http` CGI mode | |
| 28 | +- **SSH sync** — sshd in container with restricted `fossil-shell` forced command | |
| 29 | +- **Git mirror** — push to GitHub/GitLab via OAuth or SSH key auth | |
| 30 | +- **Webhooks** — outbound HTTP webhooks with HMAC-SHA256, retry, delivery logs | |
| 31 | + | |
| 32 | +### Organization & Access | |
| 33 | + | |
| 34 | +- **Organization** settings with member and team management | |
| 35 | +- **User CRUD** — create, edit, deactivate, change password | |
| 36 | +- **Team management** — create teams, assign members | |
| 37 | +- **Project-level RBAC** — read/write/admin roles via team assignment | |
| 38 | +- **Project visibility** — public, internal, private | |
| 39 | +- **User SSH keys** — upload/manage public keys for SSH access | |
| 40 | + | |
| 41 | +### Infrastructure | |
| 42 | + | |
| 43 | +- **Omnibus Docker** — multi-stage build with Fossil 2.24 compiled from source | |
| 44 | +- **Caddy** config for SSL and subdomain routing | |
| 45 | +- **Litestream** config for SQLite-to-S3 replication | |
| 46 | +- **Celery** tasks for metadata sync, upstream checks, webhook dispatch, notifications | |
| 47 | +- **Encrypted storage** — Fernet/AES-128-CBC for SSH keys and OAuth tokens at rest | |
| 48 | +- **Dark/light theme** with system preference detection | |
| 49 | +- **Keyboard shortcuts** (j/k/Enter navigation, / for search, ? for help) |
| --- a/CHANGELOG.md | |
| +++ b/CHANGELOG.md | |
| @@ -0,0 +1,49 @@ | |
| --- a/CHANGELOG.md | |
| +++ b/CHANGELOG.md | |
| @@ -0,0 +1,49 @@ | |
| 1 | # Changelog |
| 2 | |
| 3 | All notable changes to Fossilrepo are documented here. |
| 4 | |
| 5 | ## [0.1.0] - 2026-04-07 |
| 6 | |
| 7 | Initial open source release. |
| 8 | |
| 9 | ### Features |
| 10 | |
| 11 | - **Code browser** with directory navigation, syntax highlighting, line numbers, permalinks, blame with age coloring, file history, raw download |
| 12 | - **Timeline** with DAG graph (fork/merge connectors, color-coded branches, merge diamonds, leaf indicators), keyboard navigation, HTMX infinite scroll, RSS feed |
| 13 | - **Diffs** with unified and side-by-side views, syntax highlighting via highlight.js, line-level permalinks |
| 14 | - **Tickets** with full CRUD (create, edit, close/reopen, comment), filters, pagination, CSV export |
| 15 | - **Wiki** with Markdown + Fossil markup + Pikchr diagrams, create/edit, right-sidebar TOC |
| 16 | - **Forum** with threaded discussions, create threads, post replies (Django-backed + Fossil-native) |
| 17 | - **Releases** with versioned tags, markdown changelogs, file attachments, download counts, draft/prerelease support |
| 18 | - **Branches, tags, technotes** list views |
| 19 | - **Search** across checkins, tickets, and wiki |
| 20 | - **Contributor profiles** with activity views |
| 21 | - **Repository statistics** with Chart.js visualizations |
| 22 | - **Fossil Guide** serving bundled Fossil documentation |
| 23 | |
| 24 | ### Sync & Integration |
| 25 | |
| 26 | - **Upstream sync** — pull from remote Fossil repositories |
| 27 | - **HTTP sync** — clone/push/pull proxied through Django via `fossil http` CGI mode |
| 28 | - **SSH sync** — sshd in container with restricted `fossil-shell` forced command |
| 29 | - **Git mirror** — push to GitHub/GitLab via OAuth or SSH key auth |
| 30 | - **Webhooks** — outbound HTTP webhooks with HMAC-SHA256, retry, delivery logs |
| 31 | |
| 32 | ### Organization & Access |
| 33 | |
| 34 | - **Organization** settings with member and team management |
| 35 | - **User CRUD** — create, edit, deactivate, change password |
| 36 | - **Team management** — create teams, assign members |
| 37 | - **Project-level RBAC** — read/write/admin roles via team assignment |
| 38 | - **Project visibility** — public, internal, private |
| 39 | - **User SSH keys** — upload/manage public keys for SSH access |
| 40 | |
| 41 | ### Infrastructure |
| 42 | |
| 43 | - **Omnibus Docker** — multi-stage build with Fossil 2.24 compiled from source |
| 44 | - **Caddy** config for SSL and subdomain routing |
| 45 | - **Litestream** config for SQLite-to-S3 replication |
| 46 | - **Celery** tasks for metadata sync, upstream checks, webhook dispatch, notifications |
| 47 | - **Encrypted storage** — Fernet/AES-128-CBC for SSH keys and OAuth tokens at rest |
| 48 | - **Dark/light theme** with system preference detection |
| 49 | - **Keyboard shortcuts** (j/k/Enter navigation, / for search, ? for help) |
+130
-24
| --- CONTRIBUTING.md | ||
| +++ CONTRIBUTING.md | ||
| @@ -1,32 +1,138 @@ | ||
| 1 | -# Contributing to Fossilrepo django + htmx | |
| 2 | - | |
| 3 | -Thank you for your interest in contributing! | |
| 4 | - | |
| 5 | -## Getting Started | |
| 6 | - | |
| 7 | -1. Fork the repository | |
| 8 | -2. Clone your fork | |
| 9 | -3. Run `docker compose up -d` (or see README.md for stack-specific setup) | |
| 10 | -4. Create a feature branch from `main` | |
| 11 | - | |
| 12 | -## Development Process | |
| 13 | - | |
| 14 | -1. Pick an issue from the project board | |
| 15 | -2. Comment your plan on the issue before starting | |
| 16 | -3. Create a branch: `feature/issue-number-description` or `fix/issue-number-description` | |
| 17 | -4. Make your changes following `bootstrap.md` conventions | |
| 18 | -5. Write or update tests | |
| 19 | -6. Run lint and tests (see README.md for commands) | |
| 20 | -7. Submit a pull request | |
| 1 | +# Contributing to Fossilrepo | |
| 2 | + | |
| 3 | +Thanks for your interest in contributing. This document covers how to get set up, our coding standards, and the PR process. | |
| 4 | + | |
| 5 | +## Development Setup | |
| 6 | + | |
| 7 | +### Prerequisites | |
| 8 | + | |
| 9 | +- Python 3.12+ | |
| 10 | +- Docker and Docker Compose | |
| 11 | +- [uv](https://docs.astral.sh/uv/) (Python package manager) | |
| 12 | +- [Ruff](https://docs.astral.sh/ruff/) (linter/formatter) | |
| 13 | + | |
| 14 | +### Running Locally | |
| 15 | + | |
| 16 | +```bash | |
| 17 | +git clone https://github.com/ConflictHQ/fossilrepo.git | |
| 18 | +cd fossilrepo | |
| 19 | + | |
| 20 | +# Start infrastructure | |
| 21 | +docker compose up -d postgres redis mailpit | |
| 22 | + | |
| 23 | +# Install dependencies | |
| 24 | +uv sync --all-extras | |
| 25 | + | |
| 26 | +# Run migrations and seed data | |
| 27 | +DJANGO_DEBUG=true uv run python manage.py migrate | |
| 28 | +DJANGO_DEBUG=true uv run python manage.py seed | |
| 29 | + | |
| 30 | +# Start the dev server | |
| 31 | +DJANGO_DEBUG=true POSTGRES_HOST=localhost uv run python manage.py runserver | |
| 32 | +``` | |
| 33 | + | |
| 34 | +Or use Docker for everything: | |
| 35 | + | |
| 36 | +```bash | |
| 37 | +docker compose up -d --build | |
| 38 | +docker compose exec backend python manage.py migrate | |
| 39 | +docker compose exec backend python manage.py seed | |
| 40 | +``` | |
| 41 | + | |
| 42 | +### Default Users | |
| 43 | + | |
| 44 | +- `admin` / `admin` — superuser, full access | |
| 45 | +- `viewer` / `viewer` — read-only permissions | |
| 21 | 46 | |
| 22 | 47 | ## Code Style |
| 23 | 48 | |
| 24 | -See `bootstrap.md` for conventions. Run the linter before committing. | |
| 49 | +We use **Ruff** for linting and formatting. No debates, no custom configs. | |
| 50 | + | |
| 51 | +```bash | |
| 52 | +# Check | |
| 53 | +ruff check . | |
| 54 | +ruff format --check . | |
| 55 | + | |
| 56 | +# Fix | |
| 57 | +ruff check --fix . | |
| 58 | +ruff format . | |
| 59 | +``` | |
| 60 | + | |
| 61 | +Key conventions: | |
| 62 | + | |
| 63 | +- **Max line length:** 140 characters | |
| 64 | +- **Imports:** sorted by Ruff (isort rules) | |
| 65 | +- **Quote style:** double quotes | |
| 66 | +- **Target:** Python 3.12+ | |
| 67 | + | |
| 68 | +## Codebase Conventions | |
| 69 | + | |
| 70 | +Read [`bootstrap.md`](bootstrap.md) before writing code. It covers: | |
| 71 | + | |
| 72 | +- Model base classes (`Tracking`, `BaseCoreModel`) | |
| 73 | +- Soft deletes (never call `.delete()`) | |
| 74 | +- Permission system (`P` enum + project-level RBAC) | |
| 75 | +- View patterns (HTMX partials, auth checks) | |
| 76 | +- Template conventions (dark theme, Tailwind classes) | |
| 25 | 77 | |
| 26 | 78 | ## Testing |
| 27 | 79 | |
| 28 | -All new features need tests. All bug fixes need regression tests. Tests must use a real database — never mock. | |
| 80 | +Tests run against a real PostgreSQL database. No mocked databases. | |
| 81 | + | |
| 82 | +```bash | |
| 83 | +# Run all tests | |
| 84 | +DJANGO_DEBUG=true uv run pytest | |
| 85 | + | |
| 86 | +# Run specific test file | |
| 87 | +DJANGO_DEBUG=true uv run pytest tests/test_releases.py | |
| 88 | + | |
| 89 | +# Run with coverage | |
| 90 | +DJANGO_DEBUG=true uv run pytest --cov | |
| 91 | +``` | |
| 92 | + | |
| 93 | +Every PR should: | |
| 94 | + | |
| 95 | +- Include tests for new features (happy path + permission denied cases) | |
| 96 | +- Not decrease test coverage | |
| 97 | +- Pass all existing tests | |
| 98 | + | |
| 99 | +## Pull Request Process | |
| 100 | + | |
| 101 | +1. **Fork and branch** from `main`. Branch naming: `feature/short-description` or `fix/short-description`. | |
| 102 | + | |
| 103 | +2. **Write code** following the conventions in `bootstrap.md`. | |
| 104 | + | |
| 105 | +3. **Write tests.** Both allowed and denied permission cases. Assert against database state, not just status codes. | |
| 106 | + | |
| 107 | +4. **Lint and test locally.** CI will catch it anyway, but save yourself a round trip. | |
| 108 | + | |
| 109 | +5. **Open a PR** with a clear description: | |
| 110 | + - What changed and why | |
| 111 | + - How to test it | |
| 112 | + - Link to any related issues | |
| 113 | + | |
| 114 | +6. **Address review feedback** in new commits (don't amend/squash during review). | |
| 115 | + | |
| 116 | +7. **Merge** when CI is green and review is approved. | |
| 117 | + | |
| 118 | +## Reporting Issues | |
| 119 | + | |
| 120 | +Use [GitHub Issues](https://github.com/ConflictHQ/fossilrepo/issues). Include: | |
| 121 | + | |
| 122 | +- What you expected to happen | |
| 123 | +- What actually happened | |
| 124 | +- Steps to reproduce | |
| 125 | +- Browser/OS/version if relevant | |
| 126 | + | |
| 127 | +## Architecture Decisions | |
| 128 | + | |
| 129 | +Fossilrepo has some non-obvious design choices worth understanding: | |
| 130 | + | |
| 131 | +- **No Fossil HTTP server.** We read `.fossil` files directly via SQLite (`FossilReader`) and use `fossil http` in CGI mode for sync. No persistent Fossil process, stateless containers. | |
| 132 | +- **Django-backed forum posts** supplement Fossil's native forum because Fossil forum posts don't sync via clone/pull. | |
| 133 | +- **Encrypted fields** use Fernet (AES-128-CBC + HMAC) keyed from `SECRET_KEY` for SSH keys and OAuth tokens at rest. | |
| 134 | +- **Single org model.** Multi-org is possible but not implemented — fossilrepo targets self-hosted single-team deployments. | |
| 29 | 135 | |
| 30 | -## Questions? | |
| 136 | +## License | |
| 31 | 137 | |
| 32 | -Open an issue or start a discussion in this repository. | |
| 138 | +By contributing, you agree that your contributions will be licensed under the MIT License. | |
| 33 | 139 |
| --- CONTRIBUTING.md | |
| +++ CONTRIBUTING.md | |
| @@ -1,32 +1,138 @@ | |
| 1 | # Contributing to Fossilrepo django + htmx |
| 2 | |
| 3 | Thank you for your interest in contributing! |
| 4 | |
| 5 | ## Getting Started |
| 6 | |
| 7 | 1. Fork the repository |
| 8 | 2. Clone your fork |
| 9 | 3. Run `docker compose up -d` (or see README.md for stack-specific setup) |
| 10 | 4. Create a feature branch from `main` |
| 11 | |
| 12 | ## Development Process |
| 13 | |
| 14 | 1. Pick an issue from the project board |
| 15 | 2. Comment your plan on the issue before starting |
| 16 | 3. Create a branch: `feature/issue-number-description` or `fix/issue-number-description` |
| 17 | 4. Make your changes following `bootstrap.md` conventions |
| 18 | 5. Write or update tests |
| 19 | 6. Run lint and tests (see README.md for commands) |
| 20 | 7. Submit a pull request |
| 21 | |
| 22 | ## Code Style |
| 23 | |
| 24 | See `bootstrap.md` for conventions. Run the linter before committing. |
| 25 | |
| 26 | ## Testing |
| 27 | |
| 28 | All new features need tests. All bug fixes need regression tests. Tests must use a real database — never mock. |
| 29 | |
| 30 | ## Questions? |
| 31 | |
| 32 | Open an issue or start a discussion in this repository. |
| 33 |
| --- CONTRIBUTING.md | |
| +++ CONTRIBUTING.md | |
| @@ -1,32 +1,138 @@ | |
| 1 | # Contributing to Fossilrepo |
| 2 | |
| 3 | Thanks for your interest in contributing. This document covers how to get set up, our coding standards, and the PR process. |
| 4 | |
| 5 | ## Development Setup |
| 6 | |
| 7 | ### Prerequisites |
| 8 | |
| 9 | - Python 3.12+ |
| 10 | - Docker and Docker Compose |
| 11 | - [uv](https://docs.astral.sh/uv/) (Python package manager) |
| 12 | - [Ruff](https://docs.astral.sh/ruff/) (linter/formatter) |
| 13 | |
| 14 | ### Running Locally |
| 15 | |
| 16 | ```bash |
| 17 | git clone https://github.com/ConflictHQ/fossilrepo.git |
| 18 | cd fossilrepo |
| 19 | |
| 20 | # Start infrastructure |
| 21 | docker compose up -d postgres redis mailpit |
| 22 | |
| 23 | # Install dependencies |
| 24 | uv sync --all-extras |
| 25 | |
| 26 | # Run migrations and seed data |
| 27 | DJANGO_DEBUG=true uv run python manage.py migrate |
| 28 | DJANGO_DEBUG=true uv run python manage.py seed |
| 29 | |
| 30 | # Start the dev server |
| 31 | DJANGO_DEBUG=true POSTGRES_HOST=localhost uv run python manage.py runserver |
| 32 | ``` |
| 33 | |
| 34 | Or use Docker for everything: |
| 35 | |
| 36 | ```bash |
| 37 | docker compose up -d --build |
| 38 | docker compose exec backend python manage.py migrate |
| 39 | docker compose exec backend python manage.py seed |
| 40 | ``` |
| 41 | |
| 42 | ### Default Users |
| 43 | |
| 44 | - `admin` / `admin` — superuser, full access |
| 45 | - `viewer` / `viewer` — read-only permissions |
| 46 | |
| 47 | ## Code Style |
| 48 | |
| 49 | We use **Ruff** for linting and formatting. No debates, no custom configs. |
| 50 | |
| 51 | ```bash |
| 52 | # Check |
| 53 | ruff check . |
| 54 | ruff format --check . |
| 55 | |
| 56 | # Fix |
| 57 | ruff check --fix . |
| 58 | ruff format . |
| 59 | ``` |
| 60 | |
| 61 | Key conventions: |
| 62 | |
| 63 | - **Max line length:** 140 characters |
| 64 | - **Imports:** sorted by Ruff (isort rules) |
| 65 | - **Quote style:** double quotes |
| 66 | - **Target:** Python 3.12+ |
| 67 | |
| 68 | ## Codebase Conventions |
| 69 | |
| 70 | Read [`bootstrap.md`](bootstrap.md) before writing code. It covers: |
| 71 | |
| 72 | - Model base classes (`Tracking`, `BaseCoreModel`) |
| 73 | - Soft deletes (never call `.delete()`) |
| 74 | - Permission system (`P` enum + project-level RBAC) |
| 75 | - View patterns (HTMX partials, auth checks) |
| 76 | - Template conventions (dark theme, Tailwind classes) |
| 77 | |
| 78 | ## Testing |
| 79 | |
| 80 | Tests run against a real PostgreSQL database. No mocked databases. |
| 81 | |
| 82 | ```bash |
| 83 | # Run all tests |
| 84 | DJANGO_DEBUG=true uv run pytest |
| 85 | |
| 86 | # Run specific test file |
| 87 | DJANGO_DEBUG=true uv run pytest tests/test_releases.py |
| 88 | |
| 89 | # Run with coverage |
| 90 | DJANGO_DEBUG=true uv run pytest --cov |
| 91 | ``` |
| 92 | |
| 93 | Every PR should: |
| 94 | |
| 95 | - Include tests for new features (happy path + permission denied cases) |
| 96 | - Not decrease test coverage |
| 97 | - Pass all existing tests |
| 98 | |
| 99 | ## Pull Request Process |
| 100 | |
| 101 | 1. **Fork and branch** from `main`. Branch naming: `feature/short-description` or `fix/short-description`. |
| 102 | |
| 103 | 2. **Write code** following the conventions in `bootstrap.md`. |
| 104 | |
| 105 | 3. **Write tests.** Both allowed and denied permission cases. Assert against database state, not just status codes. |
| 106 | |
| 107 | 4. **Lint and test locally.** CI will catch it anyway, but save yourself a round trip. |
| 108 | |
| 109 | 5. **Open a PR** with a clear description: |
| 110 | - What changed and why |
| 111 | - How to test it |
| 112 | - Link to any related issues |
| 113 | |
| 114 | 6. **Address review feedback** in new commits (don't amend/squash during review). |
| 115 | |
| 116 | 7. **Merge** when CI is green and review is approved. |
| 117 | |
| 118 | ## Reporting Issues |
| 119 | |
| 120 | Use [GitHub Issues](https://github.com/ConflictHQ/fossilrepo/issues). Include: |
| 121 | |
| 122 | - What you expected to happen |
| 123 | - What actually happened |
| 124 | - Steps to reproduce |
| 125 | - Browser/OS/version if relevant |
| 126 | |
| 127 | ## Architecture Decisions |
| 128 | |
| 129 | Fossilrepo has some non-obvious design choices worth understanding: |
| 130 | |
| 131 | - **No Fossil HTTP server.** We read `.fossil` files directly via SQLite (`FossilReader`) and use `fossil http` in CGI mode for sync. No persistent Fossil process, stateless containers. |
| 132 | - **Django-backed forum posts** supplement Fossil's native forum because Fossil forum posts don't sync via clone/pull. |
| 133 | - **Encrypted fields** use Fernet (AES-128-CBC + HMAC) keyed from `SECRET_KEY` for SSH keys and OAuth tokens at rest. |
| 134 | - **Single org model.** Multi-org is possible but not implemented — fossilrepo targets self-hosted single-team deployments. |
| 135 | |
| 136 | ## License |
| 137 | |
| 138 | By contributing, you agree that your contributions will be licensed under the MIT License. |
| 139 |
+145
-51
| --- README.md | ||
| +++ README.md | ||
| @@ -1,95 +1,189 @@ | ||
| 1 | -# Fossilrepo Django + HTMX | |
| 1 | +# Fossilrepo | |
| 2 | + | |
| 3 | +**Self-hosted Fossil forge with a modern web interface.** | |
| 4 | + | |
| 5 | +Fossilrepo wraps [Fossil SCM](https://fossil-scm.org) with a Django + HTMX management layer, replacing Fossil's built-in web UI with a GitHub/GitLab-caliber experience while preserving everything that makes Fossil unique: single-file repos, built-in wiki, tickets, forum, and technotes. | |
| 6 | + | |
| 7 | +## Why Fossilrepo? | |
| 8 | + | |
| 9 | +Fossil is the most underrated version control system. Every repository is a single SQLite file containing your code, wiki, tickets, forum, and technotes. No external services, no complex setup. But its web UI hasn't changed since 1998. | |
| 10 | + | |
| 11 | +Fossilrepo fixes that. You get: | |
| 12 | + | |
| 13 | +- A modern dark/light UI built with Django, HTMX, Alpine.js, and Tailwind CSS | |
| 14 | +- GitHub-style code browser with line numbers, blame, history, and syntax highlighting | |
| 15 | +- Timeline with DAG graph showing fork/merge connectors and color-coded branches | |
| 16 | +- Full ticket CRUD with filters, comments, and CSV export | |
| 17 | +- Wiki with Markdown + Fossil markup + Pikchr diagram rendering | |
| 18 | +- Forum with threaded discussions | |
| 19 | +- Releases with file attachments and markdown changelogs | |
| 20 | +- Git mirror sync to GitHub/GitLab via OAuth | |
| 21 | +- Clone/push/pull over HTTP and SSH through Django's auth layer | |
| 22 | +- Webhook dispatch with HMAC signing and delivery logs | |
| 23 | +- Omnibus Docker image with Fossil compiled from source | |
| 2 | 24 | |
| 3 | -Server-rendered Django with HTMX for dynamic behavior and Alpine.js for lightweight client state. Tailwind CSS for styling. Choose this for content-heavy CRUD, admin-centric tools, and apps where server-rendered simplicity beats a full SPA. | |
| 25 | +All while Fossil remains the source of truth. Fossilrepo reads `.fossil` files directly via SQLite for speed, and uses the `fossil` CLI for writes to preserve artifact integrity. | |
| 4 | 26 | |
| 5 | 27 | ## Stack |
| 6 | 28 | |
| 7 | 29 | | Layer | Technology | |
| 8 | 30 | |-------|-----------| |
| 9 | 31 | | Backend | Django 5 (Python 3.12+) | |
| 10 | -| Frontend | HTMX 2.0 + Alpine.js 3 + Tailwind CSS | | |
| 11 | -| Database | PostgreSQL 16 | | |
| 32 | +| Frontend | HTMX 2.0 + Alpine.js 3 + Tailwind CSS (CDN) | | |
| 33 | +| Database | PostgreSQL 16 (app data) + SQLite (Fossil repos) | | |
| 12 | 34 | | Cache/Broker | Redis 7 | |
| 13 | -| Job Queue | Celery + Redis | | |
| 35 | +| Jobs | Celery + Redis | | |
| 14 | 36 | | Auth | Session-based (httpOnly cookies) | |
| 37 | +| SCM | Fossil 2.24 (compiled from source in Docker) | | |
| 15 | 38 | | Linter | Ruff | |
| 16 | -| Package Manager | uv | | |
| 17 | 39 | |
| 18 | 40 | ## Quick Start |
| 19 | 41 | |
| 20 | 42 | ```bash |
| 21 | -# Start the stack | |
| 43 | +git clone https://github.com/ConflictHQ/fossilrepo.git | |
| 44 | +cd fossilrepo | |
| 22 | 45 | docker compose up -d --build |
| 23 | 46 | |
| 24 | -# Run migrations and seed data | |
| 47 | +# Run migrations and seed sample data | |
| 25 | 48 | docker compose exec backend python manage.py migrate |
| 26 | 49 | docker compose exec backend python manage.py seed |
| 27 | 50 | |
| 28 | 51 | # Open the app |
| 29 | 52 | open http://localhost:8000 |
| 30 | 53 | ``` |
| 31 | 54 | |
| 32 | -**Default users:** | |
| 33 | -- `admin` / `admin` (superuser, full access) | |
| 34 | -- `viewer` / `viewer` (view-only permissions) | |
| 55 | +**Default users:** `admin` / `admin` (superuser) and `viewer` / `viewer` (read-only). | |
| 56 | + | |
| 57 | +## Features | |
| 58 | + | |
| 59 | +### Code Browser | |
| 60 | +- Directory navigation with breadcrumbs | |
| 61 | +- Syntax-highlighted source view with line numbers and permalinks | |
| 62 | +- Blame with age-based coloring (newest = brand red, oldest = gray) | |
| 63 | +- File history, raw download, rendered preview for Markdown/HTML | |
| 64 | + | |
| 65 | +### Timeline | |
| 66 | +- DAG graph with fork/merge connectors, color-coded branches | |
| 67 | +- Merge commit diamonds, leaf indicators | |
| 68 | +- Keyboard navigation (j/k/Enter), HTMX infinite scroll | |
| 69 | +- RSS feed | |
| 70 | + | |
| 71 | +### Diffs | |
| 72 | +- Unified and side-by-side view (toggle with localStorage preference) | |
| 73 | +- Syntax highlighting via highlight.js | |
| 74 | +- Line-level permalinks | |
| 75 | +- Compare any two checkins | |
| 76 | + | |
| 77 | +### Tickets | |
| 78 | +- Filter by status, type, priority, severity | |
| 79 | +- Full CRUD: create, edit, close/reopen, comment | |
| 80 | +- CSV export | |
| 81 | +- Pagination with configurable page size | |
| 82 | + | |
| 83 | +### Wiki | |
| 84 | +- Markdown + Fossil wiki markup + raw HTML | |
| 85 | +- Pikchr diagram rendering | |
| 86 | +- Right-sidebar table of contents | |
| 87 | +- Create and edit pages | |
| 88 | + | |
| 89 | +### Forum | |
| 90 | +- Threaded discussions (Fossil-native + Django-backed posts) | |
| 91 | +- Create threads, post replies | |
| 92 | +- Markdown body with preview | |
| 93 | + | |
| 94 | +### Releases | |
| 95 | +- Versioned releases with tag names and markdown changelogs | |
| 96 | +- File attachments with download counts | |
| 97 | +- Draft and prerelease support | |
| 98 | + | |
| 99 | +### Sync | |
| 100 | +- Pull from upstream Fossil remotes | |
| 101 | +- Git mirror to GitHub/GitLab (OAuth or SSH key auth) | |
| 102 | +- Clone/push/pull over HTTP via `fossil http` CGI proxy | |
| 103 | +- SSH push via restricted sshd (port 2222) | |
| 104 | +- Configurable sync modes: on-change, scheduled, both | |
| 105 | + | |
| 106 | +### Webhooks | |
| 107 | +- Outbound webhooks on checkin, ticket, wiki, and release events | |
| 108 | +- HMAC-SHA256 signed payloads | |
| 109 | +- Exponential backoff retry (3 attempts) | |
| 110 | +- Delivery log with response status and timing | |
| 111 | + | |
| 112 | +### Organization | |
| 113 | +- Single-org model with teams and members | |
| 114 | +- User CRUD: create, edit, deactivate, change password | |
| 115 | +- Team management with member assignment | |
| 116 | +- Project-level team roles: read, write, admin | |
| 117 | +- Project visibility: public, internal, private | |
| 118 | + | |
| 119 | +### Infrastructure | |
| 120 | +- Omnibus Docker image (Fossil compiled from source) | |
| 121 | +- Caddy for SSL termination and subdomain routing | |
| 122 | +- Litestream for continuous SQLite-to-S3 replication | |
| 123 | +- Celery Beat for scheduled metadata sync and upstream checks | |
| 124 | +- Encrypted credential storage (Fernet/AES-128-CBC at rest) | |
| 35 | 125 | |
| 36 | 126 | ## Architecture |
| 37 | 127 | |
| 38 | 128 | ``` |
| 39 | 129 | Browser |
| 40 | - +-- Django Templates + HTMX + Alpine.js + Tailwind CSS | |
| 41 | - | | |
| 42 | - v (standard HTTP + HTMX partial responses) | |
| 43 | - | | |
| 44 | - Django 5 (Views, ORM, Permissions) | |
| 45 | - |-- Celery (async tasks) | |
| 46 | - |-- PostgreSQL 16 (data) | |
| 47 | - +-- Redis 7 (cache, sessions, broker) | |
| 130 | + | | |
| 131 | + v | |
| 132 | +Django 5 + HTMX + Alpine.js + Tailwind CSS | |
| 133 | + | | |
| 134 | + |-- FossilReader (direct SQLite reads from .fossil files) | |
| 135 | + |-- FossilCLI (subprocess wrapper for write operations) | |
| 136 | + |-- fossil http (CGI proxy for clone/push/pull) | |
| 137 | + | | |
| 138 | + |-- PostgreSQL 16 (orgs, users, teams, projects, settings) | |
| 139 | + |-- Redis 7 (Celery broker, cache) | |
| 140 | + |-- Celery (background sync, webhooks, notifications) | |
| 141 | + | | |
| 142 | + v | |
| 143 | +.fossil files (SQLite — code + wiki + tickets + forum + technotes) | |
| 144 | + | | |
| 145 | + v | |
| 146 | +Litestream --> S3 (continuous backup) | |
| 48 | 147 | ``` |
| 49 | 148 | |
| 50 | -No separate frontend service. Django serves everything — templates, static files, and HTMX partials. | |
| 51 | - | |
| 52 | -## Endpoints | |
| 53 | - | |
| 54 | -| Path | Description | | |
| 55 | -|------|------------| | |
| 56 | -| `/` | Redirects to dashboard | | |
| 57 | -| `/dashboard/` | Main dashboard | | |
| 58 | -| `/items/` | Item list with HTMX search | | |
| 59 | -| `/items/create/` | Create item form | | |
| 60 | -| `/items/<slug>/` | Item detail | | |
| 61 | -| `/items/<slug>/edit/` | Edit item form | | |
| 62 | -| `/items/<slug>/delete/` | Delete confirmation | | |
| 63 | -| `/auth/login/` | Login page | | |
| 64 | -| `/auth/logout/` | Logout | | |
| 65 | -| `/admin/` | Django admin | | |
| 66 | -| `/health/` | Health check (JSON) | | |
| 149 | +No separate frontend service. Django serves everything: templates, static files, and HTMX partials. | |
| 150 | + | |
| 151 | +## Configuration | |
| 152 | + | |
| 153 | +All runtime settings are configurable via Django admin (Constance): | |
| 154 | + | |
| 155 | +| Setting | Default | Description | | |
| 156 | +|---------|---------|-------------| | |
| 157 | +| `SITE_NAME` | Fossilrepo | Display name | | |
| 158 | +| `FOSSIL_DATA_DIR` | /data/repos | Where .fossil files live | | |
| 159 | +| `FOSSIL_BINARY_PATH` | fossil | Path to the fossil binary | | |
| 160 | +| `FOSSIL_STORE_IN_DB` | false | Store .fossil snapshots via Django file storage | | |
| 161 | +| `FOSSIL_S3_TRACKING` | false | Track S3/Litestream replication | | |
| 162 | +| `GIT_SYNC_MODE` | disabled | Default sync mode for new mirrors | | |
| 163 | +| `GIT_SYNC_SCHEDULE` | */15 * * * * | Default cron for scheduled sync | | |
| 164 | + | |
| 165 | +See [`.env.example`](.env.example) for all environment variables and [`.env.production.example`](.env.production.example) for production configuration. | |
| 67 | 166 | |
| 68 | 167 | ## Development |
| 69 | 168 | |
| 70 | 169 | ```bash |
| 71 | 170 | # Local development (without Docker) |
| 72 | 171 | uv sync --all-extras |
| 73 | -POSTGRES_HOST=localhost POSTGRES_PORT=5434 uv run python manage.py runserver | |
| 172 | +DJANGO_DEBUG=true POSTGRES_HOST=localhost uv run python manage.py runserver | |
| 74 | 173 | |
| 75 | 174 | # Run tests |
| 76 | -make test | |
| 175 | +DJANGO_DEBUG=true uv run pytest | |
| 77 | 176 | |
| 78 | -# Run linter | |
| 79 | -make lint | |
| 177 | +# Lint | |
| 178 | +ruff check . && ruff format --check . | |
| 80 | 179 | ``` |
| 81 | 180 | |
| 82 | -## Conventions | |
| 83 | - | |
| 84 | -See [`bootstrap.md`](bootstrap.md) for the full conventions document. | |
| 85 | - | |
| 86 | -Key patterns: | |
| 87 | -- All models inherit `Tracking` (audit trails) or `BaseCoreModel` (named entities with UUID) | |
| 88 | -- Soft deletes only — never call `.delete()` on business objects | |
| 89 | -- Group-based permissions checked in every view via `P.PERMISSION.check(user)` | |
| 90 | -- HTMX partials for dynamic updates, Alpine.js for client-side state | |
| 91 | -- Tests against real Postgres, both allowed and denied permission cases | |
| 181 | +See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full development guide and [`bootstrap.md`](bootstrap.md) for codebase conventions. | |
| 182 | + | |
| 183 | +## License | |
| 184 | + | |
| 185 | +MIT License. See [LICENSE](LICENSE) for details. | |
| 92 | 186 | |
| 93 | 187 | --- |
| 94 | 188 | |
| 95 | -Fossilrepo is a [CONFLICT](https://weareconflict.com) brand. CONFLICT is a registered trademark of CONFLICT LLC. | |
| 189 | +Built by [CONFLICT](https://weareconflict.com). Fossilrepo is open source under the MIT license. | |
| 96 | 190 |
| --- README.md | |
| +++ README.md | |
| @@ -1,95 +1,189 @@ | |
| 1 | # Fossilrepo Django + HTMX |
| 2 | |
| 3 | Server-rendered Django with HTMX for dynamic behavior and Alpine.js for lightweight client state. Tailwind CSS for styling. Choose this for content-heavy CRUD, admin-centric tools, and apps where server-rendered simplicity beats a full SPA. |
| 4 | |
| 5 | ## Stack |
| 6 | |
| 7 | | Layer | Technology | |
| 8 | |-------|-----------| |
| 9 | | Backend | Django 5 (Python 3.12+) | |
| 10 | | Frontend | HTMX 2.0 + Alpine.js 3 + Tailwind CSS | |
| 11 | | Database | PostgreSQL 16 | |
| 12 | | Cache/Broker | Redis 7 | |
| 13 | | Job Queue | Celery + Redis | |
| 14 | | Auth | Session-based (httpOnly cookies) | |
| 15 | | Linter | Ruff | |
| 16 | | Package Manager | uv | |
| 17 | |
| 18 | ## Quick Start |
| 19 | |
| 20 | ```bash |
| 21 | # Start the stack |
| 22 | docker compose up -d --build |
| 23 | |
| 24 | # Run migrations and seed data |
| 25 | docker compose exec backend python manage.py migrate |
| 26 | docker compose exec backend python manage.py seed |
| 27 | |
| 28 | # Open the app |
| 29 | open http://localhost:8000 |
| 30 | ``` |
| 31 | |
| 32 | **Default users:** |
| 33 | - `admin` / `admin` (superuser, full access) |
| 34 | - `viewer` / `viewer` (view-only permissions) |
| 35 | |
| 36 | ## Architecture |
| 37 | |
| 38 | ``` |
| 39 | Browser |
| 40 | +-- Django Templates + HTMX + Alpine.js + Tailwind CSS |
| 41 | | |
| 42 | v (standard HTTP + HTMX partial responses) |
| 43 | | |
| 44 | Django 5 (Views, ORM, Permissions) |
| 45 | |-- Celery (async tasks) |
| 46 | |-- PostgreSQL 16 (data) |
| 47 | +-- Redis 7 (cache, sessions, broker) |
| 48 | ``` |
| 49 | |
| 50 | No separate frontend service. Django serves everything — templates, static files, and HTMX partials. |
| 51 | |
| 52 | ## Endpoints |
| 53 | |
| 54 | | Path | Description | |
| 55 | |------|------------| |
| 56 | | `/` | Redirects to dashboard | |
| 57 | | `/dashboard/` | Main dashboard | |
| 58 | | `/items/` | Item list with HTMX search | |
| 59 | | `/items/create/` | Create item form | |
| 60 | | `/items/<slug>/` | Item detail | |
| 61 | | `/items/<slug>/edit/` | Edit item form | |
| 62 | | `/items/<slug>/delete/` | Delete confirmation | |
| 63 | | `/auth/login/` | Login page | |
| 64 | | `/auth/logout/` | Logout | |
| 65 | | `/admin/` | Django admin | |
| 66 | | `/health/` | Health check (JSON) | |
| 67 | |
| 68 | ## Development |
| 69 | |
| 70 | ```bash |
| 71 | # Local development (without Docker) |
| 72 | uv sync --all-extras |
| 73 | POSTGRES_HOST=localhost POSTGRES_PORT=5434 uv run python manage.py runserver |
| 74 | |
| 75 | # Run tests |
| 76 | make test |
| 77 | |
| 78 | # Run linter |
| 79 | make lint |
| 80 | ``` |
| 81 | |
| 82 | ## Conventions |
| 83 | |
| 84 | See [`bootstrap.md`](bootstrap.md) for the full conventions document. |
| 85 | |
| 86 | Key patterns: |
| 87 | - All models inherit `Tracking` (audit trails) or `BaseCoreModel` (named entities with UUID) |
| 88 | - Soft deletes only — never call `.delete()` on business objects |
| 89 | - Group-based permissions checked in every view via `P.PERMISSION.check(user)` |
| 90 | - HTMX partials for dynamic updates, Alpine.js for client-side state |
| 91 | - Tests against real Postgres, both allowed and denied permission cases |
| 92 | |
| 93 | --- |
| 94 | |
| 95 | Fossilrepo is a [CONFLICT](https://weareconflict.com) brand. CONFLICT is a registered trademark of CONFLICT LLC. |
| 96 |
| --- README.md | |
| +++ README.md | |
| @@ -1,95 +1,189 @@ | |
| 1 | # Fossilrepo |
| 2 | |
| 3 | **Self-hosted Fossil forge with a modern web interface.** |
| 4 | |
| 5 | Fossilrepo wraps [Fossil SCM](https://fossil-scm.org) with a Django + HTMX management layer, replacing Fossil's built-in web UI with a GitHub/GitLab-caliber experience while preserving everything that makes Fossil unique: single-file repos, built-in wiki, tickets, forum, and technotes. |
| 6 | |
| 7 | ## Why Fossilrepo? |
| 8 | |
| 9 | Fossil is the most underrated version control system. Every repository is a single SQLite file containing your code, wiki, tickets, forum, and technotes. No external services, no complex setup. But its web UI hasn't changed since 1998. |
| 10 | |
| 11 | Fossilrepo fixes that. You get: |
| 12 | |
| 13 | - A modern dark/light UI built with Django, HTMX, Alpine.js, and Tailwind CSS |
| 14 | - GitHub-style code browser with line numbers, blame, history, and syntax highlighting |
| 15 | - Timeline with DAG graph showing fork/merge connectors and color-coded branches |
| 16 | - Full ticket CRUD with filters, comments, and CSV export |
| 17 | - Wiki with Markdown + Fossil markup + Pikchr diagram rendering |
| 18 | - Forum with threaded discussions |
| 19 | - Releases with file attachments and markdown changelogs |
| 20 | - Git mirror sync to GitHub/GitLab via OAuth |
| 21 | - Clone/push/pull over HTTP and SSH through Django's auth layer |
| 22 | - Webhook dispatch with HMAC signing and delivery logs |
| 23 | - Omnibus Docker image with Fossil compiled from source |
| 24 | |
| 25 | All while Fossil remains the source of truth. Fossilrepo reads `.fossil` files directly via SQLite for speed, and uses the `fossil` CLI for writes to preserve artifact integrity. |
| 26 | |
| 27 | ## Stack |
| 28 | |
| 29 | | Layer | Technology | |
| 30 | |-------|-----------| |
| 31 | | Backend | Django 5 (Python 3.12+) | |
| 32 | | Frontend | HTMX 2.0 + Alpine.js 3 + Tailwind CSS (CDN) | |
| 33 | | Database | PostgreSQL 16 (app data) + SQLite (Fossil repos) | |
| 34 | | Cache/Broker | Redis 7 | |
| 35 | | Jobs | Celery + Redis | |
| 36 | | Auth | Session-based (httpOnly cookies) | |
| 37 | | SCM | Fossil 2.24 (compiled from source in Docker) | |
| 38 | | Linter | Ruff | |
| 39 | |
| 40 | ## Quick Start |
| 41 | |
| 42 | ```bash |
| 43 | git clone https://github.com/ConflictHQ/fossilrepo.git |
| 44 | cd fossilrepo |
| 45 | docker compose up -d --build |
| 46 | |
| 47 | # Run migrations and seed sample data |
| 48 | docker compose exec backend python manage.py migrate |
| 49 | docker compose exec backend python manage.py seed |
| 50 | |
| 51 | # Open the app |
| 52 | open http://localhost:8000 |
| 53 | ``` |
| 54 | |
| 55 | **Default users:** `admin` / `admin` (superuser) and `viewer` / `viewer` (read-only). |
| 56 | |
| 57 | ## Features |
| 58 | |
| 59 | ### Code Browser |
| 60 | - Directory navigation with breadcrumbs |
| 61 | - Syntax-highlighted source view with line numbers and permalinks |
| 62 | - Blame with age-based coloring (newest = brand red, oldest = gray) |
| 63 | - File history, raw download, rendered preview for Markdown/HTML |
| 64 | |
| 65 | ### Timeline |
| 66 | - DAG graph with fork/merge connectors, color-coded branches |
| 67 | - Merge commit diamonds, leaf indicators |
| 68 | - Keyboard navigation (j/k/Enter), HTMX infinite scroll |
| 69 | - RSS feed |
| 70 | |
| 71 | ### Diffs |
| 72 | - Unified and side-by-side view (toggle with localStorage preference) |
| 73 | - Syntax highlighting via highlight.js |
| 74 | - Line-level permalinks |
| 75 | - Compare any two checkins |
| 76 | |
| 77 | ### Tickets |
| 78 | - Filter by status, type, priority, severity |
| 79 | - Full CRUD: create, edit, close/reopen, comment |
| 80 | - CSV export |
| 81 | - Pagination with configurable page size |
| 82 | |
| 83 | ### Wiki |
| 84 | - Markdown + Fossil wiki markup + raw HTML |
| 85 | - Pikchr diagram rendering |
| 86 | - Right-sidebar table of contents |
| 87 | - Create and edit pages |
| 88 | |
| 89 | ### Forum |
| 90 | - Threaded discussions (Fossil-native + Django-backed posts) |
| 91 | - Create threads, post replies |
| 92 | - Markdown body with preview |
| 93 | |
| 94 | ### Releases |
| 95 | - Versioned releases with tag names and markdown changelogs |
| 96 | - File attachments with download counts |
| 97 | - Draft and prerelease support |
| 98 | |
| 99 | ### Sync |
| 100 | - Pull from upstream Fossil remotes |
| 101 | - Git mirror to GitHub/GitLab (OAuth or SSH key auth) |
| 102 | - Clone/push/pull over HTTP via `fossil http` CGI proxy |
| 103 | - SSH push via restricted sshd (port 2222) |
| 104 | - Configurable sync modes: on-change, scheduled, both |
| 105 | |
| 106 | ### Webhooks |
| 107 | - Outbound webhooks on checkin, ticket, wiki, and release events |
| 108 | - HMAC-SHA256 signed payloads |
| 109 | - Exponential backoff retry (3 attempts) |
| 110 | - Delivery log with response status and timing |
| 111 | |
| 112 | ### Organization |
| 113 | - Single-org model with teams and members |
| 114 | - User CRUD: create, edit, deactivate, change password |
| 115 | - Team management with member assignment |
| 116 | - Project-level team roles: read, write, admin |
| 117 | - Project visibility: public, internal, private |
| 118 | |
| 119 | ### Infrastructure |
| 120 | - Omnibus Docker image (Fossil compiled from source) |
| 121 | - Caddy for SSL termination and subdomain routing |
| 122 | - Litestream for continuous SQLite-to-S3 replication |
| 123 | - Celery Beat for scheduled metadata sync and upstream checks |
| 124 | - Encrypted credential storage (Fernet/AES-128-CBC at rest) |
| 125 | |
| 126 | ## Architecture |
| 127 | |
| 128 | ``` |
| 129 | Browser |
| 130 | | |
| 131 | v |
| 132 | Django 5 + HTMX + Alpine.js + Tailwind CSS |
| 133 | | |
| 134 | |-- FossilReader (direct SQLite reads from .fossil files) |
| 135 | |-- FossilCLI (subprocess wrapper for write operations) |
| 136 | |-- fossil http (CGI proxy for clone/push/pull) |
| 137 | | |
| 138 | |-- PostgreSQL 16 (orgs, users, teams, projects, settings) |
| 139 | |-- Redis 7 (Celery broker, cache) |
| 140 | |-- Celery (background sync, webhooks, notifications) |
| 141 | | |
| 142 | v |
| 143 | .fossil files (SQLite — code + wiki + tickets + forum + technotes) |
| 144 | | |
| 145 | v |
| 146 | Litestream --> S3 (continuous backup) |
| 147 | ``` |
| 148 | |
| 149 | No separate frontend service. Django serves everything: templates, static files, and HTMX partials. |
| 150 | |
| 151 | ## Configuration |
| 152 | |
| 153 | All runtime settings are configurable via Django admin (Constance): |
| 154 | |
| 155 | | Setting | Default | Description | |
| 156 | |---------|---------|-------------| |
| 157 | | `SITE_NAME` | Fossilrepo | Display name | |
| 158 | | `FOSSIL_DATA_DIR` | /data/repos | Where .fossil files live | |
| 159 | | `FOSSIL_BINARY_PATH` | fossil | Path to the fossil binary | |
| 160 | | `FOSSIL_STORE_IN_DB` | false | Store .fossil snapshots via Django file storage | |
| 161 | | `FOSSIL_S3_TRACKING` | false | Track S3/Litestream replication | |
| 162 | | `GIT_SYNC_MODE` | disabled | Default sync mode for new mirrors | |
| 163 | | `GIT_SYNC_SCHEDULE` | */15 * * * * | Default cron for scheduled sync | |
| 164 | |
| 165 | See [`.env.example`](.env.example) for all environment variables and [`.env.production.example`](.env.production.example) for production configuration. |
| 166 | |
| 167 | ## Development |
| 168 | |
| 169 | ```bash |
| 170 | # Local development (without Docker) |
| 171 | uv sync --all-extras |
| 172 | DJANGO_DEBUG=true POSTGRES_HOST=localhost uv run python manage.py runserver |
| 173 | |
| 174 | # Run tests |
| 175 | DJANGO_DEBUG=true uv run pytest |
| 176 | |
| 177 | # Lint |
| 178 | ruff check . && ruff format --check . |
| 179 | ``` |
| 180 | |
| 181 | See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full development guide and [`bootstrap.md`](bootstrap.md) for codebase conventions. |
| 182 | |
| 183 | ## License |
| 184 | |
| 185 | MIT License. See [LICENSE](LICENSE) for details. |
| 186 | |
| 187 | --- |
| 188 | |
| 189 | Built by [CONFLICT](https://weareconflict.com). Fossilrepo is open source under the MIT license. |
| 190 |
+36
-11
| --- SECURITY.md | ||
| +++ SECURITY.md | ||
| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | |
| 5 | 5 | If you discover a security vulnerability in Fossilrepo, please report it responsibly. |
| 6 | 6 | |
| 7 | 7 | **Do not open a public issue.** |
| 8 | 8 | |
| 9 | -Instead, email **[email protected]** with: | |
| 9 | +Email **[email protected]** with: | |
| 10 | 10 | |
| 11 | 11 | - Description of the vulnerability |
| 12 | 12 | - Steps to reproduce |
| 13 | 13 | - Potential impact |
| 14 | 14 | - Suggested fix (if any) |
| @@ -19,15 +19,40 @@ | ||
| 19 | 19 | |
| 20 | 20 | | Version | Supported | |
| 21 | 21 | | ------- | --------- | |
| 22 | 22 | | latest | Yes | |
| 23 | 23 | |
| 24 | -## Security Best Practices | |
| 25 | - | |
| 26 | -When deploying Fossilrepo: | |
| 27 | - | |
| 28 | -- Change all default credentials (database, MinIO, session secret) | |
| 29 | -- Use HTTPS in production | |
| 30 | -- Set `NODE_ENV=production` | |
| 31 | -- Configure `CORS_ORIGINS` to your domain only | |
| 32 | -- Use strong Auth0 credentials | |
| 33 | -- Review the security hardening in `bootstrap.md` | |
| 24 | +## Security Model | |
| 25 | + | |
| 26 | +### Authentication | |
| 27 | + | |
| 28 | +- Session-based authentication with httpOnly, secure cookies | |
| 29 | +- CSRF protection on all forms (HTMX includes token via `htmx:configRequest`) | |
| 30 | +- Rate limiting on login (10 attempts/minute per IP) | |
| 31 | +- Password validation enforced (Django's built-in validators) | |
| 32 | + | |
| 33 | +### Authorization | |
| 34 | + | |
| 35 | +- Group-based permissions via `P` enum (`core/permissions.py`) | |
| 36 | +- Project-level RBAC: read, write, admin roles via team membership | |
| 37 | +- Project visibility: public (anonymous read), internal (authenticated), private (team members only) | |
| 38 | +- All views enforce permission checks before data access | |
| 39 | + | |
| 40 | +### Data Protection | |
| 41 | + | |
| 42 | +- SSH keys and OAuth tokens encrypted at rest (Fernet/AES-128-CBC, keyed from `SECRET_KEY`) | |
| 43 | +- No plaintext credentials stored in the database | |
| 44 | +- Fossil sync uses `--localauth` only for authenticated users with write access | |
| 45 | +- Anonymous users get pull-only access on public repos (no `--localauth`) | |
| 46 | + | |
| 47 | +### Deployment | |
| 48 | + | |
| 49 | +When deploying Fossilrepo in production: | |
| 50 | + | |
| 51 | +- Set a strong, unique `DJANGO_SECRET_KEY` (the app refuses to start without one when `DEBUG=False`) | |
| 52 | +- Change all default database credentials | |
| 53 | +- Enable HTTPS (`SECURE_SSL_REDIRECT`, `SESSION_COOKIE_SECURE`, `CSRF_COOKIE_SECURE` are automatic when `DEBUG=False`) | |
| 54 | +- Set `DJANGO_ALLOWED_HOSTS` to your domain only | |
| 55 | +- Set `CORS_ALLOWED_ORIGINS` and `CSRF_TRUSTED_ORIGINS` to your domain | |
| 56 | +- Review Constance settings in Django admin (OAuth secrets, S3 credentials) | |
| 57 | +- Use a reverse proxy (Caddy/nginx) for SSL termination | |
| 58 | +- Keep the Fossil binary updated (compiled from source in the Docker image) | |
| 34 | 59 | |
| 35 | 60 | DELETED _old_CLAUDE.md |
| 36 | 61 | DELETED _old_bootstrap.md |
| 37 | 62 | DELETED fossil-platform/Dockerfile |
| 38 | 63 | DELETED fossil-platform/README.md |
| --- SECURITY.md | |
| +++ SECURITY.md | |
| @@ -4,11 +4,11 @@ | |
| 4 | |
| 5 | If you discover a security vulnerability in Fossilrepo, please report it responsibly. |
| 6 | |
| 7 | **Do not open a public issue.** |
| 8 | |
| 9 | Instead, email **[email protected]** with: |
| 10 | |
| 11 | - Description of the vulnerability |
| 12 | - Steps to reproduce |
| 13 | - Potential impact |
| 14 | - Suggested fix (if any) |
| @@ -19,15 +19,40 @@ | |
| 19 | |
| 20 | | Version | Supported | |
| 21 | | ------- | --------- | |
| 22 | | latest | Yes | |
| 23 | |
| 24 | ## Security Best Practices |
| 25 | |
| 26 | When deploying Fossilrepo: |
| 27 | |
| 28 | - Change all default credentials (database, MinIO, session secret) |
| 29 | - Use HTTPS in production |
| 30 | - Set `NODE_ENV=production` |
| 31 | - Configure `CORS_ORIGINS` to your domain only |
| 32 | - Use strong Auth0 credentials |
| 33 | - Review the security hardening in `bootstrap.md` |
| 34 | |
| 35 | ELETED _old_CLAUDE.md |
| 36 | ELETED _old_bootstrap.md |
| 37 | ELETED fossil-platform/Dockerfile |
| 38 | ELETED fossil-platform/README.md |
| --- SECURITY.md | |
| +++ SECURITY.md | |
| @@ -4,11 +4,11 @@ | |
| 4 | |
| 5 | If you discover a security vulnerability in Fossilrepo, please report it responsibly. |
| 6 | |
| 7 | **Do not open a public issue.** |
| 8 | |
| 9 | Email **[email protected]** with: |
| 10 | |
| 11 | - Description of the vulnerability |
| 12 | - Steps to reproduce |
| 13 | - Potential impact |
| 14 | - Suggested fix (if any) |
| @@ -19,15 +19,40 @@ | |
| 19 | |
| 20 | | Version | Supported | |
| 21 | | ------- | --------- | |
| 22 | | latest | Yes | |
| 23 | |
| 24 | ## Security Model |
| 25 | |
| 26 | ### Authentication |
| 27 | |
| 28 | - Session-based authentication with httpOnly, secure cookies |
| 29 | - CSRF protection on all forms (HTMX includes token via `htmx:configRequest`) |
| 30 | - Rate limiting on login (10 attempts/minute per IP) |
| 31 | - Password validation enforced (Django's built-in validators) |
| 32 | |
| 33 | ### Authorization |
| 34 | |
| 35 | - Group-based permissions via `P` enum (`core/permissions.py`) |
| 36 | - Project-level RBAC: read, write, admin roles via team membership |
| 37 | - Project visibility: public (anonymous read), internal (authenticated), private (team members only) |
| 38 | - All views enforce permission checks before data access |
| 39 | |
| 40 | ### Data Protection |
| 41 | |
| 42 | - SSH keys and OAuth tokens encrypted at rest (Fernet/AES-128-CBC, keyed from `SECRET_KEY`) |
| 43 | - No plaintext credentials stored in the database |
| 44 | - Fossil sync uses `--localauth` only for authenticated users with write access |
| 45 | - Anonymous users get pull-only access on public repos (no `--localauth`) |
| 46 | |
| 47 | ### Deployment |
| 48 | |
| 49 | When deploying Fossilrepo in production: |
| 50 | |
| 51 | - Set a strong, unique `DJANGO_SECRET_KEY` (the app refuses to start without one when `DEBUG=False`) |
| 52 | - Change all default database credentials |
| 53 | - Enable HTTPS (`SECURE_SSL_REDIRECT`, `SESSION_COOKIE_SECURE`, `CSRF_COOKIE_SECURE` are automatic when `DEBUG=False`) |
| 54 | - Set `DJANGO_ALLOWED_HOSTS` to your domain only |
| 55 | - Set `CORS_ALLOWED_ORIGINS` and `CSRF_TRUSTED_ORIGINS` to your domain |
| 56 | - Review Constance settings in Django admin (OAuth secrets, S3 credentials) |
| 57 | - Use a reverse proxy (Caddy/nginx) for SSL termination |
| 58 | - Keep the Fossil binary updated (compiled from source in the Docker image) |
| 59 | |
| 60 | ELETED _old_CLAUDE.md |
| 61 | ELETED _old_bootstrap.md |
| 62 | ELETED fossil-platform/Dockerfile |
| 63 | ELETED fossil-platform/README.md |
D
_old_CLAUDE.md
-57
| --- a/_old_CLAUDE.md | ||
| +++ b/_old_CLAUDE.md | ||
| @@ -1,57 +0,0 @@ | ||
| 1 | -# CLAUDE.md -- fossilrepo | |
| 2 | - | |
| 3 | -## Project Overview | |
| 4 | - | |
| 5 | -fossilrepo is a self-hosted Fossil SCM server infrastructure tool. It provides Docker + Caddy + Litestream hosting for Fossil repositories, a CLI wrapper around fossil commands, and a sync bridge to mirror Fossil repos to GitHub/GitLab. | |
| 6 | - | |
| 7 | -Open source (MIT). Part of the CONFLICT ecosystem. | |
| 8 | - | |
| 9 | -## Repository Structure | |
| 10 | - | |
| 11 | -``` | |
| 12 | -fossilrepo/ | |
| 13 | -├── fossilrepo/ # Python package | |
| 14 | -│ ├── server/ # Fossil server management (Docker, Caddy, Litestream) | |
| 15 | -│ │ ├── config.py # Pydantic server configuration | |
| 16 | -│ │ └── manager.py # Repo lifecycle (create, delete, list) | |
| 17 | -│ ├── sync/ # Fossil → Git mirror | |
| 18 | -│ │ ├── mirror.py # Core sync logic (commits, tickets, wiki) | |
| 19 | -│ │ └── mappings.py # Data models for Fossil↔Git mappings | |
| 20 | -│ └── cli/ # Click CLI | |
| 21 | -│ └── main.py # CLI entrypoint (server, repo, sync commands) | |
| 22 | -├── docker/ # Container configs | |
| 23 | -│ ├── Dockerfile # Fossil + Caddy + Litestream | |
| 24 | -│ ├── docker-compose.yml # Local dev stack | |
| 25 | -│ ├── Caddyfile # Subdomain routing | |
| 26 | -│ └── litestream.yml # S3 replication | |
| 27 | -├── tests/ # pytest, mirrors fossilrepo/ | |
| 28 | -├── docs/ # Architecture, guides | |
| 29 | -├── fossil-platform/ # Old exploration (Flask + React), kept for reference | |
| 30 | -├── bootstrap.md # Project bootstrap doc — read first | |
| 31 | -└── AGENTS.md # Agent conventions pointer | |
| 32 | -``` | |
| 33 | - | |
| 34 | -## Key Conventions | |
| 35 | - | |
| 36 | -- Python 3.11+, typed with Pydantic models | |
| 37 | -- Click for CLI, Rich for terminal output | |
| 38 | -- Ruff for linting, pytest for testing | |
| 39 | -- Fossil is the source of truth; Git remotes are downstream mirrors | |
| 40 | -- Server infra: Docker + Caddy (SSL, subdomain routing) + Litestream (S3 replication) | |
| 41 | -- Each repo is a single .fossil file (SQLite) — Litestream replicates it continuously | |
| 42 | - | |
| 43 | -## Development | |
| 44 | - | |
| 45 | -```bash | |
| 46 | -pip install -e ".[dev]" | |
| 47 | -pytest | |
| 48 | -ruff check . | |
| 49 | -``` | |
| 50 | - | |
| 51 | -## CLI | |
| 52 | - | |
| 53 | -```bash | |
| 54 | -fossilrepo server start|stop|status | |
| 55 | -fossilrepo repo create|list|delete | |
| 56 | -fossilrepo sync run|status | |
| 57 | -``` |
| --- a/_old_CLAUDE.md | |
| +++ b/_old_CLAUDE.md | |
| @@ -1,57 +0,0 @@ | |
| 1 | # CLAUDE.md -- fossilrepo |
| 2 | |
| 3 | ## Project Overview |
| 4 | |
| 5 | fossilrepo is a self-hosted Fossil SCM server infrastructure tool. It provides Docker + Caddy + Litestream hosting for Fossil repositories, a CLI wrapper around fossil commands, and a sync bridge to mirror Fossil repos to GitHub/GitLab. |
| 6 | |
| 7 | Open source (MIT). Part of the CONFLICT ecosystem. |
| 8 | |
| 9 | ## Repository Structure |
| 10 | |
| 11 | ``` |
| 12 | fossilrepo/ |
| 13 | ├── fossilrepo/ # Python package |
| 14 | │ ├── server/ # Fossil server management (Docker, Caddy, Litestream) |
| 15 | │ │ ├── config.py # Pydantic server configuration |
| 16 | │ │ └── manager.py # Repo lifecycle (create, delete, list) |
| 17 | │ ├── sync/ # Fossil → Git mirror |
| 18 | │ │ ├── mirror.py # Core sync logic (commits, tickets, wiki) |
| 19 | │ │ └── mappings.py # Data models for Fossil↔Git mappings |
| 20 | │ └── cli/ # Click CLI |
| 21 | │ └── main.py # CLI entrypoint (server, repo, sync commands) |
| 22 | ├── docker/ # Container configs |
| 23 | │ ├── Dockerfile # Fossil + Caddy + Litestream |
| 24 | │ ├── docker-compose.yml # Local dev stack |
| 25 | │ ├── Caddyfile # Subdomain routing |
| 26 | │ └── litestream.yml # S3 replication |
| 27 | ├── tests/ # pytest, mirrors fossilrepo/ |
| 28 | ├── docs/ # Architecture, guides |
| 29 | ├── fossil-platform/ # Old exploration (Flask + React), kept for reference |
| 30 | ├── bootstrap.md # Project bootstrap doc — read first |
| 31 | └── AGENTS.md # Agent conventions pointer |
| 32 | ``` |
| 33 | |
| 34 | ## Key Conventions |
| 35 | |
| 36 | - Python 3.11+, typed with Pydantic models |
| 37 | - Click for CLI, Rich for terminal output |
| 38 | - Ruff for linting, pytest for testing |
| 39 | - Fossil is the source of truth; Git remotes are downstream mirrors |
| 40 | - Server infra: Docker + Caddy (SSL, subdomain routing) + Litestream (S3 replication) |
| 41 | - Each repo is a single .fossil file (SQLite) — Litestream replicates it continuously |
| 42 | |
| 43 | ## Development |
| 44 | |
| 45 | ```bash |
| 46 | pip install -e ".[dev]" |
| 47 | pytest |
| 48 | ruff check . |
| 49 | ``` |
| 50 | |
| 51 | ## CLI |
| 52 | |
| 53 | ```bash |
| 54 | fossilrepo server start|stop|status |
| 55 | fossilrepo repo create|list|delete |
| 56 | fossilrepo sync run|status |
| 57 | ``` |
| --- a/_old_CLAUDE.md | |
| +++ b/_old_CLAUDE.md | |
| @@ -1,57 +0,0 @@ | |
D
_old_bootstrap.md
-84
| --- a/_old_bootstrap.md | ||
| +++ b/_old_bootstrap.md | ||
| @@ -1,89 +0,0 @@ | ||
| 1 | -# fossilrepo — bootstrap | |
| 2 | - | |
| 3 | -Omnibus-style installer for a self-hosted Fossil forge. One command gets you a full-stack code hosting platform: VCS, issues, wiki, timeline, web UI, SSL, and continuous backups — all powered by Fossil SCM. | |
| 4 | - | |
| 5 | -Think GitLab Omnibus, but for Fossil. | |
| 6 | - | |
| ---- | ||
| 7 | - | |
| 8 | -## Why Fossil | |
| 9 | - | |
| 10 | -A Fossil repo is a single SQLite file. It contains the full VCS history, issue tracker, wiki, forum, and timeline. No external services. No rate limits. Portable — hand the file to someone and they have everything. | |
| 11 | - | |
| 12 | -For teams running CI agents or automation: | |
| 13 | -- Agents commit, file tickets, and update the wiki through one CLI and one protocol | |
| 14 | -- No API rate limits when many agents are pushing simultaneously | |
| 15 | -- The `.fossil` file IS the project artifact — a self-contained archive | |
| 16 | -- Litestream replicates it to S3 continuously — backup and point-in-time recovery for free | |
| 17 | - | |
| 18 | -Fossil also has a built-in web UI (skinnable), autosync, peer-to-peer sync, and unversioned content storage (like Git LFS but built-in). | |
| 19 | - | |
| ---- | ||
| 20 | - | |
| 21 | -## What fossilrepo Does | |
| 22 | - | |
| 23 | -fossilrepo packages everything needed to run a production Fossil server into one installable unit: | |
| 24 | - | |
| 25 | -- **Fossil server** — serves all repos from a single process | |
| 26 | -- **Caddy** — SSL termination, subdomain-per-repo routing (`reponame.your-domain.com`) | |
| 27 | -- **Litestream** — continuous SQLite replication to S3/MinIO (backup + point-in-time recovery) | |
| 28 | -- **CLI** — repo lifecycle management (create, list, delete) and sync tooling | |
| 29 | -- **Sync bridge** — mirror Fossil repos to GitHub/GitLab as downstream read-only copies | |
| 30 | - | |
| 31 | -New project = `fossil init`. No restart, no config change. Litestream picks it up automatically. | |
| 32 | - | |
| ---- | ||
| 33 | - | |
| 34 | -## Architecture | |
| 35 | - | |
| 36 | -``` | |
| 37 | -fossilrepo/ | |
| 38 | -├── server/ # Fossil server infra — Docker, Caddy, Litestream | |
| 39 | -├── sync/ # Fossil → GitHub/GitLab mirror | |
| 40 | -├── cli/ # fossilrepo CLI wrapper | |
| 41 | -└── docs/ # Architecture, guides | |
| 42 | -``` | |
| 43 | - | |
| 44 | -### Server Stack | |
| 45 | - | |
| 46 | -``` | |
| 47 | -Caddy (SSL termination, routing, subdomain per repo) | |
| 48 | - └── fossil server --repolist /data/repos/ | |
| 49 | - └── /data/repos/ | |
| 50 | - ├── projecta.fossil | |
| 51 | - ├── projectb.fossil | |
| 52 | - └── ... | |
| 53 | - | |
| 54 | -Litestream → S3/MinIO (continuous replication, point-in-time recovery) | |
| 55 | -``` | |
| 56 | - | |
| 57 | -One binary serves all repos. The whole platform is: repo creation + subdomain provisioning + Litestream config. | |
| 58 | - | |
| 59 | -### Sync Bridge | |
| 60 | - | |
| 61 | -Mirrors Fossil to GitHub/GitLab as a downstream copy. Fossil is the source of truth. | |
| 62 | - | |
| 63 | -Maps: | |
| 64 | -- Fossil commits → Git commits | |
| 65 | -- Fossil tickets → GitHub/GitLab Issues (optional, configurable) | |
| 66 | -- Fossil wiki → repo docs (optional, configurable) | |
| 67 | - | |
| 68 | -Triggered on demand or on schedule. | |
| 69 | - | |
| ---- | ||
| 70 | - | |
| 71 | -## Platform Vision (fossilrepos.com) | |
| 72 | - | |
| 73 | -GitLab model: | |
| 74 | -- **Self-hosted** — open source, run it yourself. fossilrepo is the tool. | |
| 75 | -- **Managed** — fossilrepos.com, hosted for you. Subdomain per repo, modern UI, billing. | |
| 76 | - | |
| 77 | -The platform is Fossil's built-in web UI with a modern skin + thin API wrapper + authentication. Not a rewrite — Fossil already does the hard parts. The value is the hosting and UX polish. | |
| 78 | - | |
| 79 | -Not being built yet — get the self-hosted tool right first. | |
| 80 | - | |
| ---- | ||
| 81 | - | |
| 82 | -## License | |
| 83 | - | |
| 84 | -MIT. |
| --- a/_old_bootstrap.md | |
| +++ b/_old_bootstrap.md | |
| @@ -1,89 +0,0 @@ | |
| 1 | # fossilrepo — bootstrap |
| 2 | |
| 3 | Omnibus-style installer for a self-hosted Fossil forge. One command gets you a full-stack code hosting platform: VCS, issues, wiki, timeline, web UI, SSL, and continuous backups — all powered by Fossil SCM. |
| 4 | |
| 5 | Think GitLab Omnibus, but for Fossil. |
| 6 | |
| ---- | |
| 7 | |
| 8 | ## Why Fossil |
| 9 | |
| 10 | A Fossil repo is a single SQLite file. It contains the full VCS history, issue tracker, wiki, forum, and timeline. No external services. No rate limits. Portable — hand the file to someone and they have everything. |
| 11 | |
| 12 | For teams running CI agents or automation: |
| 13 | - Agents commit, file tickets, and update the wiki through one CLI and one protocol |
| 14 | - No API rate limits when many agents are pushing simultaneously |
| 15 | - The `.fossil` file IS the project artifact — a self-contained archive |
| 16 | - Litestream replicates it to S3 continuously — backup and point-in-time recovery for free |
| 17 | |
| 18 | Fossil also has a built-in web UI (skinnable), autosync, peer-to-peer sync, and unversioned content storage (like Git LFS but built-in). |
| 19 | |
| ---- | |
| 20 | |
| 21 | ## What fossilrepo Does |
| 22 | |
| 23 | fossilrepo packages everything needed to run a production Fossil server into one installable unit: |
| 24 | |
| 25 | - **Fossil server** — serves all repos from a single process |
| 26 | - **Caddy** — SSL termination, subdomain-per-repo routing (`reponame.your-domain.com`) |
| 27 | - **Litestream** — continuous SQLite replication to S3/MinIO (backup + point-in-time recovery) |
| 28 | - **CLI** — repo lifecycle management (create, list, delete) and sync tooling |
| 29 | - **Sync bridge** — mirror Fossil repos to GitHub/GitLab as downstream read-only copies |
| 30 | |
| 31 | New project = `fossil init`. No restart, no config change. Litestream picks it up automatically. |
| 32 | |
| ---- | |
| 33 | |
| 34 | ## Architecture |
| 35 | |
| 36 | ``` |
| 37 | fossilrepo/ |
| 38 | ├── server/ # Fossil server infra — Docker, Caddy, Litestream |
| 39 | ├── sync/ # Fossil → GitHub/GitLab mirror |
| 40 | ├── cli/ # fossilrepo CLI wrapper |
| 41 | └── docs/ # Architecture, guides |
| 42 | ``` |
| 43 | |
| 44 | ### Server Stack |
| 45 | |
| 46 | ``` |
| 47 | Caddy (SSL termination, routing, subdomain per repo) |
| 48 | └── fossil server --repolist /data/repos/ |
| 49 | └── /data/repos/ |
| 50 | ├── projecta.fossil |
| 51 | ├── projectb.fossil |
| 52 | └── ... |
| 53 | |
| 54 | Litestream → S3/MinIO (continuous replication, point-in-time recovery) |
| 55 | ``` |
| 56 | |
| 57 | One binary serves all repos. The whole platform is: repo creation + subdomain provisioning + Litestream config. |
| 58 | |
| 59 | ### Sync Bridge |
| 60 | |
| 61 | Mirrors Fossil to GitHub/GitLab as a downstream copy. Fossil is the source of truth. |
| 62 | |
| 63 | Maps: |
| 64 | - Fossil commits → Git commits |
| 65 | - Fossil tickets → GitHub/GitLab Issues (optional, configurable) |
| 66 | - Fossil wiki → repo docs (optional, configurable) |
| 67 | |
| 68 | Triggered on demand or on schedule. |
| 69 | |
| ---- | |
| 70 | |
| 71 | ## Platform Vision (fossilrepos.com) |
| 72 | |
| 73 | GitLab model: |
| 74 | - **Self-hosted** — open source, run it yourself. fossilrepo is the tool. |
| 75 | - **Managed** — fossilrepos.com, hosted for you. Subdomain per repo, modern UI, billing. |
| 76 | |
| 77 | The platform is Fossil's built-in web UI with a modern skin + thin API wrapper + authentication. Not a rewrite — Fossil already does the hard parts. The value is the hosting and UX polish. |
| 78 | |
| 79 | Not being built yet — get the self-hosted tool right first. |
| 80 | |
| ---- | |
| 81 | |
| 82 | ## License |
| 83 | |
| 84 | MIT. |
| --- a/_old_bootstrap.md | |
| +++ b/_old_bootstrap.md | |
| @@ -1,89 +0,0 @@ | |
| ---- | |
| ---- | |
| ---- | |
| ---- | |
| ---- | |
D
fossil-platform/Dockerfile
-29
| --- a/fossil-platform/Dockerfile | ||
| +++ b/fossil-platform/Dockerfile | ||
| @@ -1,29 +0,0 @@ | ||
| 1 | -# Use an official Python runtime as a parent image | |
| 2 | -FROM python:3.9-slim | |
| 3 | - | |
| 4 | -# Set environment variables | |
| 5 | -ENV PYTHONDONTWRITEBYTECODE 1 | |
| 6 | -ENV PYTHONUNBUFFERED 1 | |
| 7 | - | |
| 8 | -# Set work directory | |
| 9 | -WORKDIR /app | |
| 10 | - | |
| 11 | -# Install system dependencies | |
| 12 | -RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| 13 | - fossil \ | |
| 14 | - default-mysql-client \ | |
| 15 | - postgresql-client \ | |
| 16 | - && rm -rf /var/lib/apt/lists/* | |
| 17 | - | |
| 18 | -# Install Python dependencies | |
| 19 | -COPY requirements.txt /app/ | |
| 20 | -RUN pip install --upgrade pip && pip install -r requirements.txt | |
| 21 | - | |
| 22 | -# Copy project | |
| 23 | -COPY . /app/ | |
| 24 | - | |
| 25 | -# Expose port | |
| 26 | -EXPOSE 5000 | |
| 27 | - | |
| 28 | -# Run the application | |
| 29 | -CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"] |
| --- a/fossil-platform/Dockerfile | |
| +++ b/fossil-platform/Dockerfile | |
| @@ -1,29 +0,0 @@ | |
| 1 | # Use an official Python runtime as a parent image |
| 2 | FROM python:3.9-slim |
| 3 | |
| 4 | # Set environment variables |
| 5 | ENV PYTHONDONTWRITEBYTECODE 1 |
| 6 | ENV PYTHONUNBUFFERED 1 |
| 7 | |
| 8 | # Set work directory |
| 9 | WORKDIR /app |
| 10 | |
| 11 | # Install system dependencies |
| 12 | RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 13 | fossil \ |
| 14 | default-mysql-client \ |
| 15 | postgresql-client \ |
| 16 | && rm -rf /var/lib/apt/lists/* |
| 17 | |
| 18 | # Install Python dependencies |
| 19 | COPY requirements.txt /app/ |
| 20 | RUN pip install --upgrade pip && pip install -r requirements.txt |
| 21 | |
| 22 | # Copy project |
| 23 | COPY . /app/ |
| 24 | |
| 25 | # Expose port |
| 26 | EXPOSE 5000 |
| 27 | |
| 28 | # Run the application |
| 29 | CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"] |
| --- a/fossil-platform/Dockerfile | |
| +++ b/fossil-platform/Dockerfile | |
| @@ -1,29 +0,0 @@ | |
D
fossil-platform/README.md
-65
| --- a/fossil-platform/README.md | ||
| +++ b/fossil-platform/README.md | ||
| @@ -1,65 +0,0 @@ | ||
| 1 | -# Fossil SCM-based GitHub/GitLab-like Platform | |
| 2 | - | |
| 3 | -This project aims to create a GitHub/GitLab-like platform based on Fossil SCM, providing a comprehensive solution for repository management, issue tracking, wikis, user management, and repository analytics. | |
| 4 | - | |
| 5 | -## Core Features | |
| 6 | - | |
| 7 | -- Version Control: Utilizes Fossil SCM for repository management | |
| 8 | -- Backend: Flask-based API for interacting with Fossil SCM and managing platform features | |
| 9 | -- Database: Supports both MySQL and PostgreSQL via feature flags | |
| 10 | -- Frontend: React-based web interface for viewing repositories, commits, issues, wikis, and user management | |
| 11 | -- Authentication & Permissions: OAuth (Google, GitHub) and custom JWT-based authentication | |
| 12 | -- CI/CD Integration: Optional continuous integration (feature flag enabled) | |
| 13 | -- Notification System: Email notifications and real-time WebSocket updates | |
| 14 | -- Extensibility: Plugin system for additional features | |
| 15 | - | |
| 16 | -## Technical Stack | |
| 17 | - | |
| 18 | -- Backend: Flask (Python) | |
| 19 | -- Frontend: React (JavaScript) | |
| 20 | -- Database: MySQL/PostgreSQL (configurable via feature flags) | |
| 21 | -- ORM: SQLAlchemy | |
| 22 | -- Authentication: OAuth 2.0, JWT | |
| 23 | -- Real-time Updates: WebSockets | |
| 24 | -- CI/CD: (Optional, configurable) | |
| 25 | - | |
| 26 | -## Feature Flags | |
| 27 | - | |
| 28 | -The platform uses feature flags to enable/disable certain functionalities: | |
| 29 | - | |
| 30 | -- `DB_TYPE`: Toggle between MySQL and PostgreSQL (e.g., `DB_TYPE=mysql` or `DB_TYPE=postgres`) | |
| 31 | -- `ENABLE_CICD`: Enable/disable CI/CD integration (e.g., `ENABLE_CICD=true`) | |
| 32 | -- `ENABLE_NOTIFICATIONS`: Enable/disable real-time WebSocket updates and email notifications (e.g., `ENABLE_NOTIFICATIONS=true`) | |
| 33 | -- `AUTH_TYPE`: Choose between OAuth-based login or JWT (e.g., `AUTH_TYPE=oauth` or `AUTH_TYPE=jwt`) | |
| 34 | - | |
| 35 | -## Getting Started | |
| 36 | - | |
| 37 | -1. Clone the repository | |
| 38 | -2. Set up the backend: | |
| 39 | - - Install Python dependencies: `pip install -r requirements.txt` | |
| 40 | - - Configure environment variables for feature flags | |
| 41 | - - Run the Flask server: `python app.py` | |
| 42 | -3. Set up the frontend: | |
| 43 | - - Navigate to the frontend directory: `cd frontend` | |
| 44 | - - Install npm packages: `npm install` | |
| 45 | - - Start the React app: `npm start` | |
| 46 | - | |
| 47 | -## Development Roadmap | |
| 48 | - | |
| 49 | -1. Set up Fossil SCM integration | |
| 50 | -2. Implement database abstraction with SQLAlchemy | |
| 51 | -3. Develop core Flask backend API | |
| 52 | -4. Create basic React frontend | |
| 53 | -5. Implement authentication and authorization | |
| 54 | -6. Add notification system | |
| 55 | -7. Develop plugin system for extensibility | |
| 56 | -8. Implement CI/CD integration | |
| 57 | -9. Comprehensive testing and documentation | |
| 58 | - | |
| 59 | -## Contributing | |
| 60 | - | |
| 61 | -Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests. | |
| 62 | - | |
| 63 | -## License | |
| 64 | - | |
| 65 | -This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. |
| --- a/fossil-platform/README.md | |
| +++ b/fossil-platform/README.md | |
| @@ -1,65 +0,0 @@ | |
| 1 | # Fossil SCM-based GitHub/GitLab-like Platform |
| 2 | |
| 3 | This project aims to create a GitHub/GitLab-like platform based on Fossil SCM, providing a comprehensive solution for repository management, issue tracking, wikis, user management, and repository analytics. |
| 4 | |
| 5 | ## Core Features |
| 6 | |
| 7 | - Version Control: Utilizes Fossil SCM for repository management |
| 8 | - Backend: Flask-based API for interacting with Fossil SCM and managing platform features |
| 9 | - Database: Supports both MySQL and PostgreSQL via feature flags |
| 10 | - Frontend: React-based web interface for viewing repositories, commits, issues, wikis, and user management |
| 11 | - Authentication & Permissions: OAuth (Google, GitHub) and custom JWT-based authentication |
| 12 | - CI/CD Integration: Optional continuous integration (feature flag enabled) |
| 13 | - Notification System: Email notifications and real-time WebSocket updates |
| 14 | - Extensibility: Plugin system for additional features |
| 15 | |
| 16 | ## Technical Stack |
| 17 | |
| 18 | - Backend: Flask (Python) |
| 19 | - Frontend: React (JavaScript) |
| 20 | - Database: MySQL/PostgreSQL (configurable via feature flags) |
| 21 | - ORM: SQLAlchemy |
| 22 | - Authentication: OAuth 2.0, JWT |
| 23 | - Real-time Updates: WebSockets |
| 24 | - CI/CD: (Optional, configurable) |
| 25 | |
| 26 | ## Feature Flags |
| 27 | |
| 28 | The platform uses feature flags to enable/disable certain functionalities: |
| 29 | |
| 30 | - `DB_TYPE`: Toggle between MySQL and PostgreSQL (e.g., `DB_TYPE=mysql` or `DB_TYPE=postgres`) |
| 31 | - `ENABLE_CICD`: Enable/disable CI/CD integration (e.g., `ENABLE_CICD=true`) |
| 32 | - `ENABLE_NOTIFICATIONS`: Enable/disable real-time WebSocket updates and email notifications (e.g., `ENABLE_NOTIFICATIONS=true`) |
| 33 | - `AUTH_TYPE`: Choose between OAuth-based login or JWT (e.g., `AUTH_TYPE=oauth` or `AUTH_TYPE=jwt`) |
| 34 | |
| 35 | ## Getting Started |
| 36 | |
| 37 | 1. Clone the repository |
| 38 | 2. Set up the backend: |
| 39 | - Install Python dependencies: `pip install -r requirements.txt` |
| 40 | - Configure environment variables for feature flags |
| 41 | - Run the Flask server: `python app.py` |
| 42 | 3. Set up the frontend: |
| 43 | - Navigate to the frontend directory: `cd frontend` |
| 44 | - Install npm packages: `npm install` |
| 45 | - Start the React app: `npm start` |
| 46 | |
| 47 | ## Development Roadmap |
| 48 | |
| 49 | 1. Set up Fossil SCM integration |
| 50 | 2. Implement database abstraction with SQLAlchemy |
| 51 | 3. Develop core Flask backend API |
| 52 | 4. Create basic React frontend |
| 53 | 5. Implement authentication and authorization |
| 54 | 6. Add notification system |
| 55 | 7. Develop plugin system for extensibility |
| 56 | 8. Implement CI/CD integration |
| 57 | 9. Comprehensive testing and documentation |
| 58 | |
| 59 | ## Contributing |
| 60 | |
| 61 | Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests. |
| 62 | |
| 63 | ## License |
| 64 | |
| 65 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. |
| --- a/fossil-platform/README.md | |
| +++ b/fossil-platform/README.md | |
| @@ -1,65 +0,0 @@ | |