DEVELOPER PLATFORM · GO

Forge

A GitLab-inspired collaboration platform in Go that reviews and merges real GitHub and GitLab pull requests, and refuses to merge anything it can't prove is safe.

RoleDesign & implementation
TypeIndependent project
StackGo, PostgreSQL, OAuth + PKCE, Server-Sent Events
View source on GitHub ↗

Product context

Code collaboration with a real policy boundary.

What Forge is

Forge is a developer collaboration control plane, not a replacement Git host. Teams can connect GitHub or GitLab repositories, then manage projects, issues, milestones, reviews, approvals, simulated pipelines, notifications, and audit history in one Go application. Source code remains with the selected provider.

The hard part

A merge should depend on fresh, authoritative state—not just what a browser last displayed. Forge checks the reviewed commit, distinct reviewer identities, author exclusion, unresolved discussions, required approvals, provider mergeability, and provider CI before a maintainer can request a merge.

Design principle

Any operation with real consequence needs a recoverable trail. Merge intent is persisted before a provider call, webhook deliveries are verified and deduplicated, and sensitive actions are represented in a separate append-only audit record.

Platform modules

Developer workflows with state that can be explained.

Forge is deliberately designed around the moments where collaboration systems usually become risky: access changes, external events, reviews, pipelines, and the final merge.

01 / ACCESS

Organizations, teams & roles

Email/password accounts use bcrypt hashes; session cookies are HttpOnly, SameSite, and expire after twelve hours. Organization roles are inherited by projects, while project roles can raise—but never weaken—existing access. The model protects the final organization owner and stops archived projects from accepting work mutations.

02 / WORK

Projects, issues & milestones

Teams create and own projects with issues that can be searched by title, description, or ID, then combined with status, assignee, label, and milestone filters. Sort by date or title, with project filters retained during the session. Milestones track due dates and completion progress, expose their open issues, and can be closed or reopened. The relational model keeps this workflow structured instead of treating the dashboard as an unfiltered activity feed.

03 / REVIEW

Provider-backed merge requests

GitHub and GitLab authorization-code OAuth uses state validation and PKCE. Imported repository metadata stays connected to its provider; Forge can link an existing remote request, load its diff, collect line comments and review decisions, then fetch fresh remote state before allowing a merge attempt.

04 / POLICY

Merge gates & pipeline state

Approvals are invalidated by a new head commit, authors cannot approve their own work, and provider identities count once. Required approvals, resolved review discussions, current provider CI, and mergeability form the real gate. Forge’s queued → running → passed/failed pipelines are simulations—not hosted CI runners—and demonstrate persisted state recovery and incremental logs.

05 / INTEGRATE

External events without blind trust

GitHub webhooks are validated with HMAC-SHA256; GitLab deliveries use a secret token. Deliveries are persisted per project to prevent reprocessing and linked merge requests are flagged for refresh rather than overwritten by an out-of-order payload. This matters because a webhook is a useful signal, but it is not automatically the final authority on a provider’s state.

  • OAuth / PKCERepository import starts with provider authorization, state checks, and a PKCE verifier.
  • Webhook guardEach delivery is authenticated and deduplicated before it can affect project state.
  • Provider truthRefresh, diff loading, review submission, and merging fetch provider state again.
06 / TRACE

Live state, activity & auditability

Authenticated server-sent events deliver live changes with heartbeats and client reconnect behavior. Normal activity records describe the project timeline; sensitive operations—such as membership changes, settings, imports, approvals, merges, and webhook-secret rotation—also write to a separate hash-linked audit log. PostgreSQL triggers reject edits or deletions to those event tables, preserving append-only behavior below the application layer.

System concerns

Go, PostgreSQL, OAuth with PKCE, signed webhooks, server-sent events, bcrypt, append-only audit trails — authorization, external-system boundaries, merge safety, and explainable operations.

PROCESS BOUNDARY

The app keeps working state in one active process and persists changes with database revision checks to reject stale writers. It is intentionally a single-instance deployment today—not a horizontally scaled service with distributed cache invalidation.

PERSONAL PRODUCT

Forge makes the decision path around a merge visible: who changed what, which checks are current, what is still blocking, and which system remains authoritative.

Architecture

Provider truth stays authoritative.

BROWSER / SSEGO SERVERPOSTGRESQLGITHUB / GITLABwebhooks → refresh

Each mutation validates permissions, writes in a PostgreSQL transaction, then publishes an SSE invalidation so clients refetch.

Failure modes & recovery

Never merge on a stale assumption.

What goes wrongWhat the system does
Someone pushes after approvalApprovals invalidated; merge carries the reviewed SHA and is rejected by the provider.
Network drops during mergeMerge intent already persisted; no automatic retry; refresh reconciles with the provider.
Webhook arrives out of orderOnly flags a refresh; authoritative state is re-read from the provider.
Duplicate webhook deliveryDelivery ID accepted once per provider/project.
Two writers modify the same stateDatabase revision check rejects the stale writer instead of overwriting.
Forged webhookRejected: HMAC or secret-token validation fails.

Boundaries

What Forge deliberately does not do.

  • Single application writer; no distributed merge coordination.
  • OAuth tokens are lost on restart; no refresh-token rotation; GitLab.com only, not self-managed.
  • Reviews live in Forge and aren't published as native provider reviews.
  • CI runner is simulated and never counts as real CI for merge gates.

What I'd change next

Next evolution.

  • Support multiple instances: distributed cache invalidation, shared rate limits, and a merge lock.
  • Encrypted, persistent OAuth tokens with refresh rotation.
  • Publish reviews back to the provider as native reviews.
  • Anchor audit hash chains externally so they're tamper-evident even against a database owner.