Commit Graph
48 Commits
Author SHA1 Message Date
chenchenandClaude Opus 4.7 37de6575df fix(server): backport two prod hot-patches that kept getting wiped
1. /api/heicode-auth/* proxy: CriticalRateLimit (20/20min) → GlobalAPIRateLimit
   (180/180s). The Heicode external-identity proxy is hit on every page
   render for /me + /refresh plus the login burst — CriticalRateLimit is
   sized for sensitive ops (password reset, 2FA) and trips at ~5 quick
   page loads, returning 429 to a normal user. APIM upstream rate-limits
   itself, so a second tight layer here adds no security and just
   manufactures 429s.

2. JIT-create user group: seed "default" instead of me.Data.ChannelID.
   Companion to 578a68f which only patched the every-login overwrite
   path. New users (yj2824269760@gmail.com et al, JIT-created after
   578a68f) still landed in a UUID group → empty /v1/models response →
   desktop client showed the static 3-Claude fallback list.

Both fixes were applied on the production VM directly today (sed +
python patch) — committing them so the next docker rebuild on VM keeps
them instead of reverting to the buggy file via git checkout.

DB hot-fix already applied: 6 affected users moved to group=default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:14:35 +08:00
chenchenandClaude Opus 4.7 88c5b4a285 feat(manager-web): align login + header with Heicode brand violet
Theme tokens (theme.css)
- --primary retuned to the brand violet oklch(0.58 0.17 278) ≈ #7B6BE3
  (was a saturated pink oklch ... 286 that read off-brand against the H
  glass logo)
- New tokens: --brand-from #B888E5, --brand #7B6BE3, --brand-to #6B7CE0,
  --gradient-brand (135deg three-stop), --gradient-brand-btn for primary
  CTAs. Both light and dark modes hold the same brand identity.

Login page (auth-layout.tsx + sign-in/index.tsx + user-auth-form.tsx)
- Inlined H glass mark SVG replaces the abstract ShieldCheck pictogram
- Brand wordmark uses gradient text-fill so the word "Heicode" reads as
  the same gradient as the logo
- "Tenant access" pill and h2 heading both pick up brand violet via
  border / bg / gradient text
- Sign-in button switches from solid var(--primary) to the three-stop
  --gradient-brand-btn with violet drop shadow + lift-on-hover

Header user info (profile-dropdown.tsx)
- The right-side trigger used to be a bare 36px avatar — invisible user
  identity unless you click. Now it is a pill: gradient-filled avatar
  initials + display name + email + role badge, always visible on >=sm
- Avatar fallback fills with --gradient-brand so even pre-image, the
  user pill carries Heicode color identity

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:24:04 +08:00
chenchenandClaude Opus 4.7 f650462f17 feat(manager-web): drop third-party model brand grid from landing
Per docs §10 "禁止普通用户体验出现:模型供应商配置 / 模型提供方
选择" — the dashboard landing hero showed "OpenAI / Claude /
Gemini / DeepSeek / Qwen / Llama" as a marketing matrix, which
leaks upstream provider branding into the user-facing surface.

Replaced with Heicode capability tags (通用 / 长上下文 / 推理 /
代码 / 多模态 / 高性价比). This is the landing the user lands on
after login; admins still see real upstream provider names in
the system-settings → models tabs (those are technically the
channel protocol names and removing them would mislead admins).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:30:58 +08:00
chenchenandClaude Opus 4.7 7c3ecbcefc feat(manager): align with product-package docs §10/§11
CORS unblock — add /api/heicode-auth/*proxyPath backend proxy to
HEICODE_AUTH_BASE_URL. Frontend defaults to same-origin path so
the browser never hits APIM directly.

Sidebar — replace backend jargon (Git sources / Deployments /
Events / Wallet / Available models / Profile) with the user-facing
labels docs §10 mandates: 总览 / 准备清单 / 任务总览 / 审计 /
模型与余额 / 客户端 / 账号安全.

/sk-sources rewritten as 4-card preparation wizard with progress
meter; full Git form moves into a 高级补充 sheet. Drops JSON
editor, permission manifest, snapshots and resource-grant pills.

/deployments simplified to 任务总览: objective + status + last
update. Drops risk / budget / scope / secret_ref pills and the
RunDetailPanel; manifest details only in audit/advanced views.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:01:14 +08:00
chenchenandClaude Opus 4.7 afceb7cc2e feat(manager-web): expand favicon ladder + hide unused 2FA/Passkey UI
index.html: add png/ico/apple-touch favicon links, og:image,
and brand theme-color (#7B6BE3) so all icon surfaces use the
H glass mark.

Hide unused auth UI:
- profile page: drop PasskeyCard + TwoFACard
- system-settings/auth: drop Passkey Authentication section

These features aren't part of the Heicode platform flow (auth
is delegated to the identity service / SSO); leaving them in
the UI confuses tenants.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:52:28 +08:00
chenchenandClaude Opus 4.7 c47db748e5 feat(manager-web): swap logo to H glass mark
Match Heicode desktop client app icon: violet→blue gradient
rounded-square with white H. Replaces favicon.ico, logo.png
(used in footer / system info), heicode-logo.svg (browser
favicon link), and the inline Logo component.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:49:51 +08:00
chenchenandClaude Opus 4.7 6cc981d366 fix(server/web): SPA navigate() to backend bridge URLs renders 404
When the desktop one-click login flow opens
  /heicode/oauth/authorize?state=...&redirect_uri=...
in the browser and the user isn't signed in, Manager renders the
"please log in" bridge page that links to /sign-in?redirect=<authUrl>.
After login, useAuthRedirect's `handleLoginSuccess` calls TanStack
Router's `navigate({ to: targetPath })` to send the user back to
that authorize URL.

But TanStack Router only knows about React routes; backend bridges
(`/heicode/oauth/...`, `/api/...`) have no matching route, so the
SPA renders 404. The user has to manually re-enter the URL, at
which point the backend handles it and 302s to the loopback
callback. This produced the 500 → 404 → success symptom users hit
on first-time desktop login.

Fix: detect backend prefixes (`/heicode/oauth/`, `/api/`) and use
`window.location.assign()` to force a full-page navigation so the
server gets the request directly. React-route paths still go
through `navigate()` as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 17:29:01 +08:00
xiaoheiandchenchen 87b30b8fa1 fix: 修复登录时 /v1/models 空列表 panic 导致 500
- heicode/controller/model.go: Anthropic ListModels case 对空模型列表
  做边界保护,避免 index out of range panic -> HTTP 500
- cc-haha/src/server/services/providerService.ts: 模型探活不再发送
  anthropic-version header,统一走 OpenAI 兼容路径返回 {data:[]}
- heicode/controller/heicode_oauth.go: OAuth 未登录重定向指向 /sign-in
- heicode/deploy/nginx/heicode-gateway.conf: 3000 端口 server block
  补充 /models -> /v1/models 兼容路由
2026-05-08 20:19:21 +08:00
chenchenandClaude Opus 4.7 578a68f006 fix(server): stop overwriting users.group with Agnet channelId on every login
NewAPI's `users.group` is the local model-access bucket — it must match a
row in the `abilities` / `channels` group column to expose any models. The
Agnet channelId returned by mcp-server's /api/auth/me is a cross-platform
identity that almost never matches a NewAPI-side group, so blindly assigning
it on every login left users with `data: []` from /v1/models and the
desktop client silently fell back to the static 3-Claude default list.

Symptoms fixed: 4 users (xiaohei, 55@55.com, uwktn, test1) had UUID groups
with zero abilities, so /v1/models returned empty for them. cc-haha desktop
falls back to preset.defaultModels, hiding the 28 real models the channels
expose under group=default.

Change: drop the unconditional overwrite branch. The JIT-create path above
still seeds group from channelId on first login (kept for backward
compat), but admin-set group on existing users is preserved. mcp-server
already tracks Agnet channelId separately (see markBillingProviderNewapi),
so we don't need to mirror it into NewAPI's users.group anymore.

DB hot-fix already applied: 4 affected users moved to group=default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:05:33 +08:00
chenchenandClaude Opus 4.7 fc2c811e93 feat(server): notify mcp-server billing_provider=newapi after Agnet user sync
Implements Heicode's choice (b) for §7.7.1 ②: in syncLocalUserFromAgnet,
fire-and-forget PUT mcp-server's internal /api/auth/internal/billing-provider
{email, billing_provider:"newapi"} so mcp-server's User table billing_provider
column lands as 'newapi' for users that came in via Heicode Manager (vs the
default 'litellm' for native taijiagent users).

- Goroutine: never blocks login on this side-effect; mcp-server endpoint is
  idempotent so retries from repeat logins are harmless.
- Token via env MCP_SERVER_INTERNAL_TOKEN (K8s/compose secret); empty env
  silently skips (dev-friendly).
- Reuses agnetHTTPClient + common.Marshal + common.GetUUID per repo
  conventions.

Spec: docs/Heicode-对接进度与待办.md §7.8.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:36:24 +08:00
chenchenandClaude Opus 4.7 2f75588ed1 feat(server): expose desktop-downloads file route to TokenOrUserAuth
Add userRoute.GET /api/user/desktop-downloads/file/:platform with
TokenOrUserAuth middleware. A plain browser <a href> can hit this with
just the session cookie; New-Api-User header isn't required (the SPA's
axios layer still injects it for the metadata endpoint on selfRoute).

Closes the 401 "无权进行此操作,未提供 New-Api-User" case from the
Heicode Manager desktop installer download path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:40:40 +08:00
chenchenandClaude Opus 4.7 f70d80ca4c Revert "fix(agnet): preserve root admin's group during Agnet session sync"
This reverts commit 992a965. After re-reading the upstream Heicode
design docs (heicode.md, heicode-runtime-auth-newapi-secret-design.md,
plan.md), it is clear that:

  1. users.group = channelId is the correct upstream behaviour. Agnet's
     /me is the source of truth for which NewAPI channel a user belongs
     to. Forking that logic in NewAPI to special-case role>=root breaks
     the documented "Manager owns identity, NewAPI is just the model
     gateway" boundary.

  2. The empty-abilities symptom isn't a NewAPI fork bug. It's that
     chenchen was created by raw SQL INSERT into NewAPI's users table —
     a path that doesn't exist in the design. Real users get their
     channelId from Manager (mcp-server) at login, and ability rows for
     that channelId are provisioned out-of-band by platform operations
     when the channel goes live.

  3. Patching NewAPI to silently keep an admin's hand-edited group hides
     the real provisioning gap and pollutes the upstream sync logic for
     every future user.

Restoring upstream behaviour. Out-of-band fixes (whether to
provision abilities, route mcp-server logins, etc.) belong elsewhere.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:15:17 +08:00
chenchenandClaude Opus 4.7 992a965cd9 fix(agnet): preserve root admin's group during Agnet session sync
syncLocalUserFromAgnet rewrites users.group with the channelId returned
by Agnet's /me on every web /sign-in. That's correct for normal users —
their channel membership is owned by the Agnet identity service. But
platform administrators (RoleRootUser) are provisioned out-of-band:
operators set their group to "default" (or whichever billing tier)
manually, and their NewAPI abilities exist there.

When a root admin logs in via the web, Agnet returns a stub channelId
that has no abilities rows. The current code overwrites users.group
with that stub, and the next /v1/models call returns an empty list —
the desktop client then falls back to providerPresets.defaultModels,
hiding the real model catalogue from the operator.

Add a role guard so the rewrite only fires for users below root. Root
admins keep whatever group an operator set in the DB.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:03:40 +08:00
chenchenandClaude Opus 4.7 4665f88921 feat: route Heicode desktop login through code.xinghanlab.com Manager
Three concrete pieces:

1. Provider preset taijiaicloud now points at https://code.xinghanlab.com
   instead of the old api.taijiaicloud.com. Together with the stock
   resolveOAuthConfig fallback (<baseUrl>/heicode/oauth/authorize), this
   flips oauthEnabled on for the login card and turns the existing
   browser-redirect bridge into the default flow. Card name + promo
   updated to reflect that this is "log in via Heicode Manager".

2. loginAndActivate softens its model probe. /v1/models is best-effort:
   only hard 401/403 auth failures abort login. 5xx / panics / empty
   lists fall back to preset.defaultModels so the user lands inside the
   app even if the gateway transiently misbehaves; they can re-pick
   models from Settings later.

3. heicode_oauth.go fallback page: /login → /sign-in (matches the
   actual SPA route), title/copy de-branded from "HeiCode/新 API 控制台"
   to plain "Heicode 控制台".

Also picks up the prior unstaged Windows polish: WindowControls (min/
max/close + drag region) on the login screen, ProviderLoginCard +
globals.css refinements that landed in earlier MSI builds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:55:57 +08:00
gongzhiyongandOmX bf134dec86 Make Agnet runs submit resource-scoped work safely
Manager now exposes a Resource Grant manifest and the Agnet control-plane response carries runtime state, agent instances, and permission_manifest so frontend runs can submit bounded resource grants without plaintext credentials.

Constraint: Manager remains the user console while NewAPI stays independent and OpenBao is referenced through secret_ref only.

Rejected: platform-side high-risk approval | client approval is the product boundary; Agnet only validates approval evidence.

Confidence: medium

Scope-risk: moderate

Directive: Do not mix child Agnet runtime model selection with NewAPI billing or expose OpenBao as a public route.

Tested: git diff --check; jq empty locale JSON; go vet ./controller ./model ./router; go test -count=1 ./controller ./model ./router

Not-tested: frontend typecheck/build because local node_modules tooling is absent and user requested builds happen on the VM.

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-04 18:55:53 +08:00
gongzhiyong ba02ae5be7 feat: align manager agnet boundaries
- add Manager user_context, NewAPI billing_context, and Agnet agent_runtime deployment fields

- move resource binding/grant scope toward user-owned binding_scope and secret_ref-only paths

- document OpenBao internal access and unified heicode.xinghanlab.com routing boundaries

- fix Manager session user id preservation after external auth login
2026-05-04 09:28:03 +08:00
gongzhiyongandOmX d9eb7dcd74 feat: wire resource secrets to OpenBao
Manager needs a platform-owned secret handoff path so resource bindings can keep only vault references while OpenBao stores tenant-scoped credential payloads.

Tested: go test ./controller ./model ./router && go vet ./controller ./model ./router
Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-03 23:41:55 +08:00
gongzhiyong a7588e1bc8 chore: remove plaintext postgres retry credentials 2026-05-03 21:49:55 +08:00
gongzhiyong 50bf3de6f0 agnet: add deployment logs metrics readiness endpoints 2026-05-03 21:48:26 +08:00
gongzhiyong fb61f385fb deploy: make azure vm deploy helper executable 2026-05-03 21:17:34 +08:00
gongzhiyong 0d7491c9a1 omx(team): auto-checkpoint worker-5 [unknown] 2026-05-03 18:09:04 +08:00
gongzhiyong 24405519a9 omx(team): auto-checkpoint worker-1 [1] 2026-05-02 23:32:00 +08:00
gongzhiyong 05182f0277 task: implement manager resource grants 2026-05-02 23:30:23 +08:00
gongzhiyong 5e4648e608 omx(team): auto-checkpoint worker-5 [5] 2026-05-02 23:29:39 +08:00
gongzhiyong 0a01f36f1b omx(team): auto-checkpoint worker-2 [2] 2026-05-02 23:29:34 +08:00
gongzhiyong 33fa9f20a6 omx(team): auto-checkpoint worker-5 [5] 2026-05-02 23:28:40 +08:00
gongzhiyong a8be398087 omx(team): auto-checkpoint worker-4 [4] 2026-05-02 23:28:37 +08:00
gongzhiyong 30e0b0b4c6 omx(team): auto-checkpoint worker-2 [2] 2026-05-02 23:28:34 +08:00
gongzhiyong bf42bbda8a omx(team): auto-checkpoint worker-4 [4] 2026-05-02 23:26:17 +08:00
gongzhiyong f585d26fe7 docs: define saas manager agnet architecture 2026-05-02 22:07:02 +08:00
gongzhiyong 63fe529b36 feat(agnet): allow users to bind git sources 2026-05-01 20:55:58 +08:00
xiaohei be0d102553 fix(manager): load env file in compose override 2026-05-01 11:50:13 +00:00
Ubuntu 2f0bf2563e feat(manager): login auto relay token hidden from UI; available models page
- Add hide_from_user_ui on tokens; EnsureUserRelayToken on login and Agnet session

- List/search tokens: end-users see only visible keys; admins see all

- Add /available-models and sidebar entry; i18n en/zh + locales

- desktop download / router hooks if present under heicode/
2026-05-01 10:00:11 +00:00
Ubuntu b0acfd44c1 feat(agnet): SK repo_ref validation, create deployment UI, docs touch-ups
Extend agnet SK sources with repo_ref and snapshot display; add authenticated
deployment sheet + API types; cockpit toolbar entry; locale strings; minor docs.

Made-with: Cursor
2026-05-01 09:12:00 +00:00
Ubuntu 356592e294 fix(ui): reorder cockpit nav to bind Git sources before deployments
Made-with: Cursor
2026-05-01 08:18:35 +00:00
Ubuntu 4e8b4a66c6 feat(agnet): persist runtime_execution and sk_access_policy with validation
Go control plane: extend agent plan structs, validate bindings and SK policy
codes. Web: surface bindings on Agents page with i18n.

Made-with: Cursor
2026-05-01 08:13:21 +00:00
Ubuntu b42e5b2dd0 feat(heicode): SK workflow UI, Agnet contract docs, usage-log schema
Manager web: Git sources workflow steps and copy; typecheck fixes for auth
and home sections; UsageLog type in usage-log-schema.ts (outside ignored data/).

docs: Agnet platform contract adds runtime_execution and sk_access_policy,
orchestration-plan and acceptance matrix aligned.

Made-with: Cursor
2026-05-01 07:38:17 +00:00
Ubuntu a8f64bce68 feat(ui): reframe SK area as Git-backed sources and snapshot anchors
SK 正文以 Git 为准:侧栏/首页/登录支柱改为「Git 来源」叙事;
/sk-sources 页增加 Git 绑定说明 +「已解析快照锚点」列表标题;
驾驶舱快捷入口与 i18n(中英及同步 locale)对齐。

Made-with: Cursor
2026-05-01 07:21:02 +00:00
Ubuntu a0e69bf076 i18n(zh): complete localization of cockpit/agnet-console/sign-in
- 补齐 109 个 t() key 的中英对照(涵盖 Code 交付驾驶舱、agnet-console
  四张面板、登录页、侧栏/顶部导航/页脚、usage-logs/about/lib/api 等)
- BRAND_TAGLINE 在 auth-layout 改走 t(),新增「智能体研发控制面」
- password-input 的眼睛按钮 aria-label 走 t(),新增「切换密码可见性」
- fr/ja/ru/vi 同步 key(暂用英文兜底,等后续按 i18n 报告补译)

Made-with: Cursor
2026-05-01 06:37:25 +00:00
Ubuntu 8cd82caf72 feat(ui): hide developer console for management backend users
平台定位为管理后台,登录后不再向普通用户暴露 Playground / API Keys / Models
等开发者控制台入口;Usage logs 作为交付链路一环并入 Code delivery 分组。
路由本身保留,仅侧栏不再展示。

Made-with: Cursor
2026-05-01 04:33:15 +00:00
Ubuntu a668e1fca1 feat(auth,ui): hardened Agnet auth, admin workspace and role whitelist
Backend (controller/heicode_agnet_session.go):
- Add HEICODE_ROOT_EMAILS / HEICODE_ADMIN_EMAILS whitelists for JIT role
  assignment. Manager no longer trusts Agnet's role claim — admin / root
  is granted only by local config.
- Default JIT-synced users to RoleCommonUser.
- Promote-only role sync on every login (never demote).

Frontend auth fixes:
- login() no longer hard-codes id=1; preserves the real manager user id
  returned by /api/user/session/from-agnet so the New-Api-User header
  matches the cookie session.
- After login, prefer local /api/user/self over Agnet /me so role /
  status reflect actual manager state (e.g. whitelist promotion).
- lib/api.ts: scope 401 -> "Session expired" handling to identity
  endpoints only; admin-only 401 no longer resets the session.

UI restructuring:
- Default sidebar shows only Code delivery + Console + Personal, plus a
  single "System settings" entry for ROLE.ADMIN+.
- system-settings workspace now hosts the full Tenant administration
  tree (Channels / Models / Subscriptions / Redemption codes / Tenants /
  Templates / Agents / Vendors / All usage logs) for ROLE.ADMIN+, with
  System Administration sub-tree gated to ROLE.SUPER_ADMIN.
- Workspace switch triggers on admin paths (channels, users, templates,
  agents, subscriptions, models, redemption-codes) — not only
  /system-settings.
- system-settings route now allows ROLE.ADMIN+ instead of root-only.

Branding cleanup:
- Drop orphan "NewAPI" i18n keys from web/default locales.
- Rename web/default workspace package newapi-web -> heicode-web.

Config:
- docker-compose.azure-vm.yml exposes HEICODE_ROOT_EMAILS /
  HEICODE_ADMIN_EMAILS.

VERSION: 1.1.0-default-user-role
Made-with: Cursor
2026-04-30 21:03:08 +00:00
Ubuntu aae8dd329a chore(release): bump VERSION to 1.0.2-agnet-jit after Agnet JIT session bridge
Made-with: Cursor
2026-04-30 18:39:10 +00:00
Ubuntu c2633bb1ae fix(auth): use model.UserNameMaxLength for JIT username length
Made-with: Cursor
2026-04-30 18:29:24 +00:00
Ubuntu 6f8ed68422 chore(config): document canonical Agnet base URL from integration doc
Made-with: Cursor
2026-04-30 18:26:33 +00:00
Ubuntu 4cdd06f352 feat(auth): Manager session from Agnet tokens with JIT local user
Replace password-based /api/user/login bridge after external auth with POST /api/user/session/from-agnet: verify access (and optional refresh) against Agnet /api/auth/me, upsert local user by email, then issue the Manager session cookie. Frontend sends bearer tokens only.

Includes HEICODE_AUTH_BASE_URL in compose defaults and .env.example.

Made-with: Cursor
2026-04-30 18:23:39 +00:00
Ubuntu 4f5521a6cf refactor(auth): replace 2FA string sentinel with typed error
Use a dedicated TwoFactorRequiredError and shared type guard to keep login flow checks type-safe and less brittle than matching magic strings.

Made-with: Cursor
2026-04-30 18:07:12 +00:00
gongzhiyong 0b4d4f811e fix(auth): establish Manager session cookie after Heicode password login
External IdP login alone did not set Gin session; proxied API calls returned 401 and triggered session-expired toast. Call POST /api/user/login after token exchange, support Turnstile on sign-in, handle 2FA pending session, and clear Manager cookie on logout.

Made-with: Cursor
2026-05-01 01:59:26 +08:00
gongzhiyong 1f21309597 refactor: rename manager codebase dir new-api → heicode, module github.com/heicode/manager
Remove user-facing new-api naming; Docker/network/container names use heicode.
Go imports updated; Dockerfiles and workflows ldflags fixed.

Made-with: Cursor
2026-05-01 01:47:23 +08:00