GitW3 — MetaState git forge, based on Forgejo (GPLv3)
  • Go 81.1%
  • go-html-template 10.7%
  • JavaScript 2.7%
  • CSS 2%
  • TypeScript 1.9%
  • Other 1.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-31 14:37:19 +00:00
.devcontainer chore: rename devcontainer name (#12356) 2026-05-01 00:20:15 +02:00
.forgejo Update actions/setup-forgejo to v3.2.3 (forgejo) (#13154) 2026-06-21 03:42:54 +02:00
.github/workflows feat(branding): apply GitW3 branding at build time 2026-08-04 09:58:47 +03:00
.semgrep [v16.0/forgejo] chore(refactor): add getter/setter to APIContext data members (#13213) 2026-06-27 18:27:57 +02:00
.w3ds chore: update platform visibility 2026-08-31 14:37:19 +00:00
assets chore: remove EXIF stripping capability due to usage of AGPL licensed exif-terminator library (#13105) 2026-06-17 16:16:35 +02:00
branding feat(branding): default to light, and apply the MetaState palette 2026-08-05 16:23:13 +03:00
build fix: introduce lint-single-response to prevent control flow continuing past a ctx.Error(...)-style method (#13087) 2026-06-14 17:06:03 +02:00
cmd feat: publish signed deployments 2026-08-30 04:50:04 +08:00
contrib fix(coverage): Integration tests don't run with coverage (#12978) 2026-06-13 23:25:38 +02:00
custom/conf fix: make W3DS login mandatory 2026-08-31 20:06:42 +08:00
docker style: tidy platform files 2026-08-29 18:27:13 +08:00
docs/gitw3 fix: make W3DS login mandatory 2026-08-31 20:06:42 +08:00
models feat: sync W3DS identities and derive platform slugs 2026-08-31 17:51:15 +08:00
modules fix: make W3DS login mandatory 2026-08-31 20:06:42 +08:00
options feat: sync W3DS identities and derive platform slugs 2026-08-31 17:51:15 +08:00
public [v16.0/forgejo] chore: Update link to policy in security.txt (#13475) 2026-07-16 08:06:16 +02:00
release-notes [v16.0/forgejo] feat: render OSC 8 sequences safely (#13324) 2026-07-06 15:42:02 +02:00
release-notes-published chore(release-notes): Forgejo v15.0.3 (#13033) 2026-06-10 07:53:28 +02:00
releases/images [DOCS] RELEASE-NOTES.md 2024-02-05 14:44:32 +01:00
routers fix: make W3DS login mandatory 2026-08-31 20:06:42 +08:00
services feat: sync W3DS identities and derive platform slugs 2026-08-31 17:51:15 +08:00
templates feat: sync W3DS identities and derive platform slugs 2026-08-31 17:51:15 +08:00
tests fix: make W3DS login mandatory 2026-08-31 20:06:42 +08:00
tools chore: move backend-checks CI checks to Makefile: make pr-go (#11053) 2026-02-17 02:41:40 +01:00
web_src feat: sync W3DS identities and derive platform slugs 2026-08-31 17:51:15 +08:00
.air.toml chore: rename 'migrations' to 'gitea_migrations' 2025-10-14 14:40:49 -06:00
.deadcode-out [v16.0/forgejo] chore(refactor): remove GetX redundant accessors and use X in services/context/api.go (#13217) 2026-06-27 22:44:01 +02:00
.dockerignore fix: Dockerfile should re-use bindata files when possible 2025-06-13 14:00:57 +02:00
.editorconfig i18n(next): convert indention style to tabs: en, editorconfig (#10661) 2026-01-02 05:56:48 +01:00
.envrc.example Make direnv optional to let developers use their own direnv configuration 2024-11-06 20:34:49 +01:00
.gitattributes Add interface{} to any replacement to make fmt, exclude *.pb.go (#30461) 2024-04-15 20:01:36 +02:00
.gitignore chore: ignore publisher binary 2026-08-29 20:50:37 +08:00
.gitmodules cleanup(tests): remove manual testing submodule 2024-04-21 10:13:51 +02:00
.gitpod.yml Remove sqlite-viewer and using database client (#31223) 2024-06-09 11:13:39 +02:00
.golangci.yml chore(refactor): run routers/api/v1/permissions/tests from tests/integration (#13157) 2026-06-21 21:43:57 +02:00
.ignore Add /options/license and /options/gitignore to .ignore (#30219) 2024-04-07 15:40:31 +02:00
.mailmap Add .mailmap with aliases for Unknwon (github.com/Unknwon) 2024-08-14 08:26:16 -04:00
.markdownlint.yaml Update JS dependencies (#28537) 2023-12-30 05:29:03 +00:00
.mockery.yml feat: evaluate action job's if on the server-side when possible (#13030) 2026-06-16 00:02:57 +02:00
.node-version Update nodejs to v24.17.0 (forgejo) (#13144) 2026-06-20 02:23:03 +02:00
.npmrc Upgrade to npm lockfile v3 and explicitely set it (#23561) 2023-03-18 19:38:10 +01:00
.release-notes-assistant.yaml chore: fix rna config (#12304) 2026-04-28 18:56:52 +02:00
.spectral.yaml Add spectral linter for Swagger (#20321) 2022-07-11 18:07:16 -05:00
.yamllint.yaml fully replace drone with actions (#27556) 2023-10-11 06:39:32 +00:00
BSDmakefile feat: Makefile & BSDmakefile changes (#7455) 2025-04-27 10:04:32 +00:00
CODEOWNERS chore: update codeowners (#12844) 2026-05-31 14:42:17 +02:00
CONTRIBUTING.md chore: mention CoC and highlight AI agreement in CONTRIBUTING.md (#12867) 2026-06-01 16:17:35 +02:00
DCO Remove address from DCO (#22595) 2023-01-24 18:52:38 +00:00
Dockerfile Update data.forgejo.org/oci/golang Docker tag to v1.26 (forgejo) (#11662) 2026-03-13 08:17:21 +01:00
Dockerfile.rootless Update data.forgejo.org/oci/golang Docker tag to v1.26 (forgejo) (#11662) 2026-03-13 08:17:21 +01:00
eslint.config.mjs Update linters (forgejo) (#11627) 2026-03-12 18:27:43 +01:00
flake.lock chore: update flake.lock; add gnupg as dependency (#12497) 2026-05-09 23:53:35 +02:00
flake.nix refactor: Simplify flake.nix (#9805) 2025-10-22 19:09:11 +02:00
go.mod feat: add platform manifest publisher 2026-08-29 18:17:16 +08:00
go.sum Update module github.com/go-ldap/ldap/v3 to v3.4.14 (v16.0/forgejo) (#13657) 2026-07-28 05:59:08 +02:00
LICENSE Forgejo v9.0 is GPLv3+ 2024-08-22 09:09:29 +02:00
main.go fix: do not mix urfave v2 with urfave v3 (#8168) 2025-06-12 15:38:03 +02:00
Makefile feat: show platform publication status 2026-08-29 18:23:45 +08:00
manifest.scm chore: add delve Go debugger to Guix manifest (#12662) 2026-05-22 11:09:11 +02:00
package-lock.json feat: sign PPA release applications 2026-08-30 01:35:48 +08:00
package.json feat: sign PPA release applications 2026-08-30 01:35:48 +08:00
playwright.config.ts chore(e2e): refactor "Toggle visibility" org-members test (#12871) 2026-06-02 14:52:01 +02:00
README.md feat: add native w3ds login 2026-08-29 19:02:11 +08:00
release-notes-assistant.sh fix(rna): prioritize breaking changes without a feature or bug label over non-breaking changes (#12124) 2026-04-17 15:24:58 +02:00
RELEASE-NOTES.md chore(release-notes): fix release notes of chroma update in v8.0.0 2025-10-05 17:10:38 +05:00
shell.nix chore: update flake.lock; add gnupg as dependency (#12497) 2026-05-09 23:53:35 +02:00
stylelint.config.js chore: enforce RTL-friendly logical CSS properties with a linter (#12491) 2026-05-11 00:20:45 +02:00
tailwind.config.js chore(ui): change /devtest to /-/demo (#11019) 2026-01-26 13:12:25 +01:00
tsconfig.json feat(ui): replace Monaco with CodeMirror (#10559) 2026-01-04 23:52:33 +01:00
vitest.config.ts feat(ui): replace Monaco with CodeMirror (#10559) 2026-01-04 23:52:33 +01:00
webpack.config.js chore(ui): change /devtest to /-/demo (#11019) 2026-01-26 13:12:25 +01:00

GitW3

GitW3 is MetaState's self-hosted Git forge. It is a fork of Forgejo, rebranded for the MetaState / W3DS ecosystem.

Relationship to Forgejo

GitW3 tracks Forgejo releases. Everything that makes GitW3 GitW3 is deliberately confined to a thin layer on top of upstream:

  • Branding — application name, logo, colour scheme, templates and locale strings. Applied by branding/apply.sh, which rewrites upstream files in the working tree immediately before make build. Those rewrites are never committed, so the tracked diff against Forgejo stays empty. Forgejo's own custom/ mechanism cannot do this job: the Docker image points GITEA_CUSTOM at a volume, so the repository's custom/ directory is never read in a container, and the assets that need overriding are embedded into the binary at build time by the bindata tag anyway.
  • Nothing else, for now. In particular, W3DS login is not implemented in this fork. It is provided by a separate OIDC bridge service and wired up through Forgejo's built-in OAuth2 authentication sources, so it needs no change to this codebase.

Keeping the patch surface near zero is the whole strategy. Every line we diverge from upstream is a line that can conflict when the next Forgejo security release has to be merged.

Note that the Go module path is forgejo.org and the built binary is named gitea upstream. We override the binary name at build time (EXECUTABLE=gitw3) and leave both alone in the source — renaming them for real would mean touching thousands of lines for no user-visible gain.

Branches

Branch Owner Purpose
main us GitW3. Branched from upstream v16.0.2; carries our commits.
forgejo upstream Forgejo's development branch, mirrored verbatim. Do not commit here.
v*/forgejo upstream Forgejo release branches, mirrored verbatim. Do not commit here.
v* (tags) upstream Forgejo release tags, mirrored verbatim.
gitw3-v* (tags) us GitW3 releases.

Upstream refs are refreshed daily by .github/workflows/upstream-sync.yml, which only ever writes to upstream-owned refs and never to main.

Keeping up with upstream

See docs/gitw3/upstream-sync.md for the merge procedure.

This is not optional maintenance. Forgejo ships security releases regularly — v16.0.2 and v15.0.6 both landed on 2026-07-30 — and an un-upgraded forge exposed to the internet is a liability.

Building

Requires Go (version pinned in go.mod) and Node (pinned in .node-version).

make deps-frontend
./branding/apply.sh
EXECUTABLE=gitw3 TAGS="bindata sqlite sqlite_unlock_notify" make build
./gitw3 --version
git checkout -- cmd/ docker/ modules/ options/ public/ routers/ services/ templates/ web_src/

The branding step is not optional: without it make build produces a binary that still calls itself Forgejo. The last line puts the working tree back — see branding/README.md.

Container images are published to ghcr.io/ensombl/gitw3.

Local development

For iterating on code, use the live-reload dev server instead of the full build above:

make deps-frontend
TAGS="sqlite sqlite_unlock_notify" GITEA_RUN_MODE=dev make watch

make watch runs the frontend (webpack --watch) and backend (air, which rebuilds and restarts on .go/.tmpl changes) together. TAGS must be set explicitly here and include sqlite: unlike the release build above, make watch's backend target does not set it, so without it the install wizard won't offer SQLite3 as a database option.

First run serves the install wizard at http://localhost:3000. If that port is taken, set [server] HTTP_PORT in custom/conf/app.ini — environment variable overrides (GITEA__server__HTTP_PORT) are not read this early, only app.ini is. SQLite needs no other setup.

Testing W3DS login locally

GitW3 owns an always-visible Continue with W3DS button and the stable /user/login/w3ds entry point. The cryptographic wallet flow remains in the separate w3ds-oidc-bridge implemented by the MetaState team in MetaState-Prototype-Project/prototype#1102. The bridge is wired into Forgejo as an OAuth2 authentication source named exactly W3DS; GitW3 keeps the native button visible and reports a clear configuration error when that source is absent.

To exercise the complete flow locally:

  1. Run the OIDC bridge service (out of scope for this repo) and note its client ID, client secret, and .well-known/openid-configuration discovery URL.
  2. Register it as an authentication source. The name must be exactly W3DS — it's baked into the bridge's redirect URI as <ROOT_URL>/user/oauth2/W3DS/callback:
    ./gitea admin auth add-oauth \
      --name "W3DS" \
      --provider "openidConnect" \
      --key "<client id>" \
      --secret "<client secret>" \
      --auto-discover-url "http://<bridge-host>/.well-known/openid-configuration" \
      --scopes "openid" --scopes "profile" --scopes "email"
    
    The profile/email scopes are needed so Forgejo gets a real username/email back instead of falling back to the OIDC sub claim and a synthetic @w3ds.invalid address.
  3. Add the following to custom/conf/app.ini and restart (app.ini is only read at process startup, so this needs a restart of make watch, not just a hot-reload):
    [oauth2_client]
    ENABLE_AUTO_REGISTRATION = true
    ACCOUNT_LINKING = login
    USERNAME = nickname
    REGISTER_EMAIL_CONFIRM = false
    
    Without ENABLE_AUTO_REGISTRATION, Forgejo shows a manual "Complete new account" step on every first-time OAuth2 login instead of silently provisioning the account, which is the intended production behaviour.

Testing code sync locally

Code sync isn't part of this codebase either — a separate forgejo-code-sync service resolves each push's author via the W3DS link above and writes their commits into their eVault, using a Forgejo system webhook and the admin Users API. To exercise it locally:

  1. Create a dedicated site-admin service account for the sync service — not a shared human admin's login, since its token can read every account's login_name and every private repo's content.
  2. Generate two PATs on that account:
    • read:user,read:repository scopes, for the service's continuous use (FORGEJO_ADMIN_TOKEN).
    • write:admin scope, for the one-time webhook registration below (FORGEJO_PROVISIONING_TOKEN) — optional, falls back to the token above, but keeps the always-running token's blast radius smaller.
  3. If the sync service's webhook URL resolves to loopback relative to this instance (true for local dev, not for a real deployment), add the following to custom/conf/app.ini and restart:
    [webhook]
    ALLOWED_HOST_LIST = loopback
    
  4. Run the sync service's registration script once (idempotent, safe to re-run on redeploy) to register the system webhook via POST /api/v1/admin/hooks.
  5. Two things about that endpoint worth knowing, even though the script already handles both:
    • active must be sent as true explicitly — it defaults to false, and a hook created without it looks completely normal (201, listed in Site Administration) but never delivers anything.
    • config.is_system_webhook must be the literal string "true" — omit it and GitW3 silently creates a "default" webhook instead: invisible to GET /admin/hooks, and it only applies to repos created after it's added, never retroactively to existing ones.
    • Rotating the webhook secret needs the hook deleted and recreated, not PATCHed — PATCH /admin/hooks/{id} silently ignores a changed config.secret.
  6. Verify after registering: Site Administration → Webhooks shows the hook with Active on, not just present, and a "Test Delivery" (or a real push) actually reaches the service.
  7. Don't register the webhook twice — two system webhooks pointed at the same URL produce two envelopes per push; the sync service has no deduplication for that case by design.

Platform onboarding and Marketplace publication

The New action now offers guided W3DS platform creation. New-platform repositories receive a versioned .w3ds/platform.json, optional browser-generated identity keys, and the documented W3DS AI skill quick install. A companion process provisions the platform eName and keeps its Marketplace PlatformProfile synchronized from the default branch.

See docs/gitw3/platform-onboarding.md for the manifest contract, service deployment, system webhook, credentials, status integration, and failure behavior.

Licence

Forgejo is GPL-3.0-or-later, and so is GitW3. See LICENSE.

The Forgejo branding is not covered by that licence and is not ours to reuse: the logo is CC BY-SA 4.0 by Caesar Schinas, and the Jo mascot is CC BY 4.0 by David Revoy. The attribution exemption on the logo is granted to the Forgejo project only. GitW3 branding assets must therefore be original work, not derivatives of Forgejo's.

Upstream