Volcengine bill data has 1-2 day delay. Previously the scheduler
only refreshed current month, so when the month rolls over the
previous month's incomplete snapshot was frozen. Now it refreshes
the current month plus 2 prior months.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The K8s Service is named 'airgate-backend', not 'backend',
causing CrashLoopBackOff with 'host not found in upstream'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
To enable migrating local SQLite database to online deployment,
the AIRGATE_ENCRYPTION_KEY must match between environments.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Display project name tags (green=monitoring, grey=not) with a
'manage' link to the policy page. Much more informative at a glance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace Webhook with App ID + App Secret + mobile number
- Reuse AirDrama's feishu app (send private card messages)
- Add test button in system settings
- Add test-feishu API endpoint
- Default monitor interval changed to 60 seconds
- Token caching for feishu tenant_access_token
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Track all Volcengine usernames during sync
- Delete local users not found on Volcengine (cascade deletes related data)
- Report removed users in sync response
- Deleted test_audit and tudouceshi from local DB
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- BillingService now uses ListSplitBillDetail (split bill) instead of
ListBillDetail (bill detail) - the latter shows Project='-' for
Seedance pay-as-you-go products
- Added get_spending_all_projects() for batch query (avoids N+1 API calls)
- Scheduler optimized: single API call fetches all project spending
- Verified: amounts match Volcengine console split bill page exactly
- Updated research report with billing API findings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rewrite 操作说明.md with full admin/sub-account operation flow
- Add v0.5.0 to 版本管理.md (permission refactor + account enhancements)
- Add Scope=Project API limitation finding to research report
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New deny_policy_exempt field on IAMUser model
- Toggle in monitoring config dialog
- Exempt accounts skip Deny policy creation
- Changing the toggle immediately updates/removes Deny policy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a project is added/removed for any user, all users' Deny
policies must be updated - new projects need to be added to other
users' deny lists to prevent unauthorized cross-project access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AttachUserPolicy ignores Scope=Project parameter - policies always
attach globally. Project isolation now relies entirely on Deny policy
(AirGate_Deny_{username}) which blocks access to non-whitelisted projects.
Updated report with this finding.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Was comparing against local DB which could be stale.
Now queries Volcengine for actual project-level policies before diffing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All project management and policy operations now handled in the
unified UserPoliciesView page. Removed unused dialogs, variables,
and functions from IAMUserList.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add project section: add/remove projects with policy selection
- Each project card shows: policies, spending, monitor toggle, remove
- Replaces separate project management dialog
- All project and policy operations on one page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New page: /iam-users/:id/policies shows all policies in one view
- Separated into global policies and per-project policies sections
- Each section has inline add/remove with disabled duplicates
- Backend: new policies/overview/ endpoint returns global + project policies
- Replaces old popup-based policy management
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Global policy view: filter out project-scoped policies, only show Global
- Project list view: filter out global policies, only show Project-scoped
- Fixes: same policy appearing in both global and project views
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Without Scope parameter, AttachUserPolicy defaults to Global scope
even when ProjectName is provided. Adding Scope=Project ensures
policies are correctly limited to the specified project.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Disable now saves both global and project-level policies with scope info
- Restore puts policies back in original scope (global or project)
- Project list view now syncs policies from Volcengine in real-time
- Fixes: policies incorrectly restored as global after disable/enable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename "权限策略" to "全局权限策略" in dropdown menu
- Add info banner explaining global vs project-level in both dialogs
- Disable already-attached policies in global dropdown (grey out)
- Show policy type as tag (系统/自定义) in global policies table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deny policy (AirGate_Deny_{username}) was removed during disable
but not recreated on restore. Now _update_deny_policy is called
during restore to rebuild project isolation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Save volc_login_allowed state before disable
- Restore to original state (not always open)
- e.g. login=off before disable -> still off after restore
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Disable: sync volc_login_allowed=False
- Enable: sync volc_login_allowed from actual LoginProfile state
- Sync: check AK status to detect AirGate-disabled accounts
(all AKs inactive = disabled, even if user Status=active)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Account status now comes from Volcengine User.Status field (active/disabled)
- Console login status synced to volc_login_allowed separately
- Fixes: closing Volcengine login no longer marks account as disabled after sync
- Handles ghost LoginProfile (CreateDate=1970) correctly during sync
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Users created without console password have a phantom LoginProfile
that GetLoginProfile returns but UpdateLoginProfile/DeleteLoginProfile
reject. Now checking CreateDate to detect this.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Skip LoginProfile operations when user has no console password
- Only send non-empty fields to Volcengine UpdateUser API
- Fixes enable_user crash for users created without password
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix: detach policy before deleting (avoids deletion error on referenced policy)
- Fix: fail explicitly if project list can't be fetched (prevent no-op Deny)
- Add _refresh_all_deny_policies helper for batch refresh after new project creation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add upsert_deny_policy / remove_deny_policy to IAMService
- Auto-update Deny policy when adding/removing projects
- Auto-create Deny policy on sub-account creation
- Deny policy lists all non-authorized projects explicitly
- Verified: cross-project ListAssetGroups and ListApiKeys are blocked
- Updated research report with cross-project API findings (2026-03-28)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add volc_login_allowed field to IAMUser model
- Add toggle-volc-login API endpoint
- Add toggle button in IAMUserList dropdown menu
- Sync status on user creation and toggle
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Detect InvalidPassword error and return user-friendly message
- Rollback user creation if password policy fails
- Add password requirements hint in create form
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add edit profile (display name, phone, email) with Volcengine sync
- Add IAMService.update_user for Volcengine UpdateUser API
- Add edit-profile API endpoint and URL
- Add Edit Profile dialog in IAMUserList frontend
- Verify admin change password, sub-account change password, set login password all working
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Admin section: full workflow from account creation to key entry
- Sub-account section: login, view keys, change password, use API
- Updated for manual key entry mode and no-console-login architecture
- Added alert/auto-disable mechanism description
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Admin: set sub-account AirGate login password via dropdown menu
- Admin: toggle sub-account login enabled/disabled
- Sub-account: change own password (sidebar "修改密码")
- Sub-account: auto-redirect to login page after password change
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Makes auth role logic consistent between admin (role: 'admin')
and sub-account (role: 'iam_user') logins.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Login page: toggle between admin/sub-account login
- Auth store: isAdmin/isIamUser computed properties
- MainLayout: role-based sidebar (admin sees all, sub-account sees only my keys)
- HomeRedirect: auto-redirect based on role
- MyKeysView: sub-account can view/reveal their own API Keys
- Portal is completely isolated from admin functions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- IAMUser model: login_password_hash + login_enabled fields
- Custom JWT auth for sub-accounts (role: iam_user)
- Login/me/my-keys/reveal endpoints for sub-accounts
- Admin can set login password via set-login endpoint
- Sub-accounts can only see their own API Keys
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New ArkApiKey model (encrypted storage, bound to user+project)
- Admin enters API Key from Volcengine console into AirGate
- Sub-accounts can only view their own keys
- Reveal endpoint decrypts key on demand with audit log
- Updated research report: documented Ark API limitation (CreateApiKey
doesn't return plaintext) and manual entry solution
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New VolcengineClient.call_json() for POST+JSON signing (Ark API)
- ArkService for API Key CRUD operations
- Backend views: list/create/toggle/delete ark keys per project
- Frontend: ArkKeysView with project selector, key table, create dialog
- Created key value shown once with copy button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Key changes:
- Architecture upgraded: sub-accounts do NOT log into Volcengine console
- Documented Ark API Key management via POST+JSON (verified working)
- Added chapter 12 (Ark API Key mgmt) and 13 (实测发现 with decisions)
- Fixed Step 1 code example to NOT create console login
- Updated core requirements table, architecture diagram, limitations
- All findings verified through actual API testing on 2026-03-20
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "授权" button on each linked project row
- New dialog to select/deselect policies per project
- Backend does incremental diff: only attach new, detach removed
- Handle PolicyAttachConflict gracefully
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Global policies conflict with project-level attach - treat as success
since the user already has the permission globally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Change password: current user can change their own password
- Admin management: superuser can create/toggle/reset-password for admins
- Operation log: view all system operations with type filter
- All operations are recorded to AlertRecord for audit trail
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Disable now removes all policies (saved to DB) + Enable restores them
- Project add: policies are now user-selected (checkbox), not auto-attached
- Fix serializer allow_blank for optional fields (email/phone/password)
- Better error reporting for policy detach/attach failures
- Handle duplicate user creation with clear error message
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>