Flow
Flow — Koder Git Forge
- *rea:*Developer Platform
- *ath:*
products/dev/flow/platform - *ind:*Self-hosted git forge, based on *orgejo*(community fork of Gitea)
- *agline:*From idea to deploy.
- *tatus:*Production —
flow.koder.dev· v1.0.15
Role in the stack
Flow is Koder's git forge — the canonical place to host code. Built on Forgejo and customized as Koder Flow, it runs at https://flow.koder.dev and hosts every Koder repository, including the monorepo itself at Koder/koder.
Features
- *ightweight*— runs on almost any machine, from a Raspberry Pi to a small cloud instance
- *roject management*— issues, pull requests, wikis, kanban boards
- *ublishing*— releases for software downloads, package registry (Docker, npm, and more), granular public access for private repos (public releases, binaries-only, public packages)
- *rganizations + team permissions* CI integration, code search, LDAP, OAuth
- *rivacy-first*— built with privacy in mind from the ground up
- *obile app*— native AndroidiOS client in `app` for on
thego access - *db
next integration*— shadowwrite/read to TiKV cluster (Phase 7.1, tenant1000019) - *udit logging*— structured audit log via
modules/kallfor admin actions - *igration manifest*— RFC-005:
migrations/v{TAG}.tomlat tag commit surfaces upgrade constraints in release UI and API - *eriodic backups (RFC
004)*—074 —[backups]scheduler + worker pool ship encrypted git mirrors to Google Drive *nd Microsoft OneDrive*(FLOWMultiUploaderdispatches bydest.Provider); Phase 4 added adaptive backoff on DriveGraph throttle signals (FLOW073), exponentialbackoff retry on transient failures (FLOW-075), admin CSV export of the policyrun audit trail (FLOW077), and *uided restore*that downloads any successful run's bundle and imports it as a fresh repo (FLOW076) — RFC-004 Phase 4 fully closed. - *sync tab counters (#084)*— IssuePR tabs fetch open counts via `GET /issuescount
+GET pullscountin parallel after page load; zero layout shift,arialabeltabfor screen readers.kodercounters.jstab-counter` CSS.+.kf - *tateLabel v2 (#083)*—
shared/state_label_v2.tmpldualpath template (9 state combos: 5 issue + 4 PR) with semantic CSS classes (`kfstate*US.ini`.).viewtitle.tmplmigrated. i18n keys inlocaleen - *ageLayout canonical shell (#082, shipped)*— Three
phase layout overhaul: (P1) Issue/PR right sidebar sticky + resizable (200–600px, localStorage); (P2) Code view left filetree sidebar — compact siblingfile listing with activefile highlight, width persistent (kf_code_sidebar_w), toggle persists viasessionStorage; (P3) Mobile fullscreen drawer —position: fixed; transform: translateX(-100%)slidein + animated backdrop,codeisMobileDrawer()JS branch. `kflayoutcode/kfsidebarsidebar/kfbackdroppageCSS classes;kflayout.js` handles both left (code) and right (issue) sidebars with directionaware drag. Follow-up: #092 (issue list sidebar + Playwright regression suite). - *CP server full surface (#094, #095, #096) — RFC
001 Phases 4–5 + RFC003 Phase 2*— HTTP+SSE transport mounted at/api/v1/mcp/{stream,message}with bearertoken auth + persession JSONRPC dispatch (30min idle TTL).scope ability gates and returnsresources/listenumeratesrepos://,meta://,credentials://; the credentials reader walks the repo→org→account hierarchy with perresolved_fromprovenance + auditlogged decrypt viaSchema inputs, scopecreds.Reveal.tools/list+tools/callship the four write tools (create_issue,comment_issue,create_pr,request_review) with JSONmismatch ↔ MCP error mapping, andwrapped tool failures so the LLM can read and react without aborting. In-process tests cover SSE handshake, URI parsing, dispatch error paths, and validation gates.isError - *redential hierarchy + abilities (#098) — RFC
003 Phase 3*—only; orgmember; repomember). Scopes the requester cannot see are silently skipped (crossservices/credentials.FetchAuthorizedwraps the existing walk with anAbilitiesCheckerinjection point;MembershipAbilities{}is the default (admin sees all; account=ownertenant returns 404, not 403, per `specs/multitenancycontract.kmd).Provenance.ResolvedFrom()returns the canonicaltypeid` string for API/MCP responses. - *penTelemetry HTTP + manual spans (#099)*—
modules/tracingwraps the main HTTP mux withotelhttp(noop whenscoped tracers in[tracing].enabled=false); packagemodules/kdbandservices/mcp/handler.goemit spans on every shadow op and JSONRPC dispatch with stable attribute keys (check paths are skipped viakdb.op,mcp.method). HealthWithFilter. Settings live in[tracing](enabled / servicename / otlpendpoint / otlpinsecure / excludepaths). OTLP exporter wiring is deferred to #103. - *ebrand configs Phase 2 (#100) — RFC
005*— Build/contrib sweep aligns the deployed binary name: `Makefile EXECUTABLE = koderflow(removes the transitionallnfflowshim, fixes a stalemain.Koder FlowVersionldflag with an invalid space),.air.tomlreloadskoder, IDE/autocompletion/legal samples updated, systemd-unit socket-activation comments now referencekoderflow.main.socket`. Outof-scope items (models/gitea_migrationspackage path,gitea_*Prometheus metric names,GITEA_ROOT/GITEA_CONFenv vars, Dockerfile WORKDIR) tracked in #102. - *uilt
in metalint Action (#097) — RFC002 Phase 3*— `koderflowmeta-lint@v1registered inmodulesactionsbuilt-in registry (rewritesuses:→ in-processrun: koderflow actions metalint).servicesmeta.LintFilesystemwalksmetaand surfaces structural findings (missing/malformed frontmatter, invalid status, intra-layer duplicates of(type, name); cross-layer = valid override). CLI emits GitHub-Actions-compatible::error fileX,lineY::msgannotations and exits 1 when findings exist. Template workflow shipped atoptionsworkflowsmeta-lint.yml`. - *TLP gRPC exporter wiring (#103)*—
modules/tracing.Init()instantiatessdktrace.NewTracerProviderwithotlptracegrpcclient when[tracing].enabled=true && [tracing].otlp_endpoint != ""; resource attrs carryservice.name=koder-flow,service.version=<AppVer>,deployment.environment=<RunMode>. Sampling via[tracing].sample_ratio(default 1.0, withAlwaysSampleNeverSampleshortcuts at the extremes). `cmdweb.gograceful-shutdowns the provider aftergraceful.Done()` so in-flight spans flush to the collector. Otelsdk + exportersotlpotlptraceotlptracegrpc promoted to direct deps. - *ockerfile WORKDIR rebrand (#102 sub
1) — RFC005 Phase 3 begin*—/app/gitea/→/app/koder-flow/in Dockerfile + Dockerfile.rootless;xx-verify koder-flow(regression fix — the Forgejoera `xxverify giteawould not find the binary after #100'sEXECUTABLE = koderflow` flip); inverted backwardcompat symlink (ln -s koder-flow giteaso legacy scripts still work);Makefile reproduce-buildconsumes new path. Env vars + path mounts + Prometheus metric names + Go package paths remain in sub-tickets #104–#107. - *koder
flowfmtsubcommand (#102 sub-5 / #107)** —buildcodebatchprocess.goships akoderflowfmtsubcommand formake fmt; the legacygiteafmt` invocation continues to work via dualcase (case "koder-flow-fmt", "gitea-fmt":) for one release. Bonus: corrected a stale `koder.devdevflowenginebuildcodeformat` import path (postRFC003 location). - *ackage paths rename (#102 sub
2 / #104)*—flow.org...models/gitea_migrations/→models/koder_flow_migrations/(git mv preserves history). Package declaration updated in the 3 root files; 58 files swept via sed for both prefix styles (`koderlegacy andkoder.devproductsdevflowengine...canonical). Symbol references in doctor/cmd/routers/tests + string literalfixturesDirpath + configs (Makefile, .air.toml, .golangci.yml, .semgrep, coverage-helper, code-batch-process). Migration history is tracked by integeridNumber` — no data risk from the Go rename. - *nv vars rename (#102 sub
3 / #105)*—shot deprecation warning when the legacy name is read.GITEA_ROOT/CONF/RUN_MODE/WORK_DIR/CUSTOM/TEMP/APP_INI*→KODER_FLOW_*with a onesetting.GetenvAliased(canonical, legacy)is the new helper consumed bysetting/{setting,path}.go,base/tool.go::SetupGiteaRoot, andtests/test_utils.go::InitTest. Makefile's 30 testtarget invocations now passdisk path values so existing mounted volumes still work.KODER_FLOW_ROOT/CONF; Dockerfile + Dockerfile.rootless ENV names useKODER_FLOW_*while keeping/var/lib/gitea//data/giteaas on - *rometheus metrics dual
emit (#102 sub4 / #106)*—modules/metrics/collector.gonow uses adualDesc{canonical, legacy}helper so every one of the 27 metrics is published under BOTH the canonicalkoder_flow_prefix and the legacygitea_prefix during the rebrand transition. The legacy descriptors carry aDEPRECATEDsuffix in their# HELPline so scrapers see the migration notice. Grafana dashboards incontrib/flow-monitoring-mixin/are migrated to querykoder_flow_*(config + jsonnet locals + dashboard UID renamed). Thegitea_*emission stays for a 2release deprecation window before removal. *FC005 Phase 3 umbrella (#102) is now fully shipped — all 5 sub-tickets complete.* - *CP createissue labels + assignees (#108)*— extends the MCP `createissue
tool input schema withlabels: string[]andassignees: string[]. Labels resolve throughissuesmodel.GetLabelIDsInRepoByNames(fail loudly when any name doesn't exist on the repo — agentic callers should not silently lose triage data); assignees resolve throughusermodel.GetUserByNameper login. Both inputs dedup on the way in via the package-localdedupStrings. Schema + Go struct shape locked by a regression test intestsregression004mcpcreateissuelabelsassigneestest.go`. - *CP per
token rate limit (#109)*— wires the previouslydormantsetting.MCP.MaxCallsPerMinute(default 1000) into a tokenbucket perplane method; control-plane (Principal.TokenIDinservices/mcp/ratelimit.go.Handler.DispatchconsultsAllow(tokenID)before any datainitialize,ping, `notifications