100 Commits
Author SHA1 Message Date
Tosone 42600b95f5 feat(web): chart the build duration of a repository builder
Show how long the recent builds took above the run list: the chart reads the
last 100 runs of the builder, plots the elapsed time of the finished ones and
marks the latest duration in the header. It is drawn as plain svg so no chart
dependency is needed, and hovering a point shows the tag, the duration and
the time of that build.

Verification:
- bunx tsc --noEmit
- bun run lint
- bun run build
2026-10-28 11:09:38 +08:00
Tosone 14a7952ea6 fix(web): stop the builder page from rewriting its URL on back
The page listened to popstate and called navigate(backTo) with an empty
`back_to`, and react-router resolves an empty path to the current pathname
with an empty search, pushing a new entry. Pressing back therefore stayed on
the builder page and dropped every query parameter. The mount effect that
re-pushed the current query had the same problem: it added a duplicate
history entry.

Drop both; `back_to` is still used by the Cancel button, and the browser back
button now undoes the navigation that opened the page.

Verification:
- bunx tsc --noEmit
- bun run lint
- bun run build
2026-10-28 11:09:38 +08:00
Tosone e5032fb087 feat(web): merge the builder and runs tabs of a repository
A repository exposed two tabs that only differed by whether a builder was
configured: "Builder" opened the setup form and "Runs" opened the build
list. Merge them into one "Builder" tab: it shows the setup form while the
repository has no builder and the run list once a builder exists.

- add RepositoryTabs, the tab bar shared by the repository pages
- add pages/Builder/index.tsx, which picks the setup form or the run list
  from the repository builder and swaps to the run list after a save
- render the setup form inside the repository chrome when embedded
- point the configure/update/back links at the merged route and keep
  /repository/runners as an alias for existing bookmarks

Verification:
- bunx tsc --noEmit
- bun run lint
- bun run build
2026-10-28 11:09:37 +08:00
Tosone 833597b871 refactor(web): drop the builder shortcut from the namespace menu
The builder belongs to a repository, so the namespace level entry between
the members and the daemon task sections duplicated the repository tab.
Remove the section entry, its daemon gate and the builder specific link,
and stop mapping the builder route to the removed section.

Verification:
- bunx tsc --noEmit
- bun run lint
- bun run build
2026-10-28 11:09:37 +08:00
Tosone 2b47c02f4e refactor(web): import lodash helpers from lodash-es
The web app only uses `size` and `orderBy`, and `lodash` is the CommonJS
build that the bundler cannot tree-shake. Import the helpers by name from
`lodash-es` instead, drop `lodash` and declare `@types/lodash-es` (it was
only reachable through bytemd before).

Verification:
- bunx tsc --noEmit
- bun run lint
- bun run build
2026-10-28 11:09:37 +08:00
Tosone fb4ae986d1 build(deps): bump go and web dependencies
Update Go modules and web packages to their latest available patch and
minor releases.

Go:
- github.com/aws/aws-sdk-go-v2 v1.47.3 -> v1.47.4
- github.com/aws/aws-sdk-go-v2/config v1.33.9 -> v1.33.11
- github.com/aws/aws-sdk-go-v2/service/s3 v1.114.3 -> v1.114.5
- github.com/aws/smithy-go v1.28.5 -> v1.28.6
- github.com/go-redsync/redsync/v4 v4.18.0 -> v4.18.1
- github.com/tencentyun/cos-go-sdk-v5 v0.7.75 -> v0.7.76
- transitive: aws-sdk-go-v2 internals, eventstream, credentials, sso,
  ssooidc, sts and signin

Web:
- @base-ui/react 1.8.0 -> 1.9.0
- @tanstack/react-query 5.104.1 -> 5.105.0
- axios 1.20.0 -> 1.21.0
- cron-parser 5.10.1 -> 5.10.2
- human-format 1.2.1 -> 1.4.0
- lucide-react 1.52.0 -> 1.62.0
- react / react-dom 19.3.0 -> 19.3.1
- shadcn 4.21.3 -> 4.23.0
- zod 4.6.5 -> 4.6.7
- zustand 5.0.15 -> 5.0.16
- @types/node 26.6.4 -> 26.6.5
- autoprefixer 10.6.1 -> 10.6.2
- oxlint 1.87.0 -> 1.90.0
- postcss 8.5.29 -> 8.5.32
- postcss-import 17.0.0 -> 17.0.1
- vite 8.3.3 -> 8.3.5

Verification:
- go mod tidy
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- bun run lint
- bun run build
2026-10-27 22:55:34 +08:00
Tosone 0f31d58990 chore(scripts): quote the rs3 healthcheck so shellcheck stops warning
The healthcheck was written in single quotes, which shellcheck flags as
"expressions don't expand in single quotes" even though deferring the
expansion to the container is exactly what is wanted. Keep the same value
with escaped double quotes: the backslash stops the host shell from touching
${RS3_PORT}, and the container expands it at run time.

Verification:
- bash -n scripts/run_rs3.sh
- docker run with the rendered --health-cmd resolves RS3_PORT inside the container
2026-10-27 22:47:53 +08:00
Tosone 2da4de8fb8 chore(conf): enable the builder daemon in the development config
conf/config-dev.yaml mirrored the production default, so a local run had no
builder entry in the menu and no way to create builds without editing the
file. Enable it there: the development config is the one used when running
against a local builder.

Verification:
- helm/conf not affected; loaded by `go run . server -c conf/config-dev.yaml`
2026-10-27 22:47:53 +08:00
Tosone a1051f53c2 feat(web): show the provider push time in the code repository list
The list offered an Oci Repo Count column nobody acted on, an action column
whose only entry opened the setup builder — reachable from the repository
tabs now — and a timestamp that read as nine hours old because the API sends
UTC wall-clock strings and dayjs parsed them as local time.

- replace the count and action columns with the last update time, rendered
  through RelativeTime so the timezone is handled once
- sort by pushed_at descending and page twenty at a time, with the page size
  as a constant instead of the global settings value
- drop the forced 100rem page width: the app layout already sizes the content
  column, so the pages overflowed it and their justify-between rows pushed
  the actions past the right edge
- give the sync button the same gutter as the namespace page's create button,
  and let the pagination component own its container

Verification:
- cd web && npx tsc --noEmit
- cd web && npx oxlint
- cd web && npx vite build
2026-10-27 22:47:50 +08:00
Tosone 64e4de5702 feat(web): rework the setup builder form
The form mixed three interaction styles: popovers with a cmdk search list,
plain selects and hand-styled inputs. Picking a provider could leave two
options looking highlighted, an empty list opened an empty popup that
rendered as a thin grey line, and several fields had no dark mode support.

Make every picker a Select and calm the form down:

- provider, organization, repository and branch — plus the cron and merge
  branch pickers — are Selects now; the popup is only rendered when there is
  something to choose, and the branch pickers refresh their list when opened
  because branches are no longer synced
- provider options show their display name, an unavailable provider disables
  the organization and repository pickers, and its hint opens the credential
  dialog in place instead of navigating away
- the OCI repository picker lists the repository name without the namespace
  prefix, the way the repository is referred to elsewhere
- the section descriptions move into info tooltips next to the headings
- clone depth uses the shared input, round-trips through
  code_repository_clone_depth, clamps to a non-negative integer and explains
  that 0 clones the full history
- the self-managed repository block uses the shared inputs, keeps the token
  masked and gives the fields room to breathe
- CommandItem gets a pointer cursor, which fixes every cmdk list, and the
  setup page drops the forced 100rem width that pushed it past the viewport

Verification:
- cd web && npx tsc --noEmit
- cd web && npx oxlint
- cd web && npx vite build
2026-10-27 22:47:47 +08:00
Tosone 7039914b3a feat(web): add a builder tab on repository pages and drop duplicate navigation
The repository pages carried their own tab strip, and the sidebar repeated
the same entries under the repository node, so the same navigation existed
in two places and neither was complete: the Setup builder page was only
reachable from the code repository list, which no longer links to it.

- add /namespaces/:namespace/repository/builder rendering the setup builder,
  and turn the repository tabs into Summary | Builder | Runs | Tag list; the
  former "Builder" tab, the runner list, becomes "Runs"
- remove the repository level from the sidebar: its entries are the page
  tabs now, and "Repository list" stays highlighted while browsing into a
  repository
- drop NamespaceTabs, the duplicate header strip on the namespace pages
- resolve entity ids as opaque UUID strings: interface fields are strings
  now and the pages that parsed ids with parseInt stopped truncating them
  (a UUIDv7 starts with "1a1...", so parseInt returned 1)
- add useNamespaceId: a page opened without ?namespace_id — a bookmark or a
  hand written URL — looks the id up from the namespace in the route instead
  of requesting /namespaces/null or /namespaces//
- the tag page: title is Tags, its search box matches the namespace one, and
  it skips the request while the namespace is unresolved

Verification:
- cd web && npx tsc --noEmit
- cd web && npx oxlint
- cd web && npx vite build
2026-10-27 22:47:33 +08:00
Tosone 5c05104720 feat(coderepos): read branches on demand and track provider push time
A sync listed the branches of every repository it saw, one API call per
repository per page. For an account with a few hundred repositories that
alone exhausts the GitHub rate limit, and the result was stale the moment a
branch was pushed.

Store the provider's push time instead, and read branches only when a build
form asks for them:

- the daemon reconciles repositories and owners only; github, gitlab and
  gitea no longer page through branches, diffBranch is gone, and the
  code_repository_branches table and model are dropped from the baseline
- CodeRepository gains pushed_at, filled from github pushed_at, gitlab
  last_activity_at (falling back to updated_at) and gitea updated_at, and
  the list orders by it so "most recently active" means the provider's view
  rather than our own row's updated_at, which every sync touched
- ListCodeRepositoryBranches and GetCodeRepositoryBranch resolve the
  binding, the decrypted token and the repository, then query the provider,
  so branch names are always current; a repository id is user input and is
  now checked against the caller's binding instead of exposing another
  account's repository
- the list response also stops filling updated_at from created_at

Existing installations need the new column and the dropped table applied by
hand, as documented for the baseline migration edit.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/dal/repository/coderepo/... ./pkg/service/coderepos/... ./pkg/server/handlers/coderepos/... ./pkg/background/daemon/coderepo/...
- make gormgen
- make swagen
2026-10-27 22:47:28 +08:00
Tosone 36c36f73f8 fix(daemon): list GitHub repositories with ListByAuthenticatedUser
Repositories.List is deprecated: with an empty user it forwards to
ListByAuthenticatedUser anyway, so the call was a wrapper around the API we
want, and it was silenced with a stale "nolint: staticcheck" that the
enabled linters no longer need.

Call ListByAuthenticatedUser directly. Both hit GET /user/repos and keep the
same ListOptions pagination, so the returned repositories and the existing
"owned by this account" filter are unchanged.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- golangci-lint run --enable staticcheck --build-tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/background/...
2026-10-27 21:33:36 +08:00
Tosone ef9fa992fc fix(web): widen the credential type select so options are not clipped
The credential dialog used a w-fit trigger, so the popup inherited the width
of the currently selected label ("Access token"), and the explicit min-w-0
on the popup removed the 9rem floor that select-content normally keeps. The
longest option, "Username and password", was therefore clipped by the
popup's overflow-x-hidden.

Let the trigger span the dialog and keep the default min width of the popup.

Verification:
- cd web && npx tsc --noEmit
- cd web && npx oxlint
- cd web && npx vite build
2026-10-27 21:30:35 +08:00
Tosone 93de2dac54 fix(coderepos): stop the credential validator from panicking
PUT /api/v1/coderepos/{provider}/credential returned a 500 and logged
"http: panic serving ...: Bad field type *string": validator's max tag
panics when it is combined with required_if on a pointer field. A token
request leaves ssh_key, username and password nil, required_if passes
because the condition is false, the chain moves on to max, and max receives
the nil *string without dereferencing it.

Enforce the size limits in the service instead, next to the required checks
that already lived there, and keep required_if on the request so an
incomplete body is still rejected before it reaches the service. Swagger no
longer advertises maxLength for these fields.

Add a binding test that drives the three credential shapes through
server.WrapRequest, which is the path the panic was reached on.

Verification:
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/server/handlers/coderepos/... ./pkg/service/coderepos/...
- golangci-lint run --build-tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/api/... ./pkg/service/coderepos/... ./pkg/server/handlers/coderepos/...
- make swagen
2026-10-27 21:26:39 +08:00
Tosone ce7d1c6b6e feat(web): manage code repository credentials from settings
The code repository entry sat next to namespaces even though it holds no
content: it only configures the source builds clone from. Its provider
submenu came from the OAuth2 login flags, so turning OAuth off left an
empty menu entry and a blank page, and there was no way to supply an access
token at all.

- move the entry into the Settings group and drop the provider submenu; the
  providers are now cards on the page, so listing them twice only added a
  third level
- rebuild /coderepos as one card per provider showing the linked account,
  the credential type and the last sync result, with actions to add or
  update a credential, resync, clear it, or open the repository list
- add CredentialDialog for the token, SSH key and username/password types,
  with the OAuth binding offered as an alternative that still needs a token
  for syncing
- read the sync state of /coderepos/{provider} from the providers response
  instead of issuing a second request, and point the builder setup provider
  combobox at the credential settings when nothing is configured
- extend ICodeRepositoryProviderItem with the new fields and add the
  zh-CN/en-US strings

Verification:
- cd web && npx tsc --noEmit
- cd web && npx oxlint
- cd web && npx vite build
2026-10-27 21:07:53 +08:00
Tosone 76e1086035 refactor(builder): encrypt builder secrets with AES-GCM
The authorization token, signing key and SCM credentials handed to a build
runner were encrypted with AES-CTR, which has no integrity protection: a
tampered environment value decrypted into garbage that downstream code
would only fail on much later.

Use crypt.Seal/crypt.Open for those values. The key stays the same
per-build key derived from the builder and runner IDs, and every secret is
sealed once up front instead of inline in the env list, so a failure is
reported before the runner starts.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/background/build/...
2026-10-27 21:07:49 +08:00
Tosone 48102fe383 feat(daemon): sync code repositories with stored credentials
The daemon read the OAuth access token straight from user_3rdparty, so a
sync that ran more than two hours after the last login failed with a 401
and the reason was never surfaced: the status row said Failed with an empty
message, and nobody could tell that a token had expired.

- load and decrypt the credential, and fail with a message that tells the
  user what to do when it is missing or cannot be opened
- reject non-token credentials for syncing, since listing repositories is an
  API call that an SSH key or username/password cannot make
- resolve the provider base URL from scm.providers and pass it to the
  GitLab and Gitea clients instead of letting them default to the hosted
  endpoints
- truncate the stored error message to the column size, so a long provider
  error does not fail the status update that is supposed to explain it

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
2026-10-27 21:07:46 +08:00
Tosone 9322b7e79e feat(builders): resolve clone credentials from the credential store
Creating a builder fell back to the login OAuth token whenever the clone
credential lookup found nothing, which copied a login credential into
builders.scm_token and then into the build pod environment. The same block
logged a real database error and carried on, producing a builder with no
credentials at all.

Read only the credential store now, and fail loudly instead:

- decryptedCredential loads the row, rejects type none, and opens the sealed
  token, ssh key and password before they are handed to the builder
- a missing credential returns 400 with an actionable message instead of
  silently creating a credential-less builder, and other lookup errors are
  returned rather than logged

Verification:
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/builders/...
2026-10-27 21:07:43 +08:00
Tosone 5ca747ddd7 refactor(oauth2): stop persisting OAuth tokens on login
The callback stored the access and refresh token on user_3rdparty and
re-issued the code repository sync on every login, which only worked
because the login refreshed an expiring token. Credentials now live in the
clone credential table, so the tokens have no reader left.

- drop the token update on repeated login and the token fields from both
  binding-creation paths; Oauth2UserInfo no longer carries them
- stop publishing a sync task when a binding is created: there is no
  credential at that point, so the task could only report a failure
- derive the GitLab and Gitea OAuth endpoints from scm.providers[].baseUrl
  instead of hardcoding gitlab.com, and point Gitea at its own
  /login/oauth endpoints and redirect callback

Verification:
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/oauth2/...
2026-10-27 21:07:40 +08:00
Tosone a80519d86f feat(coderepos): configure a per-provider SCM credential
Users had no way to supply their own access token: the only credential in
play was the OAuth token captured at login, which expires and which the
builders then copied into their own table. The clone credential table
existed but had no write path, so every lookup fell back to that token.

Give each provider an explicit credential:

- GET/PUT/DELETE /api/v1/coderepos/{provider}/credential plus
  POST .../credential/validate; the read endpoint returns a masked token and
  "has" flags, never the secret
- UpsertCodeRepositoryCredential validates a token against the provider,
  resolves the account id from it, ensures the third-party binding exists
  (409 when the account already belongs to another user) and seals
  token/ssh_key/password before storing them
- only token credentials can list repositories: ssh and username/password
  are clone credentials, so validate reports validated=false for them and
  no sync is queued
- ListCodeRepositoryProviders returns the configured providers joined with
  the caller's binding, credential and last sync state, so a provider that
  is configured but not linked yet is still offered by the UI
- fix the AccountID and UpdatedAt mistakes in the user3rdparty response,
  which dereferenced a nil pointer and reported the creation time twice
- regenerate the coderepos and user repository mocks and the operator
  swagger spec

Verification:
- make gormgen
- make swagen
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/coderepos/... ./pkg/server/handlers/coderepos/...
2026-10-27 21:07:37 +08:00
Tosone 3cb76aae80 feat(bootstrap): generate the credential master key on first start
auth.credentialKey is optional, so a deployment must work without operator
input. Generate a random 32-byte key on first start and persist it in the
settings table, which keeps the credential service able to decrypt values
written by an earlier process.

- run the task right after the services are registered, before signing
- take a distributed lock around the check-then-create and re-read inside
  it, otherwise two replicas starting together would generate different
  keys and leave half the credentials unreadable
- when auth.credentialKey is set it is authoritative: only its length is
  validated and nothing is written to the settings table

Verification:
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/app/bootstrap/...
2026-10-27 21:07:31 +08:00
Tosone 391c380cb5 feat(dal): store SCM credentials in code_repository_clone_credentials
user_3rdparty held the OAuth access and refresh token issued at login and
three different consumers read the access token from it: the code
repository daemon to list repositories, the builder to clone, and login to
issue a JWT. Access tokens expire (GitLab after two hours) and refresh
tokens were written but never read, so syncing and building silently broke
a couple of hours after the user last signed in.

Split identity from credentials:

- drop token and refresh_token from user_3rdparty, leaving a pure identity
  binding, and stop auto-updating cr_last_update_timestamp so unrelated
  writes no longer fake a sync
- make code_repository_clone_credentials usable: one live row per
  third-party account through a (user_3rdparty_id, deleted_at) unique
  constraint, wider token/password columns for the sealed values, and
  UpsertCredential/DeleteCredential built on clause.OnConflict
- add UserRepository.UpsertUser3rdPartyByAccountID so a user who only ever
  pastes a token still gets a binding, without duplicating rows when two
  requests race

The baseline 0001 migration is edited in place for all four dialects
instead of adding an increment: fresh installs get the final schema, while
existing installations have to apply the constraint manually (documented in
the migration design notes).

Verification:
- make gormgen
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/dal/repository/coderepo/... ./pkg/dal/repository/user/...
2026-10-27 21:07:28 +08:00
Tosone c293d6b49e feat(service): seal SCM credentials at rest with a dedicated service
Every consumer that needs an access token would otherwise have to resolve
the master key itself and remember to hash it before calling crypt. Keep
that knowledge in one place:

- service/credential resolves the key once at construction time:
  auth.credentialKey when configured, otherwise the value the credential
  bootstrap task persists in the settings table
- it fails fast when neither exists or when the configured key is shorter
  than 32 bytes, because storing credentials that can never be decrypted
  is worse than refusing to start
- Seal/Open delegate to crypt.Seal/crypt.Open so stored values are
  authenticated

Verification:
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/credential/...
2026-10-27 21:07:23 +08:00
Tosone 642b2d576c feat(config): add scm provider configuration and credential master key
The source-code providers a deployment can use were implied by
auth.oauth2.*, so disabling OAuth login also disabled code repository sync
and every build that clones source code, and there was nowhere to configure
a self-hosted GitLab or Gitea at all: the gitea client was created with an
empty base URL.

Make provider capability explicit and independent from login:

- add scm.providers[] with provider and baseUrl; github and gitlab default
  to their hosted endpoints, gitea and other self-hosted instances require
  a base URL and are skipped with a warning when it is missing
- derive the provider list from the enabled OAuth2 providers when
  scm.providers is empty, so existing configurations keep working
- expose Configuration.ResolveScmProviders and Configuration.ScmProvider
- add auth.credentialKey for the master key that encrypts SCM credentials
  at rest, plus the credential.master_key settings key used as fallback

conf/config.yaml, both configuration docs and the Helm chart (values and
configmap) document the two new sections.

Verification:
- go test -run "TestConfigurationScm|TestConfigurationResolveScm" -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/config/...
- helm template test ./deploy/sigma
2026-10-27 21:07:20 +08:00
Tosone 867a26a23c feat(crypt): add authenticated AES-GCM seal/open helpers
Encrypt/Decrypt are AES-CTR without a MAC, so a stored ciphertext can be
altered without detection. The only current caller derives a per-build key
from the builder and runner IDs, which is fine for the short-lived build
environment but cannot be used for values that outlive a process.

Add Seal/Open on top of AES-256-GCM (base64(nonce|ciphertext|tag)) next to
the existing helpers instead of changing them: the builder image still
decrypts the CTR format with crypt.Decrypt. The key is derived with
sha256 like Encrypt, so operators only deal with one key convention.

Verification:
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/utils/crypt/...
2026-10-27 21:07:15 +08:00
Tosone 187f5c4d97 refactor(server)!: remove the embedded MCP server
Sigma shipped three overlapping ways to operate a remote server: the
embedded MCP server, sigma-cli, and the sigma-api-operator skill. All
three wrapped the same HTTP API, yet each covered a different subset:
user CRUD existed only in the CLI, system-* only in MCP, and builders,
daemons, webhooks, validators, code repositories and tokens were
reachable only through raw HTTP. MCP was disabled by default and still
carried 1246 lines of production code plus 606 lines of tests to
maintain that partially overlapping surface.

Keep two surfaces instead: sigma-cli for execution and the skill for
API discovery.

- delete pkg/server/mcp and its mcp-go dependency, which also drops the
  jsonschema-go, jsonschema/v6 and uritemplate/v3 transitives
- drop ConfigurationMCP, its defaults and the authz/audit skipper
  bypasses that existed only to let the MCP endpoint bypass both
- remove the mcp section from conf/config*.yaml, docs/configuration.md,
  and the Helm chart values and configmap
- replace docs/mcp.md with docs/cli.md covering sigma-cli login, global
  flags, per-resource commands, jq composition and agent usage
- make sigma-cli the preferred path in the sigma-api-operator skill and
  rebuild its examples around the resources the CLI does not wrap yet,
  using the paths and request schemas from swagger.yaml

Lint was already red on dev for an unrelated reason: golangci-lint
v2.13.0 vendors golang.org/x/tools v0.49.0, which only decodes export
data version 4, so every import of a Go 1.27.2 standard library package
failed typecheck with "export data version 5 is greater than maximum
supported version 4". Bump to v2.15.0 (x/tools v0.52.0) and fix the two
modernize findings it reports for Go 1.27's strings.CutLast.

- .github/workflows/lint.yml: golangci-lint v2.13.0 -> v2.15.0, and
  document the export data constraint next to the pin
- pkg/authz/resolver.go, pkg/logger/logger.go: replace LastIndex slicing
  with strings.CutLast
- bump github.com/docker/cli v29.9.0 -> v29.9.1

BREAKING CHANGE: the `mcp` configuration section and the /api/v1/mcp
endpoint are gone. Use sigma-cli or the REST API for automation.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- golangci-lint v2.15.0 run --build-tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./... (0 issues)
- golangci-lint config verify
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/authz/... ./pkg/logger/... ./cmd/cli/... ./pkg/app/... ./pkg/background/build/...
- go test -run TestConfiguration -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/config/...
- go mod tidy
- make swagen
- helm template sigma ./deploy/sigma
- bun run docs:build
- make build
- make build-cli
2026-10-21 19:33:07 +08:00
Tosone 940ab15dd4 build(deps): bump grype, syft, buildkit and other dependencies
Update direct Go module dependencies to their latest patch/minor
releases, including security and bug fixes across registry,
scanning, storage and build backends. Align the grype, syft,
buildkit, cosign and swagger-ui versions pinned in the Dockerfile
with their upstream releases.

Direct upgrades:
- github.com/alicebob/miniredis/v2 v2.39.0 -> v2.40.0
- github.com/anchore/grype v0.120.0 -> v0.121.0
- github.com/anchore/syft v1.54.0 -> v1.55.0
- github.com/aws/aws-sdk-go-v2 v1.47.1 -> v1.47.3
- github.com/aws/aws-sdk-go-v2/config v1.33.6 -> v1.33.9
- github.com/aws/aws-sdk-go-v2/service/s3 v1.114.0 -> v1.114.3
- github.com/aws/smithy-go v1.28.2 -> v1.28.5
- github.com/docker/cli v29.8.2+incompatible -> v29.9.2+incompatible
- github.com/mark3labs/mcp-go v1.1.1 -> v1.2.1
- github.com/moby/buildkit v0.33.1 -> v0.34.1
- github.com/pressly/goose/v3 v3.28.0 -> v3.29.0
- github.com/prometheus/client_golang v1.24.1 -> v1.25.0
- github.com/sigstore/cosign/v3 v3.1.3 -> v3.1.4
- go.podman.io/podman/v6 v6.1.3 -> v6.1.4
- golang.org/x/crypto v0.57.0 -> v0.58.0
- golang.org/x/net v0.59.0 -> v0.61.0
- golang.org/x/sync v0.23.0 -> v0.24.0
- turso.tech/database/tursogo v0.8.2 -> v0.8.3

Dockerfile:
- build/Dockerfile: SYFT_VERSION 1.54.0 -> 1.55.0, GRYPE_VERSION
  0.120.0 -> 0.121.0, COSIGN_VERSION v3.1.3 -> v3.1.4,
  SWAGGER_UI_VERSION 5.33.1 -> 5.33.2, BUILDKIT_VERSION
  v0.33.1-rootless -> v0.34.1-rootless

Notable transitive bumps: grpc 1.83.2 -> 1.84.0, prometheus/common
0.70.1 -> 0.72.0, sigstore/sigstore 1.10.8 -> v1.11.1,
sigstore/sigstore-go v1.2.2 -> v1.3.0, rekor v1.5.3 -> v1.5.4,
go-openapi v0.x -> v1.0.0 across analysis/spec/validate,
google.golang.org/api v0.294.0 -> v0.301.0,
klauspost/compress 1.20.0 -> 1.20.1, and the podman buildah/storage
modules.

cloud.google.com/go/auth resolves to the pseudo-version
v0.24.1-0.20261001053825-dbc26066f70a because the cosign KMS/GCS
dependency chain requires a commit that has no tagged release yet.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- golangci-lint v2.15.0 run --build-tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" (0 issues)
- go mod tidy
2026-10-21 19:32:35 +08:00
Tosone 10269798be refactor(web): migrate legacy accent colors to design tokens
The legacy pages still used scattered Tailwind colors (purple, blue,
indigo) as interactive accents, so the app drifted away from the single
neutral `--primary` accent of the design system. Replace them with tokens:

- purple primary buttons -> bg-primary / text-primary-foreground
- gray secondary buttons -> bg-secondary
- indigo active tabs -> border-primary / text-foreground
- purple and indigo focus rings -> focus:ring-ring
- blue switches -> peer-checked:bg-primary, with the knob switched to
  primary-foreground while checked so it stays visible in dark mode
- blue checkboxes -> accent-primary
- blue links and the Dockerfile editor selection -> text-primary and
  selection:bg-foreground

Verification:
- cd web && npx oxlint
- cd web && bun run build
2026-10-11 09:31:17 +08:00
Tosone 3e4f4c8564 fix(web): use the background token for page shells
The legacy page shells hardcoded `bg-white` without a dark variant, so
the whole page rendered white in dark mode. Use the `bg-background`
token, matching the pages that were already migrated.

Verification:
- cd web && npx oxlint
- cd web && bun run build
2026-10-11 09:31:09 +08:00
Tosone 4d29fb868c docs: redesign the documentation homepage
Rebuild the VitePress home page around the sigma brand: a compact
one-line hero with a terminal-style rotating tagline and a copyable
install command, a six-tile capability grid, and new Vue sections for a
quick start terminal, the architecture diagram, and a closing CTA.

Apply the logo's warm orange palette with dark-mode-aware accents, load
Nunito for all Latin text from the Fontsource jsDelivr CDN, and align
every section gutter with the hero and feature grid so the content shares
one width. Keep the hero title, the Architecture lead and the closing CTA
on a single line where the viewport allows.

Verification:
- cd docs && npx vitepress build
- checked light/dark and mobile layouts in headless Chrome
2026-10-10 19:37:45 +08:00
Tosone 7b98fc29c0 refactor(server): simplify handler wrapping and request binding
Remove the unused Wrap/WrapHandle helpers and the HandlerFunc type; route
registration now passes handler method values directly. Drop the
unreachable application/x-www-form-urlencoded and multipart/form-data
branches in bindBody since every bound endpoint is JSON, and merge
adapter.go into request.go. Add tests for the query/param mapping error
paths, the nil-validator path, and non-JSON bodies, raising the package
coverage to 100%.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/server/
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/server/...
- go tool cover -func: pkg/server 100.0% of statements
2026-10-07 21:07:06 +08:00
Tosone ffe28bb78e refactor(api): rename UserStatus Deactive to Inactive
"Deactive" is not a valid English word; the standard antonym of "Active"
is "Inactive". Restore the enum value, regenerate the go-enum output,
update the CLI test expectation, sync the generated swagger enum and
x-enum-varnames, and fix the web UI request payload and label.

Note: persisted rows and API clients using the old "Deactive" value must
switch to "Inactive"; no data migration is included.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/api/enums/... ./cmd/cli/...
- CI_DATABASE_TYPE=turso go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/server/validators/...
2026-10-07 20:56:24 +08:00
Tosone 00735de3b1 feat(web): use Nunito as the primary font
Load Nunito (variable, normal and italic) from Fontsource and put it
first in the `--font-sans` stack, keeping Geist as a fallback so
characters missing from Nunito still render.

Also bump the sidebar `sigma` wordmark from `text-sm` to `text-lg` so
the wordmark reads more clearly next to the 32px logo mark.

Verification:
- bun run lint
- bun run build
2026-10-06 23:28:43 +08:00
Tosone 7c2c45884a build(deps): bump go and web dependencies
Update Go modules and web packages to their latest available versions.

Go:
- github.com/go-git/go-git/v6 v6.0.0-alpha.5 -> v6.0.0-beta.1
- github.com/redis/go-redis/v9 and redisotel v9.22.0 -> v9.23.0
- github.com/tidwall/gjson v1.19.0 -> v1.20.0
- turso.tech/database/tursogo v0.8.1 -> v0.8.2
- transitive: go-billy/v6 beta.1, ProtonMail/go-crypto 1.5.2,
  pjbgf/sha1cd 0.7.0, go.uber.org/atomic 1.12.0

Web:
- @fontsource-variable/nunito 5.3.0 (new)
- @vitejs/plugin-react 5.2.0 -> 6.1.2
- @tanstack/react-query 5.104.0 -> 5.104.1
- cron-parser 4.9.0 -> 5.10.1
- lucide-react 1.49.0 -> 1.52.0
- shadcn 4.21.1 -> 4.21.3
- vite 8.3.2 -> 8.3.3
- oxlint 1.86.0 -> 1.87.0
- postcss 8.5.28 -> 8.5.29
- postcss-import 16.2.0 -> 17.0.0
- postcss-nesting 13.0.2 -> 14.0.3
- @types/node 25.9.9 -> 26.6.4

Adapt to the cron-parser v5 API, where the default `parseExpression`
export was replaced by the named `CronExpressionParser.parse`.

Verification:
- go mod tidy
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- bun run lint
- bun run build
2026-10-06 23:28:41 +08:00
Tosone 14df8a87d4 style(web): sort imports into third-party and local groups
Reorder imports across web/src into two blocks separated by a blank line:
third-party packages first, then this repository's @/ and relative modules,
each sorted alphabetically. Document the convention in AGENTS.md.

Verification:
- web: `npx tsc --noEmit`, `npx oxlint`, `npx vite build`
2026-10-04 19:59:27 +08:00
Tosone c5851c81d2 build(deps): bump grype, otel and other dependencies
Upgrade github.com/anchore/grype to v0.120.0, github.com/aws/smithy-go to
v1.28.2, github.com/lmittmann/tint to v1.2.1, and the go.opentelemetry.io
modules (otel, otel/sdk, otel/trace, otlptracegrpc, otlptracehttp, otelgin,
otelhttp) to v1.47.0/v0.72.0, together with the transitive bumps they pull
in. Install tzdata in the alpine runtime image so named timezones are
available at runtime.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
2026-10-04 19:59:22 +08:00
Tosone cb982ec37c feat(config): add email for the initial administrator account
Populate auth.admin.email in the example configurations, docs and Helm
values so the bootstrap sets the initial administrator's email address.

Verification:
- parsed conf/config*.yaml and confirmed auth.admin.email is read
2026-10-04 17:07:50 +08:00
Tosone 01e1c6f94f build(deps): bump cosign to v3.1.3
Update github.com/sigstore/cosign from v2.6.5 to v3.1.3 and switch the
import path in the signing bootstrap to the v3 module. go.sum also picks
up the transitive lib/pq and go.step.sm/crypto bumps.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go vet -tags "..." ./pkg/app/bootstrap/...
2026-10-04 16:43:15 +08:00
Tosone 4cbddc95ab style(web): organize code repository imports 2026-10-04 16:35:32 +08:00
Tosone 2a61be0cbf fix(web): keep namespace form select popups at trigger width
Drop the shared minimum popup width on the create and update namespace
visibility and size-limit unit selects so each popup matches its trigger.

Verification:
- web: `npx tsc --noEmit`, `npx oxlint`, `npx vite build`
2026-10-04 16:35:32 +08:00
Tosone f4ccd565f6 feat(web): add icons to daemon task actions
Add a SquarePen icon for Update and a Play icon for Run in the four GC
action menus, and tidy the page formatting.

Verification:
- web: `npx tsc --noEmit`, `npx oxlint`, `npx vite build`
2026-10-04 16:35:23 +08:00
Tosone ce781cdff7 feat(web): manage user status and role in settings
- right align the namespace count and status columns, and rename the
  namespace header to "Namespace count"
- render last login and created at with RelativeTime
- replace the inline update button with a centered three-dot menu whose
  Deactive action calls PUT /users/{id} to deactivate the user
- drop the status field from the update dialog, disable the role select
  for the signed in user, and omit role/status when updating self

Verification:
- web: `npx tsc --noEmit`, `npx oxlint`, `npx vite build`
2026-10-04 16:35:17 +08:00
Tosone bbd7308153 fix(web): refine select and dropdown menu interactions
Open select popups below the trigger instead of covering it, show a
pointer cursor on select options, give options more vertical room, and
use a not-allowed cursor for disabled selects and menu items.

Verification:
- web: `npx tsc --noEmit`, `npx oxlint`, `npx vite build`
2026-10-04 16:35:11 +08:00
Tosone 7ad608c2f8 feat(handler): protect a user's own status and role
Reject self status or role changes with 403 in the user update handler,
and make the user service persist role updates so administrators can still
manage other users' roles.

Verification:
- go build -tags "..." ./pkg/service/users/... ./pkg/server/handlers/users/...
2026-10-04 16:35:04 +08:00
Tosone d2f02d1db4 refactor(api): rename user status inactive to deactive
Rename the UserStatus enum value Inactive to Deactive, regenerate the
go-enum output, update the CLI test expectation and sync the generated
swagger enum and x-enum-varnames.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
- go test -tags "..." ./cmd/cli/... ./pkg/server/validators/...
2026-10-04 16:34:58 +08:00
Tosone b8ef92eba1 feat(web): restructure sidebar menu and polish user list
Rebuild the sidebar menu as a context-driven hierarchy so every
collapsible group has real children:

- add a Home entry and list namespaces under Namespaces, merging the
  former hot-namespace group; the active namespace is always shown and
  expanded even when it is not hot
- nest the namespace sections (summary, repositories, members, daemon
  tasks, webhooks) and the active repository sections (summary, tags,
  builder) under the current branch, using SidebarMenuSub so children
  share a vertical guide line
- expose the enabled code repository providers (github, gitlab) under
  Code Repository and fall back to a plain link when none is enabled
- drive expansion and highlighting from the route only, highlighting the
  selected leaf instead of its container rows
- add a Base UI collapsible primitive, align the sidebar menu metrics
  with the content lists (h-9/text-sm items, h-8 sub items, sidebar-accent
  active state), use a neutral gray for the sidebar text both when idle
  and selected, and drop the unused --sidebar-active token
- add the menu.allNamespaces message

Also polish the settings user list: un-bold the header and username, show
last login and created at with RelativeTime, and replace the inline update
button with a centered three-dot dropdown.

Verification:
- web: `npx tsc --noEmit`
- web: `npx oxlint`
- web: `npx vite build`
2026-10-04 12:03:21 +08:00
Tosone 8389a3080c build(docker): bump build tool versions
Update the pinned tool versions in the builder image:
- buildkit v0.33.0-rootless -> v0.33.1-rootless
- swagger-ui 5.33.0 -> 5.33.1
- syft 1.51.1 -> 1.54.0
- grype 0.118.0 -> 0.120.0
- cosign v2.6.1 -> v3.1.3
2026-10-04 09:03:15 +08:00
Tosone 3958a6b61d docs(swagger): align handler API annotations with implementation
Fix and complete Swagger annotations for the HTTP handlers so the
generated OpenAPI spec matches the registered routes and request
types:

- Correct path parameter types from number/int64 to string, since all
  resource IDs are UUID strings.
- Fix wrong router paths and methods (builders, coderepos, tags,
  webhooks, users, validators) and add missing path parameters.
- Fix request/response schema references (builder runner list, oauth2
  callback, webhook get/log) and a few summary/description typos.
- Add annotations for previously undocumented endpoints: artifacts,
  analytics, builder runner actions, and user self/signup/recovery.
- Rename the users and coderepos path parameters to user_id/repo_id and
  align the route registrations and request struct tags accordingly;
  mark BuilderRunnerItem.Log as swaggertype string so swag can parse it.
- Regenerate tools/skill/sigma-api-operator/swagger.yaml. The
  distribution handlers are intentionally left undocumented.

Verification:
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/server/handlers/users/ ./pkg/server/handlers/coderepos/ -run TestInitialize -count=1
- go tool swag fmt && go tool swag init --output tools/skill/sigma-api-operator --outputTypes yaml
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/server/handlers/... ./pkg/api/...
- gofmt -l pkg/server/handlers pkg/api
2026-10-03 21:51:37 +08:00
Tosone 20af519812 fix(handler): log original error instead of rebuilding it
Replace `errors.New(utils.UnwrapJoinedErrors(err))` with the original `err`
in slog error logging so the logged value keeps its error chain for
`errors.Is`/`errors.As` classification. Also drop the duplicated `err`
attribute in the namespace handlers.

Verification:
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/server/handlers/...
2026-10-03 21:14:08 +08:00
Tosone ee12dbda37 docs(agents): document lint version, govulncheck and storage tests
Sync the golangci-lint version, note the new govulncheck workflow, drop
the removed codeql.yml reference, and record that the pkg/storage test
suites are run manually against cloud resources.
2026-10-03 16:20:36 +08:00
Tosone 9d0affcd12 build(ci): pin govulncheck and add a non-blocking scan workflow
Add golang.org/x/vuln/cmd/govulncheck to the go.mod tool set and run it
in a dedicated workflow with the project build tags. The report is
written to GITHUB_STEP_SUMMARY and the step is non-blocking so findings
are reported without failing CI.

Verification:
- go tool govulncheck -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
2026-10-03 16:20:36 +08:00
Tosone 1fefe15ea5 refactor(test): use t.Context in unit tests
Replace context.Background() with t.Context() so test contexts are
canceled when the test ends, which surfaces leaked background work. The
pkg/storage suites are intentionally left unchanged because they run
manually against cloud resources.

Verification:
- go vet ./...
2026-10-03 16:20:36 +08:00
Tosone 2cc50352ce refactor(clients): propagate request context through registry clients
Thread the caller context through ClientsFactory.New and
Clients.AuthToken so proxied blob and manifest requests keep
cancellation and trace propagation instead of starting from
context.Background(). Regenerate the mock and update callers and tests.
Document the intentionally background contexts in the one-shot builder
CLI.

Verification:
- go generate ./pkg/distribution/clients/... (no diff)
- go vet ./...
2026-10-03 16:20:36 +08:00
Tosone d2d9e94c12 build(lint): enable the modernize linter
Turn on golangci-lint's modernize linter so the go fix modernizations
are enforced going forward.

Verification:
- golangci-lint run (0 issues)
2026-10-03 16:20:36 +08:00
Tosone c6b0f93ff4 refactor: apply go fix modernizations
Adopt modern Go and stdlib idioms surfaced by the modernize analyzer:
promote embedded fields in struct literals, and replace hand-written
equivalents with maps.Copy, min, atomic.Int64, new(expr) and
slices.SortStableFunc.

Verification:
- go fix -diff ./... (no remaining changes)
- go vet ./...
2026-10-03 16:20:36 +08:00
Tosone e7df1342b5 refactor(web): modernize namespace page and use @ import alias
Reformat the page, switch relative imports to the @ alias, replace the
inline update/delete buttons with a dropdown row-actions menu, and use
exponentiation for the TiB/GiB/MiB size conversion.

Verification:
- cd web && bunx tsc --noEmit
- cd web && bun run lint
2026-10-03 00:33:57 +08:00
Tosone 95c6006fa1 fix(web): use exponentiation for size unit conversions
JavaScript bitwise shifts operate on 32-bit integers, so `1 << 40` evaluates
to `1 << 8` (256) instead of 1 TiB, corrupting TiB size limits and the
calcUnit TiB branch. Replace the shifts with exponentiation.

Verification:
- cd web && bunx tsc --noEmit
- cd web && bun run lint
2026-10-03 00:27:26 +08:00
Tosone 217cec5829 build(deps): bump go and web dependencies
- Update go.mod/go.sum (grype, syft, aws-sdk-go-v2, distribution,
  gin contrib, validator and others).
- Update web/package.json and web/bun.lock (shikijs, react-router-dom,
  lucide-react, oxlint, esbuild, vite and others).
- Ignore the local `.delta/` directory in .gitignore.
2026-10-02 23:36:56 +08:00
Tosone dbd9601947 refactor(web): unify namespace UI and modernize tables, tabs and dialogs
- Add a shared NamespaceTabs component and use underline tabs across the
  namespace summary, repository, member, daemon task and webhook pages.
- Redesign the pagination footer with theme tokens and a page indicator,
  and give previous/next proper pointer and disabled states.
- Align the daemon task and webhook table headers with the namespace list
  style, drop bold text, and use a muted header color.
- Convert the namespace member list to the shadcn Table component and
  match the search/create toolbar height.
- Modernize the webhook create dialog (Input, Label, Switch, two-column
  events) and unify button and input styles.
- Make the namespace summary markdown editor fill the available height.
- Stay silent on 404/empty responses for the namespace summary, member
  and webhook requests instead of showing an error toast.
- Add standard `appearance` declarations and update deprecated Tailwind
  classes to clear editor warnings.

Verification: bunx tsc --noEmit; bunx oxlint; bun run build (web)
2026-10-02 23:34:29 +08:00
Tosone eca764eda4 test(logger): split coverage tests by covered source file
Drop the coverage_test.go catch-all and distribute its cases to the test
files matching the units they exercise: logger_test.go for logger.go,
glog_test.go for glog.go, and a new trace_handler_test.go for the trace
handler.

Verification:
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/logger/
- golangci-lint run --build-tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/logger/...
2026-09-28 21:24:36 +08:00
Tosone 44440383a4 ci(testkit): exclude pkg/testkit from unit tests
The testkit package only provides test helpers, so skip it in the unit-test
package matrix and coverage run, matching the other infrastructure-only
excludes.
2026-09-28 21:24:33 +08:00
Tosone f6d7a97cdf fix(rs3): probe /readyz and drop unused RS3_ENDPOINT
The rs3 server binary never reads RS3_ENDPOINT; it is a client-only setting
for rs3-cli, which only the old healthcheck used. Switch the rs3 healthcheck
to `curl --fail .../readyz` with a start period (matching scripts/run_rs3.sh
and CI) and remove the now-dead RS3_ENDPOINT from compose.yml, the demo-server
compose, run_rs3.sh, and the test workflow.

Verification:
- git grep RS3_ENDPOINT -> no matches
- docker compose config for compose.yml and tools/demo-server/compose.yml
2026-09-28 20:55:25 +08:00
Tosone bb9b02adf4 test(storage): remove stray filesystem test artifacts
These files are created and deleted by the filesystem storage tests at
runtime and were committed by accident; drop them from the tree.
2026-09-28 20:55:25 +08:00
Tosone 7dd41773a5 docs(ptr): remove stale generated README
The gomarkdoc output referenced the upstream code.byted.org import path and
is not maintained for this package.
2026-09-28 20:55:25 +08:00
Tosone 47dc5db656 docs(todo): move non-HA backlog above completed list
Promote the password recovery flow to its own backlog section and renumber
the completed items so the remaining non-HA work is grouped together.
2026-09-28 20:55:25 +08:00
Tosone 747da40b7d test(utils): generate hash and compress fixtures at runtime
Delete the checked-in ci.txt and test.txt fixtures and write them into
t.TempDir() inside the hash and compress tests, keeping the fixture content
in package constants so the expected digests stay unchanged.

Verification:
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/utils/hash/ ./pkg/utils/compress/
2026-09-28 20:55:25 +08:00
Tosone ed3b2d2563 docs(hash): translate comments to English
Translate the remaining Chinese doc comments on FileVerify, String, and File
into English, and drop the unused package-only doc.go file.
2026-09-28 20:32:19 +08:00
Tosone 3327863518 refactor(infra): move mocks into per-package mocks subpackages
Move the cache, counter, lock, and workq mock files from their package
directories into a `mocks` subpackage, matching the existing service and
storage layout. Update the `//go:generate` directives to emit into
`mocks/*_mocks.go` with package `mocks`, regenerate the files, and document
the convention in AGENTS.md.

Verification:
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/infra/...
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/infra/...
2026-09-28 20:32:17 +08:00
Tosone 44fd74b66d test(logger): raise package coverage to 100%
Add tests for SetLevel branches, source trimming, the log writer error path,
formatLogLine error branches, gorm trace logging, the Logger methods, both
Fatal helpers (via a re-exec subprocess) and the trace handler.

Split databaseTraceCall into a thin wrapper plus databaseTraceCallFrom(caller)
so the stack walk can be tested with a fake caller; the behavior is unchanged.
2026-09-27 14:57:02 +08:00
Tosone 9ec5d37b28 refactor(server): move request validators under server
pkg/validators is the gin request-validation layer: it registers gin's
binding.Validator and is used by the HTTP handlers, so move it to
pkg/server/validators where the rest of the HTTP layer lives.

The only non-server consumer was pkg/background/daemon, which called
validators.Initialize() even though the worker never uses gin binding
validation. Drop that call so the worker does not depend on the server
package; the server still initializes validators through
handlers.Initialize.
2026-09-27 14:57:02 +08:00
Tosone d516c5707c refactor(storage): move storage mock into a mocks subpackage
Move pkg/storage/storage_mocks.go to pkg/storage/mocks/ (package mocks) so the
generated mock is not counted in the storage package coverage, and update the
//go:generate directive and the tests that referenced the mock.
2026-09-27 12:37:00 +08:00
Tosone 9a7e6c8655 test(telemetry): cover context helpers and tracer initialization
Add tests for every context helper and for Init across disabled, http, grpc
and invalid protocol configurations, raising coverage from 21.6% to 98.6%.

This also surfaced a real bug: Init failed when tracing was enabled because
resource.Default() (schema 1.43.0) conflicted with semconv.SchemaURL
(1.26.0). Build the service name resource schemaless so Init succeeds.
2026-09-27 12:37:00 +08:00
Tosone fb7f20e8c4 refactor(service): move service mocks into per-domain mocks subpackages
Move every pkg/service/<domain>/*_mocks.go into pkg/service/<domain>/mocks/
(package mocks) so generated mocks are no longer part of the packages under
test and stop depressing their coverage. Update the //go:generate directives
and the tests that referenced the mocks.
2026-09-27 12:37:00 +08:00
Tosone fe9b072a11 chore: consolidate validators coverage, repository mocks and test database
Raise the validators package coverage from 49.2% to 97.1% with table-driven
tests for every validation function and fold the repetitive RegisterValidation
checks in newValidator into one loop.

Move the repository mocks out of the packages under test into per-domain mocks
subpackages, update the //go:generate directives and test imports, skip the
mocks packages in the CI test matrix and drop the unused Codecov config.

Default InitializeIntegration to the turso dialect so integration tests run
locally without a PostgreSQL server.
2026-09-27 12:37:00 +08:00
Tosone c70127b0d1 feat(config): initialize namespaces from configuration
Replace the hard-coded library namespace seed with an idempotent bootstrap
task driven by a new namespace.initialize config list, so users can declare
any number of namespaces and set the visibility of each one (public or
private). The task only creates namespaces that do not exist yet.

Remove the seed INSERT from the four 0001 migrations and wire the new config
into the example configs, the docs and the Helm chart (values + configmap).
2026-09-27 11:11:04 +08:00
Tosone 93cf7c1946 chore(dal): document UserRecoverCode and track its recovery gap
Add an explicit TableName() for UserRecoverCode and document that the
password recovery backend is wired up (endpoints, service, repository and
generated query) but the code is never delivered to users and the web UI has
no recover pages. Track the remaining work in TODO.md.
2026-09-27 11:10:47 +08:00
Tosone 68c4cb8be1 chore(dal): remove unused Locker model
pkg/dal/models/locker.go is dead code: it is absent from the gorm-gen model
list in pkg/dal/cmd/gen.go, has no generated query, and no migration creates
a lockers table. Locking is handled by pkg/infra/lock instead.
2026-09-27 11:10:43 +08:00
Tosone 2009156bf5 ci: replace Minio with rs3 and make E2E CI run
Run the self-hosted rs3 service instead of Minio in test.yml and swap the
local helper script, Makefile helm values, and AGENTS.md notes accordingly.

Fix the E2E workflow (refs #426): it only triggered on the `main` branch,
which does not exist in this repository, so the job never ran. Trigger it
on `dev` for both push and pull_request like test.yml, build the image via
the consolidated `make docker-build`, bump the checkout/setup-go actions,
drop the hosted-toolcache cleanup, and refresh the E2E tooling to k6
v2.3.0 and skopeo v1.24.1.

Repair the image startup path as well: start nginx with an explicit
/etc/nginx/nginx.conf and a /dev/stderr error log so the non-root user does
not touch the compiled-in log path, create /etc/sigma with mode 0755 before
copying config.yaml (COPY --chmod made the directory non-traversable), and
disable redis in the shipped default config since cache, locker and work
queue are inmemory.
2026-09-26 19:42:46 +08:00
Tosone f054f7bdd1 chore: add YAML language server schema hints and pin node in mise
Reference JSON schemas at the top of CI workflows and tool configs so
editors can validate and autocomplete them, and add node to mise.toml.
2026-09-26 12:36:33 +08:00
Tosone d1d15108c8 ci: switch coverage upload from Codecov to Coveralls
Replace the codecov/codecov-action step with coverallsapp/github-action,
using COVERALLS_REPO_TOKEN and the golang format for the Go coverprofiles
emitted by `go test -coverprofile`. Update the README badges and the CI
workflow notes so no references to Codecov remain.

Verification:
- Ruby YAML parse of .github/workflows/test.yml
2026-09-20 13:34:09 +08:00
Tosone 2ac08864f6 ci(lint): run oxlint for the web app
Add a `Lint web` step to the lint workflow so the frontend gets the same
treatment as the Go code. It reuses the dependencies installed by the
existing `Build web` step (same job, same bun cache) and runs
`bun run lint`, which is the oxlint invocation configured in
web/package.json and web/.oxlintrc.json — no extra setup or duplicated
dependency install required.

Verification: parsed the workflow YAML and confirmed the step order is
Checkout -> Setup golang -> Setup bun -> Cache bun -> Build web ->
Lint web -> Run golangci-lint -> Lint Dockerfile; `cd web && bun run lint`
exits 0 locally (0 warnings, 0 errors).
2026-09-17 16:16:25 +08:00
Tosone 3b99c1d305 chore(web): enable react/perf lint rules and resolve every finding
Turn on the react, react-hooks, suspicious and perf rule sets in oxlint and
fix the 2665 diagnostics they report instead of muting the rules:

- validation/limit state is derived during render instead of being synced
  in an effect (namespace/repository/tag limits, size limit + unit,
  username/email/password checks in Menu, Users, Webhook and Member)
- refetch triggers are gone: mutation handlers now call the memoized fetcher
  directly (Namespace list and members, Menu token timer) instead of bumping
  a `refresh` state that only existed to re-run an effect
- data fetchers (fetchNamespace/fetchTags/fetchRepository/fetchWebhook/
  fetchMembers/logout) are memoized with useCallback and their effects use
  correct dependency arrays; the async profile seeding uses an override state
  instead of an effect
- fix 39 shadowed variables (resp/err/*ListData/configData/requestUrl/...),
  use stable list keys instead of array indexes, hoist `cutDigest` to module
  scope and memoize the ToggleGroup context value
- replace the ported HTML5 email pattern with a zod based `isEmail` helper
  (zod 4, `z.email()`), dropping the control-character regex
- use-mobile seeds its state lazily and Shiki derives the highlighted html
  with useMemo

.oxlintrc.json pins the setup: plugins react/typescript/unicorn/oxc,
correctness as error, suspicious/perf as warn, `_`-prefixed names ignored by
no-unused-vars, and react-in-jsx-scope off because the app uses the React 19
automatic JSX runtime (that rule only applies to React < 17).

Verification: web: `bun run lint` (0 warnings, 0 errors, no
oxlint-disable directives left in src); `tsc --noEmit`; `vite build`;
unused-import scan reports 0.
2026-09-17 16:13:02 +08:00
Tosone 8bb35e880b chore(web): clear oxlint warnings and pin its configuration
Fix the diagnostics that oxlint reports on the codebase instead of
silencing the rules:

- unused event parameters (41): `onClick={e => ...}` -> `onClick={() => ...}`
  and `.catch(err => ...)` -> `.catch(() => ...)` where the argument was
  never used
- unused state members: keep only the half that is used
  (`const [sortOrder] = useState(...)`, `const [, setUserObj] = ...`), and
  drop the sort state in CodeRepository/List that was fully unused
- unused props/locals: drop `index` from TableItem/TableItemDropdown (plus
  interface and call sites), `namespace`/`repository` from Tag TableItem,
  two dead `const user = ...` in Login/Callback and the unused `u` URL in
  Webhook/List, along with the imports that became unused (IUserSelf, IOrder)
- one-line effects (10): `useEffect(() => { cond && setX() }, [dep])` ->
  explicit `if (cond) { setX(); }`
- utils/index.ts: keep the HTML5 email pattern as-is with a scoped
  `oxlint-disable-next-line no-control-regex` and a reason

Add .oxlintrc.json to pin the setup: correctness rules are errors,
no-unused-vars ignores `_`-prefixed names, browser/es2024 globals,
dist/node_modules/public ignored. The rule set matches the previous
defaults, so nothing is disabled to hide a warning.

Verification: web: `bun run lint` (0 warnings, 0 errors); `tsc --noEmit`;
`vite build`; unused-import scan reports 0.
2026-09-17 15:40:19 +08:00
Tosone 3ca56e7b67 refactor(web): replace @headlessui/react with shadcn components
Swap every headlessui usage for the shadcn/base-ui components that are
already bundled in the app, then drop the dependency:

- menus (8): Menu/MenuButton/MenuItems/MenuItem + Transition -> DropdownMenu;
  role checks that guarded the original clicks are preserved as
  DropdownMenuItem `disabled`
- dialogs (14): Dialog/DialogPanel/DialogTitle + Transition* -> Dialog,
  DialogContent, DialogTitle, DialogDescription, DialogFooter and Button
- listboxes (6): Listbox -> Select; the multiple-selection one becomes a
  DropdownMenu with DropdownMenuCheckboxItem
- comboboxes (9): Combobox -> Popover + Command, wiring the existing search
  state into CommandInput and keeping shouldFilter={false} for server-side
  search
- remove @headlessui/react from package.json/bun.lock

Also included:
- drop imports that became unused (Table/Button in Builder/RunnerList,
  Separator, useSidebar, dayjs, Link/useParams, Check/ChevronsUpDown and the
  leftover shadcn imports in the webhook pages)
- replace Tailwind v4 arbitrary sizes that have spacing-scale equivalents
  (w-[350px] -> w-87.5, h-[36px] -> h-9, after:top-[2px] -> after:top-0.5, ...);
  h-[18.4px] is intentionally kept since 4.6 is not a multiple of 0.25
- fix the webhook log delete-confirm label (was "Resend")
- add oxlint with `lint` and `lint:fix` scripts

Verification: web: `tsc --noEmit`; `vite build`; `oxlint` (0 errors,
72 pre-existing warnings); scripted scan reports 0 unused imports and no
remaining @headlessui imports.
2026-09-17 15:31:21 +08:00
Tosone 959b2f2ee6 feat(web): polish layout, sidebar, tables and utils
Follow up the shadcn/ui migration with a round of layout and UX fixes:

- layout: unify the horizontal padding of the page header, page toolbars,
  table headers/cells and pagination on `px-4`, so titles, search boxes and
  the first/last table columns share one left/right baseline while the table
  itself stays full width.
- sidebar: stop the SidebarProvider wrapper (`w-full`) from squeezing the
  page content, enlarge the menu rows, lighten the active background through
  a new `--sidebar-active` token, drop the bold active label, and always show
  a pointer cursor for buttons and menu items.
- user menu: fold API docs, theme and language into the bottom dropdown,
  persist username/email on login, callback and token refresh, fall back to
  "sigma" when no username is known, and expose a Login entry for guests.
- tables: replace the row action dropdown with inline update/delete icon
  buttons (delete in red), right align the Action column, only render sort
  arrows for the active sort, keep namespace/repository names readable on
  hover, and render created/updated columns as relative times.
- components: add `RelativeTime` (dayjs relativeTime + tooltip) and the
  `Field`/`FieldLabel` primitives, rebuild the login page on top of them,
  and bump the shared button/input/select/toggle/tabs presets to h-9.
- home: lay the summary cards out in a responsive grid instead of a fixed
  1600px wide row that overflowed the viewport.
- utils: merge the short helper modules into `utils/index.ts` (trimHTTP,
  calcUnit, Regex, Tooltip) and `utils/request.ts` (axios interceptors plus
  token refresh), leaving only index/request/distros.

Verification:
- `npx tsc --noEmit`
- `npx vite build`
2026-09-16 22:41:24 +08:00
Tosone b10d58b948 build(deps): bump go dependencies and build tool versions
- build/Dockerfile: swagger-ui 5.33.0, syft 1.51.1, grype 0.118.0
- go.mod: aws-sdk-go-v2 config/credentials/kms/sts, docker/cli 29.8.1,
  mark3labs/mcp-go 1.1.0, go.podman.io/* 6.1.2, gorm postgres driver 1.6.3
- add mise.toml pinning the Go and Bun toolchain versions

Verification: go mod verify; go build -tags
"netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./...
2026-09-16 20:04:43 +08:00
Tosone 2723ffb4b0 test(service): add unit tests for distribution, daemons, oauth2, and manifest services
Add mock-based unit tests to five service packages, raising statement
coverage on the business-logic layer:

- distribution/upload: 5.6% -> 54.0%
- distribution/blob: 9.8% -> 31.1%
- daemons: 0.6% -> 48.6%
- oauth2: 2.7% -> 22.8%
- distribution/manifest: 27.1% -> 34.1%

Tests cover error mapping (not-found vs internal), auth branches (Basic
password verify / Bearer token validate), namespace ownership checks, GC
rule/runner/record get-list across all four GC types, digest verification,
redirect handling, and artifact-type classification.

Transaction success paths (query.Q.Transaction) remain uncovered at the
unit level by design, matching the existing service-test convention; those
paths are exercised by handler/DB tests.

Verification:
- go test -count=1 -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/daemons/ ./pkg/service/oauth2/ ./pkg/service/distribution/manifest/ ./pkg/service/distribution/upload/ ./pkg/service/distribution/blob/
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/daemons/ ./pkg/service/oauth2/ ./pkg/service/distribution/manifest/
2026-09-14 23:19:12 +08:00
Tosone 9cdeabcb2b test(handlers): add handler unit tests for four under-tested packages
Cover webhooks, builders, coderepos and daemons handler packages with
gomock-based tests that assert both the happy paths and the error and
authorization branches:

- webhooks: create/list/get/put/delete, ping, log list/get/delete/resend
- builders: builder CRUD plus runner list/get/run/rerun/stop/log guards
- coderepos: list/get/owners/branches/resync/providers/user3rdparty
- daemons: all 32 gc-* endpoints across blob/tag/repository/artifact

Package statement coverage after this change: webhooks 43.6%, builders
63.7%, coderepos 73.4%, daemons 86.9% (previously ~3-5%).

Verification:
CI_DATABASE_TYPE=turso go test -parallel 1 -failfast   -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp"   -timeout 30m ./pkg/server/handlers/webhooks/... ./pkg/server/handlers/builders/...   ./pkg/server/handlers/coderepos/... ./pkg/server/handlers/daemons/...
gofmt -w <new test files> && golangci-lint run --new
2026-09-14 20:36:36 +08:00
Tosone f677ad3f5f docs: complete placeholder doc comments across the codebase
Replace every `// <Identifier> ...` placeholder doc comment with a real
description of the declared symbol. 276 comments in 71 files were rewritten:
149 top-level placeholders first, then a follow-up scan caught another 127
indented ones (interface methods and const blocks) that a column-anchored
match had missed.

Comments now open with the declared identifier and record the actual
contract - behaviour, side effects, error/panic conditions, units, HTTP
endpoints, lock keys and cache prefixes - instead of restating the
signature. Three placeholders carried a stale identifier and were corrected
to the declared symbol: ConfigurationDatabasePostgresql, GetImageRef and
Initialize.

No functional change: every modified line is a comment.

Verification:
- grep '^\s*//\s+\S+\s+\.\.\.\s*$' over all *.go returns no matches
- gofmt -l over the changed files prints nothing
- CGO_ENABLED=1 go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./... exits 0
- git diff HEAD -U0 filtered to non-comment changed lines is empty
2026-09-14 14:58:06 +08:00
Tosone a7c816494a feat(auth): add login rate limit configuration
Add login failure rate limiting with per-username tracking, supporting both delay-based throttling and lockout via configurable backend.
Update all sample configs, Helm templates, and documentation to include the new auth loginRateLimit settings.

Verification:
All config files, Helm charts, and docs are updated to match the new configuration schema.
2026-09-13 15:26:25 +08:00
Tosone 2adc82c54b refactor(cache): rename package from cacher to cache
Rename the cache module package name from `cacher` to `cache` across all files, including:
- Update all internal package declarations
- Fix import aliases in dependent modules
- Correct mockgen package configuration
- Update cache interface and error type references

This aligns the package naming with the module directory structure and improves consistency across the codebase.
2026-09-13 14:48:06 +08:00
Tosone ac246ad163 feat(authn): throttle failed logins per username
Add a cache-backed failed-login throttler for Basic auth. Once a username
reaches auth.loginRateLimit.maxFailures failures within window, each
subsequent authentication attempt is delayed by delay (capped at 5s)
instead of being rejected; the counter is cleared on a successful login.

- add pkg/infra/ratelimit backed by pkg/infra/cache (inmemory/redis) with
  Count/Incr/Reset and Prometheus metrics for failures, delayed attempts,
  and cache errors
- wire ConfigurationAuthLoginRateLimit with defaults (5 failures, 5m window,
  1s delay) and document it in conf/config.yaml
- integrate the limiter into the authn middleware, counting all Basic
  failures including /v2/, and honor request context cancellation
- add unit tests for threshold behavior, delay, and cancellation
- mark the login rate limit item complete in TODO.md
2026-09-13 12:54:54 +08:00
Tosone d2470bb310 build(deps): bump Go and web dependencies
Update direct and indirect Go module versions, including aws-sdk-go-v2,
goose, ClickHouse, Azure SDK and golang.org/x/exp, and refresh the web
toolchain (react 19.3, vite 8.3, typescript 7, shadcn, tailwind).

Switch the web Vite `@` alias from `__dirname` to `import.meta.dirname`
to align with the ESM config runtime.

Verification: not run (dependency-only change).
2026-09-12 17:16:41 +08:00
Tosone e361e401b0 chore(tools): invoke declared tools via go tool
Use the tools declared in go.mod's tool block (go-enum, addlicense,
swag, mockgen) through the `go tool` prefix, so they resolve via the
module tool directives instead of relying on globally installed
binaries:

- rewrite //go:generate mockgen/go-enum directives to
  `go tool mockgen` / `go tool go-enum` (42 source files)
- switch the Makefile addlicense target to `go tool addlicense`
- regenerate GoMock files with `go generate ./...`, which updates
  the generated-by headers, fixes stale mock signatures, and drops
  the unused MockFactory from runtime_mocks.go

Verification:
- go tool lists go-enum/addlicense/swag/mockgen from go.mod
- go generate ./... completes on enums.go
- go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" \
    ./pkg/background/build/runtime ./pkg/dal/repository/analytics ./pkg/service/token
2026-09-12 11:07:51 +08:00
Tosone 720022de3e refactor(mocks): generate mocks into source packages
Move generated mocks out of the `mocks/` subpackages and into the
source packages as `*_mocks.go` files for `pkg/distribution/clients`
and `pkg/service/password`, updating the go:generate directives to
emit `-package=clients` / `-package=password`. Update the import in
`pkg/service/users/users_test.go` to reference the new location.

Also:
- add `go.uber.org/mock/mockgen` to the tool directives and refresh
  module dependencies
- bump CI service images (mysql 9, postgres 18-alpine) and drop the
  removed mocks packages from the coverage exclusion list
- clean up .gitignore and ignore local tool artifacts (.pi/,
  skills-lock.json)

Verification:
- go vet -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/users/ ./pkg/service/password/ ./pkg/distribution/clients/
- go test -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./pkg/service/users/
2026-09-11 00:19:17 +08:00
Tosone 476df70a60 refactor: replace authz self-built cache with shared infra Cacher
Replace the hand-rolled authz cache (sync.RWMutex + map + dual-index
namespace cache) with the shared pkg/infra/cache Cacher, matching the
existing namespace_cache / repository_cache pattern.

- Inject Config and RedisClientFactory into the authorizer and build the
  Cachers via cacher.NewWithOptions in NewAuthorizer (now returns
  (Authorizer, error))
- Use read-through Cachers for role and namespace lookups; represent
  non-members with negative caching instead of the empty-string sentinel
- Keep the 30s TTL to preserve multi-instance eventual consistency, while
  gaining LRU 2Q, singleflight and an optional Redis backend
- Drop pkg/authz/cache.go and rewrite the cache tests as construction
  tests (inmemory success, redis-disabled failure)
- Document the New convenience wrapper in pkg/infra/cache/cacher.go

Verification: CI_DATABASE_TYPE=sqlite3 go test ./pkg/authz/... passes
2026-09-09 23:22:44 +08:00
Tosone 7594514d8b build: bump dependencies
- miniredis v2.38.0 -> v2.39.0
- aws-sdk-go-v2 v1.45.1 -> v1.46.0 (config, s3, and transitive sub-packages)
- docker/cli v29.7.2 -> v29.8.0
- gin-contrib/cors v1.7.7 -> v1.7.8, pprof v1.5.4 -> v1.5.5
- go-playground/validator v10.30.3 -> v10.30.4
- go-sql-driver/mysql v1.10.0 -> v1.10.1
- pgx/v5 v5.10.0 -> v5.11.0
- mcp-go v0.58.0 -> v1.0.0
- moby/buildkit v0.32.2 -> v0.33.0
- podman/v6 v6.1.0 -> v6.1.1
- golang.org/x/crypto, net, oauth2, sync (and transitive x/* packages)
- resty.dev/v3 v3.0.0-rc.3 -> v3.0.0-rc.4
- distribution-spec/specs-go refresh
- plus assorted transitive dependency bumps

Verification: go.sum regenerated to match go.mod
2026-09-09 21:59:31 +08:00
Tosone 4934a7061a build(deps): update all indirect and direct go module versions
Update all direct and indirect Go module dependencies to their latest compatible versions, including security patches and feature updates across the codebase.
2026-08-28 11:09:57 +08:00
Tosone c9ac979c95 refactor: migrate json encoding to json/v2 package across codebase
Replace all usages of standard encoding/json with encoding/json/v2 and jsontext
where applicable, update decoding logic to use json.UnmarshalRead and
json.MarshalWrite instead of manual encoder/decoder instances.

Verification:
go test -race ./pkg/... ./cmd/...
2026-08-27 14:28:01 +08:00