- codeql.yml removed: GitHub-only (uses github/codeql-action/*).
- build.yml + release.yml: runs-on switched to ubuntu-latest (Gitea Cloud
has no Windows runner). Dalamud staging is now downloaded via curl/unzip
into $HOME/.xlcore/dalamud/Hooks/dev/, the path the Dalamud SDK 15 uses
on Linux. Locate-step uses find instead of Get-ChildItem.
- release.yml: softprops/action-gh-release replaced with the Gitea-native
https://gitea.com/actions/release-action. Auto-injected GITHUB_TOKEN on
Gitea Actions has Gitea-API scope and is sufficient.
- forge-announce.yml: environment: Webhook removed (Gitea has no
environments — DISCORD_FORGE_WEBHOOK is a repo-level Actions secret).
avatar_url and embed url switched from raw.githubusercontent.com /
github.com to gitea.com.
- release-footer.md: install URL plus the five doc links (README, PRIVACY,
THIRD_PARTY_NOTICES, SECURITY, SUPPORT) and LICENSE link switched to
gitea.com/.../src/branch/main/. ChatTwo upstream link stays on GitHub.
Two CodeQL alerts opened against the codeql-manual-build workflow's
first scan. Both real, both small fixes.
#1 Medium / Workflow does not contain permissions
build.yml runs read-only against the repo (no push, no release
creation, no API mutations) but never declared a permissions
block, so the default GITHUB_TOKEN scope applied. Pin to
contents: read at workflow level. Release and CodeQL workflows
already have their explicit minimal scopes.
#2 Critical / Unvalidated local pointer arithmetic
ImGuiUtil.WrappedTextWithPos splits its input on newlines and
passes each part through Encoding.UTF8.GetBytes inside a fixed
block. Empty splits (consecutive newlines, blank lines) produced
a zero-length byte array, fixed gave us a valid pointer, and
textEnd = text + bytes.Length collapsed onto text. The downstream
ImGuiNative.CalcWordWrapPositionA calls received identical start
and end pointers, which is undefined behaviour at the native
boundary even if it happens to no-op on the current ImGui build.
Bail before entering the fixed block when bytes.Length == 0 and
render an empty line for the gap, which is what the original
text == null guard was trying to do but could never reach inside
a fixed block over a non-null array.
LICENSE now starts with the EUPL-1.2 standard header so github-linguist
detects the licence correctly in the repo header. The dual-copyright
block (upstream ChatTwo authors plus Hellion Online Media) moves into a
new COPYRIGHT file referenced from the README. NOTICE.md and
UPSTREAM_SYNC.md stay as-is.
New files under .github:
- workflows/build.yml: validates every push to main and every PR
against the current Dalamud staging branch on a Windows runner
- workflows/release.yml: builds Release on every v* tag, locates the
DalamudPackager latest.zip and attaches it to the matching GitHub
Release via softprops/action-gh-release
- dependabot.yml: weekly NuGet sweeps and monthly GitHub Actions
sweeps with conventional-commit prefixes, grouped patch and minor
PRs to cut review noise
- ISSUE_TEMPLATE/bug_report.yml + feature_request.yml + config.yml:
structured intake that pushes security reports through the private
advisory flow and routes upstream-only issues to ChatTwo
- SECURITY.md: documents the vulnerability reporting channels, scope,
and target disclosure window
The release workflow replaces the previous manual upload step. Tag a
release and the ZIP shows up on the release page automatically.