No description
  • Go 89.8%
  • HTML 5.9%
  • Python 2.4%
  • CSS 1.4%
  • JavaScript 0.4%
  • Other 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-06 21:21:28 +02:00
.forgejo ci: add Forgejo checks (#3) 2026-09-04 23:28:31 +02:00
cmd/fjomp idea/0001-agent-mediated-authoring (#68) 2026-09-06 02:10:07 +02:00
docs Improve idea reading and implementation records (#69) 2026-09-06 21:17:27 +02:00
internal Wrap long commit references in idea prose (#70) 2026-09-06 21:21:28 +02:00
scripts Improve idea reading and implementation records (#69) 2026-09-06 21:17:27 +02:00
.forge chore: initialize Fjomp repository 2026-09-04 23:15:00 +02:00
.gitignore chore: initialize Fjomp repository 2026-09-04 23:15:00 +02:00
go.mod Improve idea reading and implementation records (#69) 2026-09-06 21:17:27 +02:00
go.sum Improve idea reading and implementation records (#69) 2026-09-06 21:17:27 +02:00
Makefile chore: add common developer commands (#5) 2026-09-04 23:23:59 +02:00
README.md feat: add project archival (#38) 2026-09-05 19:42:38 +02:00
todo.md chore: initialize Fjomp repository 2026-09-04 23:15:00 +02:00

Fjomp

Fjomp is a small, single-user project-management application built as a Go monolith with server-rendered HTML, HTMX, and SQLite.

The product scope, architectural decisions, delivery milestones, and issue workflow are documented in todo.md.

Development status

The repository is in its bootstrap milestone. The initial server, configuration, automation, contribution templates, and developer tooling are being established.

Development

Prerequisites:

  • Go 1.26 or newer
  • GNU Make 4 or newer
  • forge 0.10 or newer for Forgejo issues and pull requests

Format the code with:

make fmt

Run all baseline checks with:

make check

The individual fmt-check, vet, test, and build targets are also available when running a single check is more convenient.

Development follows an issue-to-branch-to-pull-request workflow. Keep main deployable and scope each branch to one Forgejo issue.

Configuration

Fjomp reads runtime configuration from the environment:

Variable Default Description
FJOMP_HTTP_ADDRESS 127.0.0.1:8091 TCP address used by the HTTP server.
FJOMP_DATABASE_PATH fjomp.db SQLite database path. Set this to a persistent absolute path in production.
FJOMP_SHUTDOWN_TIMEOUT 10s Maximum time allowed for graceful HTTP shutdown.

Invalid values are reported at startup before the server begins listening.

Every SQLite connection enables foreign-key enforcement and uses write-ahead logging. Connections wait up to 5 seconds for a database lock before returning a busy error. Fjomp verifies these settings when opening the database and stops startup if they cannot be applied.

Operational probes

GET /healthz reports process liveness. GET /readyz reports whether all registered dependencies are available. Both endpoints return stable UTF-8 plain-text responses and never include dependency error details.

HTTP security policy

All responses opt out of MIME sniffing and framing, use a same-origin referrer policy, isolate the browsing context and resources to the same origin, and use a content security policy limited to same-origin resources. Handler panics are logged with their request ID and converted to a generic HTTP 500 response.

The browser project-creation route relies on the v1 tailnet-only access boundary and does not issue application CSRF tokens. Keep Fjomp behind the tailnet restriction; add same-origin CSRF protection before exposing mutating HTML routes publicly or supporting multiple users.

Browser project mutations include a one-time server-issued submission token and a same-origin HTMX-compatible enhancement (/static/fjomp-htmx.js), so browser retries cannot repeat a successful submission through one rendered form. Tokens expire after ten minutes and the in-memory token registry is capped at 1024 entries, evicting the oldest entry when full; this state is intentionally single-process and is not a substitute for durable idempotency across replicas.

Archiving is an explicit POST /projects/{id}/archive action. A normal browser response redirects to the active-project list; an HTMX response is an empty successful fragment so the archived project is removed from its active list. Archived projects remain directly viewable by GET /projects/{id} but are no longer returned by the active list, and repeating the action with a fresh valid form token is a successful no-op.