Compare commits

...

16 Commits

Author SHA1 Message Date
jmiller f3ce51d629 Merge pull request 'chore: final version update' (#560) from chore/final-version into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
2026-06-07 02:21:06 +00:00
Jonathan Miller 1f505b48c7 chore: update wiki version to v1.26.1-moko.06.11.01
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m49s
2026-06-06 21:20:37 -05:00
jmiller afda7abcbe Merge pull request 'fix(settings): remove duplicate description from manifest' (#559) from fix/manifest-desc-dedup into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
2026-06-07 02:08:31 +00:00
Jonathan Miller 798d9c3ae0 fix(settings): remove duplicate description from manifest page
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 9s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m40s
Description is already managed in repo general settings. The manifest
now reads it from the repository object instead of a separate form field.
2026-06-06 21:07:39 -05:00
jmiller e0f22dd397 Merge pull request 'chore: wiki version update' (#558) from chore/wiki-version-update into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
2026-06-07 01:57:10 +00:00
Jonathan Miller ecda05aa46 chore: update wiki version to v1.26.1-moko.06.11.00 and roadmap
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m26s
2026-06-06 20:56:25 -05:00
jmiller 9eadade2f4 Merge pull request 'feat: Issue Types settings + MCP SSE + npm auto-publish' (#557) from feat/type-settings-mcp-sse-npm into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
2026-06-07 00:53:45 +00:00
Jonathan Miller 2cc4f7c047 feat: org settings for Issue Types + MCP SSE hosted + npm auto-publish
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m9s
- Org settings page for managing Issue Type definitions (CRUD)
- MCP SSE endpoint deployed at git.mokoconsulting.tech/mcp/
- npm auto-publish workflow on MCP source changes to main
2026-06-06 19:52:55 -05:00
jmiller 74a5fe2b80 Merge pull request 'fix(auth): login form with OAuth on all error pages' (#556) from fix/error-pages-login into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Site Health (push) Has been skipped
2026-06-06 23:26:43 +00:00
Jonathan Miller 50c472991a fix(auth): add login form with OAuth to all error pages
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Failing after 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m33s
- 403: OAuth buttons moved below password form (matches regular login)
- 404: Login form with OAuth added for unauthenticated users
- Both pages load OAuth2 providers and show Sign In with Google etc.
2026-06-06 18:25:51 -05:00
jmiller 7dabf844a8 Merge pull request 'fix(auth): show OAuth providers on 403 login form' (#547) from fix/403-oauth-login into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
2026-06-06 23:16:41 +00:00
Jonathan Miller 7d03541201 fix(auth): show OAuth providers on 403 login form
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 3s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m13s
The 403 Access Denied page login form now shows OAuth2 provider
buttons (Sign in with Google, etc.) alongside the username/password
form. Previously only showed password login even when OAuth was
configured.
2026-06-06 18:15:25 -05:00
jmiller d4a2c33c37 Merge pull request 'chore: changelog + MCP type/security tools' (#546) from chore/changelog-mcp-update into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
2026-06-06 22:51:55 +00:00
Jonathan Miller e59290802a chore: update changelog and MCP with type/security tools
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m32s
- Add v1.26.1-moko.06.10 changelog entry with all features
- Add gitea_org_issue_types_list, gitea_issue_set_type, gitea_security_alerts to MCP
- Add type_id param to issue create
2026-06-06 17:51:09 -05:00
jmiller 1d857d8205 Merge pull request 'chore: update wiki' (#544) from chore/wiki-mcp-update into dev
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (push) Has been skipped
2026-06-06 22:26:54 +00:00
Jonathan Miller 4f9aeb7b85 chore: update wiki - version, first-class fields, security, roadmap
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m43s
- Update version to v1.26.1-moko.06.10.00
- Document 13 default statuses including Pending states
- Document status replacing close button in comment form
- Add Security scanning, MCP, Wiki folders to features list
- Update roadmap with completed and planned items
- Add features/ folder link to pages table
2026-06-06 17:26:19 -05:00
16 changed files with 453 additions and 36 deletions
+50 -1
View File
@@ -445,9 +445,10 @@ server.tool(
assignees: z.array(z.string()).optional().describe('Usernames to assign'),
status_id: z.number().optional().describe('Custom status definition ID'),
priority_id: z.number().optional().describe('Custom priority definition ID'),
type_id: z.number().optional().describe('Custom type definition ID'),
...ConnectionParam,
},
async ({ owner, repo, title, body: issueBody, labels, milestone, assignees, status_id, priority_id, connection }) => {
async ({ owner, repo, title, body: issueBody, labels, milestone, assignees, status_id, priority_id, type_id, connection }) => {
const c = clientFor(connection);
// Search for existing issue with same title to prevent duplicates
@@ -483,6 +484,7 @@ server.tool(
if (issueData?.id) {
if (status_id !== undefined) await c.post(`/repos/${owner}/${repo}/issues/${issueData.id}/custom-status`, { status_id });
if (priority_id !== undefined) await c.post(`/repos/${owner}/${repo}/issues/${issueData.id}/custom-priority`, { priority_id });
if (type_id !== undefined) await c.post(`/repos/${owner}/${repo}/issues/${issueData.id}/custom-type`, { type_id });
}
const out = formatResponse(res);
out.content[0].text = `Updated existing issue #${existing.number} (duplicate prevented)\n${out.content[0].text}`;
@@ -501,6 +503,7 @@ server.tool(
if (newIssue?.id) {
if (status_id !== undefined) await c.post(`/repos/${owner}/${repo}/issues/${newIssue.id}/custom-status`, { status_id });
if (priority_id !== undefined) await c.post(`/repos/${owner}/${repo}/issues/${newIssue.id}/custom-priority`, { priority_id });
if (type_id !== undefined) await c.post(`/repos/${owner}/${repo}/issues/${newIssue.id}/custom-type`, { type_id });
}
return formatResponse(res);
},
@@ -2006,6 +2009,52 @@ server.tool(
},
);
// ── Issue Types (org-level) ──────────────────────────────────────────────
server.tool(
'gitea_org_issue_types_list',
'List custom issue type definitions for an organization',
{
org: z.string().describe('Organization name'),
...ConnectionParam,
},
async ({ org, connection }) => {
const c = clientFor(connection);
return formatResponse(await c.get(`/orgs/${org}/issue-types`));
},
);
server.tool(
'gitea_issue_set_type',
'Set custom type on an issue',
{
owner: z.string().describe('Repository owner'),
repo: z.string().describe('Repository name'),
issue_id: z.number().describe('Internal issue ID'),
type_id: z.number().describe('Type definition ID (0 to clear)'),
...ConnectionParam,
},
async ({ owner, repo, issue_id, type_id, connection }) => {
const c = clientFor(connection);
return formatResponse(await c.post(`/repos/${owner}/${repo}/issues/${issue_id}/custom-type`, { type_id }));
},
);
// ── Security ────────────────────────────────────────────────────────────
server.tool(
'gitea_security_alerts',
'List security alerts for a repository',
{
...OwnerRepo,
...ConnectionParam,
},
async ({ owner, repo, connection }) => {
const c = clientFor(connection);
return formatResponse(await c.get(`/repos/${owner}/${repo}/security/alerts`));
},
);
// ── Start Server ────────────────────────────────────────────────────────
async function main(): Promise<void> {
+51
View File
@@ -0,0 +1,51 @@
name: Publish MCP to npm
on:
push:
branches: [main]
paths:
- '.mokogitea/mcp/**'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install and build
working-directory: .mokogitea/mcp
run: |
npm ci
npx tsc
- name: Check version change
id: version
working-directory: .mokogitea/mcp
run: |
LOCAL_VERSION=$(node -p "require('./package.json').version")
NPM_VERSION=$(npm view @mokoconsulting/mokogitea-mcp version 2>/dev/null || echo "0.0.0")
if [ "$LOCAL_VERSION" != "$NPM_VERSION" ]; then
echo "changed=true" >> $GITHUB_OUTPUT
echo "Version changed: $NPM_VERSION -> $LOCAL_VERSION"
else
echo "changed=false" >> $GITHUB_OUTPUT
echo "Version unchanged: $LOCAL_VERSION"
fi
- name: Publish to npm
if: steps.version.outputs.changed == 'true'
working-directory: .mokogitea/mcp
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish to Gitea registry
if: steps.version.outputs.changed == 'true'
working-directory: .mokogitea/mcp
run: |
npm publish --registry ${{ github.server_url }}/api/packages/${{ github.repository_owner }}/npm/ \
--//$(echo "${{ github.server_url }}" | sed 's|https://||')/api/packages/${{ github.repository_owner }}/npm/:_authToken=${{ secrets.GITEA_TOKEN }}
+40
View File
@@ -3,6 +3,46 @@
All notable changes to MokoGitea are documented here. Versions follow the format
`v{upstream}-moko.{major}.{minor}` (e.g. `v1.26.1-moko.06.03`).
## [v1.26.1-moko.06.10] - 2026-06-06
* FEATURES
* feat(issues): first-class Type field with 12 auto-seeded defaults (Bug, Feature, Enhancement, Task, Documentation, Security, Roadmap, Client, Dolibarr, Infrastructure, Joomla, WaaS)
* feat(issues): first-class Status field with 13 auto-seeded defaults including 7 Pending states
* feat(issues): first-class Priority field with 4 auto-seeded defaults (Critical, High, Medium, Low)
* feat(issues): Type/Status/Priority colored badges in issue list view
* feat(issues): status dropdown replaces close/reopen button in comment form
* feat(security): built-in security scanning platform with secret scanner (15 patterns)
* feat(security): Security tab in repo navigation with alerts, scan controls
* feat(wiki): hierarchical folder navigation with sidebar tree and breadcrumbs
* feat(ui): well-known file tabs (README/LICENSE/CONTRIBUTING/SECURITY/CHANGELOG)
* feat(settings): repo manifest settings with REST API and auto-sync on push
* feat(mcp): public MCP server published to npm (@mokoconsulting/mokogitea-mcp)
* feat(mcp): SSE transport, env var config, Docker support, 120+ tools
* feat(mcp): issue dedup on create, type_id/status_id/priority_id params
* MIGRATIONS
* All org labels migrated to first-class Type/Status/Priority fields and deleted
* Type custom field (id=9) migrated to type_id and deleted
* Status custom field (id=1) deleted (replaced by first-class field)
* Priority labels migrated to priority_id
* Pending labels migrated to status definitions
* Scope labels migrated to type definitions
* Manifests populated for all 61 repos via API
* FIXES
* fix(ui): dashboard issue count badges use label spans instead of strong tags
* fix(wiki): directory check before raw redirect for folder navigation
* fix(wiki): proper display names in sidebar tree (strip dash markers)
* fix: replace non-ASCII em dashes with hyphens for hook compatibility
* fix: hookify __init__.py for stop hook JSON validation
* INFRASTRUCTURE
* npm: @mokoconsulting/mokogitea-mcp@1.1.0 and @mokoconsulting/mokowaas-mcp@1.0.0
* MCP servers consolidated under moko-platform/mcp/servers/
* Remote MCP repos renamed to hyphens
* Wiki restructured into features/, api/, operations/ folders
* Swagger API docs enabled at /api/swagger
## [v1.26.1-moko.06.04] - 2026-06-06
* FEATURES
+12
View File
@@ -2992,6 +2992,18 @@
"org.settings.issue_priority_created": "Issue priority created.",
"org.settings.issue_priority_updated": "Issue priority updated.",
"org.settings.issue_priority_deleted": "Issue priority deleted.",
"org.settings.issue_types": "Issue Types",
"org.settings.issue_types_desc": "Define issue types for all repositories in this organization.",
"org.settings.issue_types_empty": "No custom issue types defined yet.",
"org.settings.issue_type_add": "Add Type",
"org.settings.issue_type_name": "Type Name",
"org.settings.issue_type_color": "Color",
"org.settings.issue_type_description": "Description",
"org.settings.issue_type_default": "Default",
"org.settings.issue_type_sort_order": "Sort Order",
"org.settings.issue_type_created": "Issue type created.",
"org.settings.issue_type_updated": "Issue type updated.",
"org.settings.issue_type_deleted": "Issue type deleted.",
"org.settings.update_streams": "Update Server",
"org.settings.licensing": "Update Server",
"org.settings.licensing_desc": "Manage update feeds and optional license key gating across all repositories in this organization.",
+98
View File
@@ -0,0 +1,98 @@
// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
// SPDX-License-Identifier: GPL-3.0-or-later
package org
import (
"net/http"
"strconv"
issues_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/issues"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/context"
)
const tplOrgIssueTypes templates.TplName = "org/settings/issue_types"
func SettingsIssueTypes(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("org.settings.issue_types")
ctx.Data["PageIsOrgSettings"] = true
ctx.Data["PageIsSettingsIssueTypes"] = true
defs, err := issues_model.GetAllIssueTypeDefsByOrg(ctx, ctx.Org.Organization.ID)
if err != nil {
ctx.ServerError("GetAllIssueTypeDefsByOrg", err)
return
}
ctx.Data["IssueTypes"] = defs
ctx.HTML(http.StatusOK, tplOrgIssueTypes)
}
func SettingsIssueTypesCreatePost(ctx *context.Context) {
sortOrder, _ := strconv.Atoi(ctx.FormString("sort_order"))
def := &issues_model.IssueTypeDef{
OrgID: ctx.Org.Organization.ID,
Name: ctx.FormString("name"),
Color: ctx.FormString("color"),
Description: ctx.FormString("description"),
SortOrder: sortOrder,
IsDefault: ctx.FormString("is_default") == "on",
IsActive: true,
}
if def.Name == "" {
ctx.Flash.Error("Type name is required")
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-types")
return
}
if err := issues_model.CreateIssueTypeDef(ctx, def); err != nil {
ctx.ServerError("CreateIssueTypeDef", err)
return
}
ctx.Flash.Success(ctx.Tr("org.settings.issue_type_created"))
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-types")
}
func SettingsIssueTypesEditPost(ctx *context.Context) {
id := ctx.PathParamInt64("id")
def, err := issues_model.GetIssueTypeDefByID(ctx, id)
if err != nil {
ctx.ServerError("GetIssueTypeDefByID", err)
return
}
if def.OrgID != ctx.Org.Organization.ID {
ctx.NotFound(nil)
return
}
def.Name = ctx.FormString("name")
def.Color = ctx.FormString("color")
def.Description = ctx.FormString("description")
def.IsDefault = ctx.FormString("is_default") == "on"
def.IsActive = ctx.FormString("is_active") == "on"
sortOrder, _ := strconv.Atoi(ctx.FormString("sort_order"))
def.SortOrder = sortOrder
if err := issues_model.UpdateIssueTypeDef(ctx, def); err != nil {
ctx.ServerError("UpdateIssueTypeDef", err)
return
}
ctx.Flash.Success(ctx.Tr("org.settings.issue_type_updated"))
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-types")
}
func SettingsIssueTypesDeletePost(ctx *context.Context) {
id := ctx.PathParamInt64("id")
def, err := issues_model.GetIssueTypeDefByID(ctx, id)
if err != nil {
ctx.ServerError("GetIssueTypeDefByID", err)
return
}
if def.OrgID != ctx.Org.Organization.ID {
ctx.NotFound(nil)
return
}
if err := issues_model.DeleteIssueTypeDef(ctx, id); err != nil {
ctx.ServerError("DeleteIssueTypeDef", err)
return
}
ctx.Flash.Success(ctx.Tr("org.settings.issue_type_deleted"))
ctx.Redirect(ctx.Org.OrgLink + "/settings/issue-types")
}
+1 -1
View File
@@ -88,7 +88,7 @@ func ManifestSettingsPost(ctx *context.Context) {
RepoID: ctx.Repo.Repository.ID,
Name: ctx.FormString("name"),
Org: ctx.FormString("org"),
Description: ctx.FormString("description"),
Description: ctx.Repo.Repository.Description,
Version: ctx.FormString("version"),
LicenseSPDX: ctx.FormString("license_spdx"),
LicenseName: ctx.FormString("license_name"),
+6
View File
@@ -1079,6 +1079,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) {
m.Post("/{id}/edit", org.SettingsIssuePrioritiesEditPost)
m.Post("/{id}/delete", org.SettingsIssuePrioritiesDeletePost)
})
m.Group("/issue-types", func() {
m.Get("", org.SettingsIssueTypes)
m.Post("", org.SettingsIssueTypesCreatePost)
m.Post("/{id}/edit", org.SettingsIssueTypesEditPost)
m.Post("/{id}/delete", org.SettingsIssueTypesDeletePost)
})
}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true))
}, context.OrgAssignment(context.OrgAssignmentOptions{RequireOwner: true}))
}, reqSignIn)
+26
View File
@@ -16,8 +16,11 @@ import (
"syscall"
"time"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/httplib"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/oauth2"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs"
@@ -166,6 +169,18 @@ func (ctx *Context) notFoundInternal(logMsg string, logErr error) {
ctx.Data["IsRepo"] = ctx.Repo.Repository != nil
ctx.Data["Title"] = "Page Not Found"
ctx.Data["ErrorMsg"] = "" // FIXME: the template never renders this message, need to fix in the future (and show safe messages to end users)
ctx.Data["CurrentURL"] = ctx.Req.URL.RequestURI()
// Load OAuth2 providers for the login form on error pages
if !ctx.IsSigned {
oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
if err != nil {
log.Error("NotFound: GetOAuth2Providers: %v", err)
}
ctx.Data["OAuth2Providers"] = oauth2Providers
ctx.Data["EnableSSPI"] = auth_model.IsSSPIEnabled(ctx)
}
ctx.HTML(http.StatusNotFound, "status/404")
}
@@ -187,6 +202,17 @@ func (ctx *Context) Forbidden() {
ctx.Data["IsRepo"] = ctx.Repo.Repository != nil
ctx.Data["Title"] = "Access Denied"
ctx.Data["CurrentURL"] = ctx.Req.URL.RequestURI()
// Load OAuth2 providers for the login form on the 403 page
if !ctx.IsSigned {
oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true))
if err != nil {
log.Error("Forbidden: GetOAuth2Providers: %v", err)
}
ctx.Data["OAuth2Providers"] = oauth2Providers
ctx.Data["EnableSSPI"] = auth_model.IsSSPIEnabled(ctx)
}
ctx.HTML(http.StatusForbidden, "status/403")
}
+81
View File
@@ -0,0 +1,81 @@
{{template "org/settings/layout_head" (dict "ctxData" . "pageClass" "organization settings issue-types")}}
<h4 class="ui top attached header">
{{ctx.Locale.Tr "org.settings.issue_types"}}
</h4>
<div class="ui attached segment">
<p class="text grey">{{ctx.Locale.Tr "org.settings.issue_types_desc"}}</p>
{{if .IssueTypes}}
<table class="ui compact table">
<thead>
<tr>
<th>{{ctx.Locale.Tr "org.settings.issue_type_color"}}</th>
<th>{{ctx.Locale.Tr "org.settings.issue_type_name"}}</th>
<th>{{ctx.Locale.Tr "org.settings.issue_type_default"}}</th>
<th>{{ctx.Locale.Tr "org.settings.issue_type_sort_order"}}</th>
<th></th>
</tr>
</thead>
<tbody>
{{range .IssueTypes}}
<tr {{if not .IsActive}}class="tw-opacity-50"{{end}}>
<td>
{{if .Color}}<span class="tw-inline-block tw-w-4 tw-h-4 tw-rounded" style="background-color: {{.Color}}"></span>{{else}}<span class="text grey">-</span>{{end}}
</td>
<td>
<strong>{{.Name}}</strong>
{{if not .IsActive}}<span class="ui mini grey label">Inactive</span>{{end}}
{{if .Description}}<br><small class="text grey">{{.Description}}</small>{{end}}
</td>
<td>
{{if .IsDefault}}<span class="ui mini blue label">{{ctx.Locale.Tr "org.settings.issue_type_default"}}</span>{{else}}<span class="text grey">-</span>{{end}}
</td>
<td>{{.SortOrder}}</td>
<td class="tw-text-right">
<form method="post" action="{{$.OrgLink}}/settings/issue-types/{{.ID}}/delete" class="tw-inline">
{{$.CsrfTokenHtml}}
<button class="ui tiny red icon button" type="submit" title="{{ctx.Locale.Tr "remove"}}">{{svg "octicon-trash" 14}}</button>
</form>
</td>
</tr>
{{end}}
</tbody>
</table>
{{else}}
<div class="empty-placeholder"><p>{{ctx.Locale.Tr "org.settings.issue_types_empty"}}</p></div>
{{end}}
<div class="divider"></div>
<h5>{{ctx.Locale.Tr "org.settings.issue_type_add"}}</h5>
<form class="ui form" method="post" action="{{.OrgLink}}/settings/issue-types">
{{.CsrfTokenHtml}}
<div class="three fields">
<div class="required field">
<label>{{ctx.Locale.Tr "org.settings.issue_type_name"}}</label>
<input name="name" required placeholder="e.g. Bug, Feature, Task">
</div>
<div class="field">
<label>{{ctx.Locale.Tr "org.settings.issue_type_color"}}</label>
<input name="color" type="color" value="#2563eb">
</div>
<div class="field">
<label>{{ctx.Locale.Tr "org.settings.issue_type_sort_order"}}</label>
<input name="sort_order" type="number" value="0" min="0">
</div>
</div>
<div class="two fields">
<div class="field">
<label>{{ctx.Locale.Tr "org.settings.issue_type_description"}}</label>
<input name="description" placeholder="Help text">
</div>
<div class="field">
<div class="ui checkbox tw-mt-4">
<input name="is_default" type="checkbox">
<label>{{ctx.Locale.Tr "org.settings.issue_type_default"}}</label>
</div>
</div>
</div>
<button class="ui primary button" type="submit">{{ctx.Locale.Tr "org.settings.issue_type_add"}}</button>
</form>
</div>
{{template "org/settings/layout_footer" .}}
+3
View File
@@ -37,6 +37,9 @@
<a class="{{if .PageIsSettingsIssuePriorities}}active {{end}}item" href="{{.OrgLink}}/settings/issue-priorities">
{{svg "octicon-flame"}} {{ctx.Locale.Tr "org.settings.issue_priorities"}}
</a>
<a class="{{if .PageIsSettingsIssueTypes}}active {{end}}item" href="{{.OrgLink}}/settings/issue-types">
{{svg "octicon-tag"}} {{ctx.Locale.Tr "org.settings.issue_types"}}
</a>
{{if .EnableActions}}
<details class="item toggleable-item" {{if or .PageIsOrgSettingsActionsGeneral .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables}}open{{end}}>
<summary>{{svg "octicon-play"}} {{ctx.Locale.Tr "actions.actions"}}</summary>
-4
View File
@@ -19,10 +19,6 @@
<input name="org" value="{{.Manifest.Org}}" placeholder="Organization">
</div>
</div>
<div class="field">
<label>{{ctx.Locale.Tr "repo.settings.manifest_description"}}</label>
<input name="description" value="{{.Manifest.Description}}" placeholder="Project description">
</div>
<div class="three fields">
<div class="field">
<label>{{ctx.Locale.Tr "repo.settings.manifest_version"}}</label>
+4
View File
@@ -23,6 +23,10 @@
</div>
<button class="ui primary fluid button tw-mt-2" type="submit">{{ctx.Locale.Tr "sign_in"}}</button>
</form>
{{if or .OAuth2Providers .EnableSSPI}}
<div class="divider"></div>
{{template "user/auth/external_auth_methods" .}}
{{end}}
</div>
{{end}}
</div>
+21
View File
@@ -11,6 +11,27 @@
<a class="tw-block tw-my-4" href="{{.NotFoundGoBackURL}}">{{ctx.Locale.Tr "go_back"}}</a>
{{end}}
</div>
{{if not .IsSigned}}
<div class="tw-max-w-sm tw-mx-auto tw-mt-4">
<form class="ui form" action="{{AppSubUrl}}/user/login" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="redirect_to" value="{{.CurrentURL}}">
<div class="required field">
<label>{{ctx.Locale.Tr "home.uname_holder"}}</label>
<input type="text" name="user_name" required autofocus>
</div>
<div class="required field">
<label>{{ctx.Locale.Tr "password"}}</label>
<input type="password" name="password" required>
</div>
<button class="ui primary fluid button tw-mt-2" type="submit">{{ctx.Locale.Tr "sign_in"}}</button>
</form>
{{if or .OAuth2Providers .EnableSSPI}}
<div class="divider"></div>
{{template "user/auth/external_auth_methods" .}}
{{end}}
</div>
{{end}}
</div>
</div>
</div>
+29 -10
View File
@@ -28,23 +28,42 @@ Each status has:
| Sort Order | Controls display order in dropdowns (ascending) |
| Is Active | Inactive statuses are hidden from dropdowns but preserved on existing issues |
### Example Statuses
### Default Statuses (auto-seeded)
| Status | Color | Closes Issue | Use Case |
|--------|-------|:------------:|----------|
| In Progress | Blue | No | Work is actively being done |
| Needs Info | Yellow | No | Waiting for more information from reporter |
| Blocked | Red | No | Cannot proceed due to external dependency |
| Won't Fix | Gray | Yes | Decided not to address this issue |
| Duplicate | Purple | Yes | Already tracked in another issue |
| Resolved | Green | Yes | Fix has been implemented and verified |
| Needs Info | Yellow | No | Waiting for more information |
| Blocked | Red | No | Cannot proceed due to dependency |
| Resolved | Green | Yes | Fix implemented and verified |
| Won't Fix | Gray | Yes | Decided not to address |
| Duplicate | Purple | Yes | Already tracked elsewhere |
| Pending: Design | Lavender | No | Waiting on design work |
| Pending: Testing | Yellow | No | Waiting for testing |
| Pending: Review | Green | No | Waiting for code review |
| Pending: Feedback | Pink | No | Waiting for feedback |
| Pending: Documentation | Purple | No | Waiting for docs |
| Pending: Deployment | Blue | No | Ready to deploy |
| Pending: Dependency | Light Blue | No | Blocked by external dependency |
Statuses are auto-seeded when an org first accesses them. Admins can add, edit, reorder, or deactivate statuses.
## Comment Form Integration
The status dropdown **replaces the close/reopen button** in the comment form footer for issues with org statuses:
- Open issues show all statuses plus a "Close" option
- Selecting a status with `closes_issue = true` auto-closes the issue
- Closed issues show only "Reopen" for non-admin users
- Admins see the full dropdown on closed issues including "Reopen"
- PRs still use the standard close/reopen button
## Issue List Badges
Status shows as a colored badge on each issue in the issue list view, alongside Type and Priority badges.
## Issue Sidebar
When an organization has custom statuses defined, a **Status** dropdown appears in the issue sidebar between labels and custom fields. The dropdown:
- Shows all active status definitions for the repo's organization
- Auto-submits on change (no save button needed)
Status also appears as a read-only display in the sidebar (the editable control is in the comment form). The dropdown:
- Displays a colored left border on each option
- Shows a power symbol on statuses that close the issue
- Selecting "—" (empty) clears the status
+7 -3
View File
@@ -7,7 +7,7 @@ Moko Consulting's custom fork of [Gitea](https://gitea.com), extending the self-
| **Language** | Go |
| **License** | MIT |
| **Upstream** | Gitea 1.26.1 |
| **Version** | v1.26.1-moko.06.07.03 |
| **Version** | v1.26.1-moko.06.11.01 |
| **Platform** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea) |
---
@@ -16,10 +16,13 @@ Moko Consulting's custom fork of [Gitea](https://gitea.com), extending the self-
- **Commercial License System** — Package-based license keys with download gating, domain restriction, key expiry, and payment webhook API
- **Update Server** — Built-in update feeds for Joomla, WordPress, Dolibarr, Composer, Drupal, PrestaShop, and WHMCS
- **Custom Issue Statuses** — Org-defined workflow states (In Progress, Blocked, Won't Fix) with auto close/reopen
- **First-Class Issue Fields** — Type (12 types), Status (13 statuses), Priority (4 levels) as built-in fields with auto-seed defaults, colored badges in issue list, and sidebar dropdowns
- **Security Scanning** — Built-in security scanner with secret detection (15 patterns), push-time scanning, alert management, and Security tab in repo navigation
- **Custom Fields** — Org-level field definitions for issues (sidebar) and repos (metadata) with dropdown, text, number, date, checkbox, and URL types
- **Manifest Settings** — Per-repo identity/governance/build metadata with REST API for CI/CD integration
- **Manifest Settings** — Per-repo identity/governance/build metadata with REST API and auto-sync on push
- **Wiki Folders** — Hierarchical folder navigation with sidebar tree, breadcrumbs, and index page fallback
- **Well-Known File Tabs** — README/LICENSE/CONTRIBUTING/SECURITY/CHANGELOG tabs on repo home page
- **MCP Server** — 120+ tool MCP server published to npm (@mokoconsulting/mokogitea-mcp) with SSE transport
- **Org-Level Branch Protection** — Organization-scoped rulesets that cascade to all repos. Supports glob patterns. Full CRUD API
- **Enterprise Sub-Orgs** — Parent-child organization hierarchy
- **Three-Level Visibility** — Public (200), Private (403), Hidden (404) for repositories
@@ -39,6 +42,7 @@ Moko Consulting's custom fork of [Gitea](https://gitea.com), extending the self-
| [Org Branch Protection API](Org-Branch-Protection-API) | Org-level branch protection rulesets and API reference |
| [Project API](Project-API) | Custom API endpoint reference for project boards |
| [Roadmap](Roadmap) | Development roadmap and planned features |
| [features/](features) | Feature documentation folder |
---
+24 -17
View File
@@ -1,42 +1,49 @@
# MokoGitea Roadmap
## Recently Completed (v1.26.1-moko.06.07)
## Recently Completed (v1.26.1-moko.06.11)
- First-class Type field (12 types) replacing labels and custom fields
- First-class Status field (13 statuses) with auto close/reopen
- First-class Priority field (4 levels) with auto-seed defaults
- All org labels migrated to first-class fields and deleted
- Type/Status/Priority colored badges in issue list view
- Security scanning platform with 15 secret detection patterns
- Security tab in repo navigation (admin-only)
- Wiki hierarchical folder navigation with sidebar tree
- Well-known file tabs (README/LICENSE/CONTRIBUTING/SECURITY/CHANGELOG)
- Custom issue statuses with auto close/reopen
- Org-level issue priorities (Critical/High/Medium/Low)
- Repo manifest settings with REST API
- Manifest auto-sync on push to default branch
- Status dropdown replaces close button
- Auto-seed default statuses and priorities for orgs
- MCP server published to npm (@mokoconsulting/mokogitea-mcp)
- MCP SSE transport for hosted deployments
- Repo manifest settings with REST API and auto-sync on push
- MCP server published to npm (@mokoconsulting/mokogitea-mcp) with SSE transport
- Dashboard issue count badges fixed
- Status dropdown replaces close/reopen button
- Org settings page for Issue Types
- MCP SSE endpoint hosted at git.mokoconsulting.tech/mcp/
- npm auto-publish workflow on MCP source changes
- OAuth providers on 403/404 error pages
- All stale branches cleaned up (main + dev only)
## In Progress
- Rename moko-platform to MokoPlatform
- Granular role-based permissions for all features (#9)
- Built-in secret scanning (#508)
- Enterprise Wiki with hierarchical folder navigation (#79)
- Wire moko-platform CLI to manifest API (#505)
- Bulk migrate remaining 41 flat wikis to folders
## Planned
- Standard status presets and cross-org migration (#507)
- Auto-create default teams on org creation (#513)
- Update server reads from repo_manifest (#512)
- Dependency vulnerability scanner module
- Code security analysis scanner module
- Payment gateways for license keys (#135)
- Independent visibility controls for issues/wiki/projects (#133)
## Infrastructure
- MCP SSE endpoint at git.mokoconsulting.tech/mcp
- MCP SSE endpoint hosted at git.mokoconsulting.tech/mcp
- Smithery/Claude Code marketplace listing
- Docker image for MCP server
- npm auto-publish workflow on release
---
| Revision | Date | Author | Description |
|---|---|---|---|
| 3.0 | 2026-06-06 | Jonathan Miller (@jmiller) | First-class fields, security scanning, wiki folders, MCP release |
| 2.0 | 2026-06-06 | Jonathan Miller (@jmiller) | Complete rewrite with current features and priorities |
| 1.0 | 2026-05-09 | Jonathan Miller (@jmiller) | Initial version |