feat: add admin cost calculation table - #855
Open
yedouo wants to merge 174 commits into
Open
Conversation
Constraint: TokenSpace and Seedance proxy scopes are 87 and 82 characters while production columns are varchar(80). Rejected: Truncate scope hashes | it would change binding identity and invalidate reusable bindings. Confidence: high Scope-risk: narrow Directive: Keep all grouped Seedance providers on one provider-configured asset lifecycle with no channel-ID branches. Tested: Design self-review, whitespace validation, and clean origin/main code-path inspection. Not-tested: No implementation changes are included in this design-only commit.
Constraint: Wallet pricing and subscription enforcement must remain independently testable Rejected: One monolithic implementation plan | the wallet and billing paths have separate regression surfaces Confidence: high Scope-risk: broad Directive: Execute each task with a red-green test cycle and preserve monthly/media enforcement Tested: plan self-review for spec coverage, placeholders, and interface consistency
Constraint: Stripe validation and wallet rendering must share code-defined amounts Confidence: high Scope-risk: narrow Tested: focused controller top-up contract tests
Constraint: Unmapped or unconfigured languages must fall back to USD Rejected: Trust raw stripe_currency_prices from API | parser must discard unsupported currencies and invalid minor-unit values Confidence: high Scope-risk: narrow Directive: Keep checkout display math based on minor units; JPY remains zero-decimal while USD/BRL/INR divide by 100 Tested: bun test src/features/wallet/lib/stripe-currency.test.ts Tested: bun run typecheck Tested: bun x prettier --check src/features/wallet/types.ts src/features/wallet/hooks/use-topup-info.ts src/features/wallet/lib/stripe-currency.ts src/features/wallet/lib/stripe-currency.test.ts Tested: git diff --check
Constraint: A wallet tier may not display one currency and submit another Rejected: Region-based default currency | Locale must choose the initial checkout currency while region only gates selector visibility Confidence: high Scope-risk: moderate Directive: Preserve URL/manual checkout currency precedence before applying language defaults Tested: bun test src/features/wallet/components/recharge-form-card.test.tsx src/features/wallet/lib/stripe-currency.test.ts Tested: bun test src/features/wallet/components/recharge-form-card.test.tsx src/features/wallet/components/subscription-plans-card.test.tsx src/features/wallet/lib/stripe-currency.test.ts Tested: bun run typecheck Not-tested: Full web/default test suite
Constraint: Inbound/manual currency must not force an unconfigured checkout price into the recharge UI Rejected: Let touched currency always bypass fallback | It hides purchasable USD presets when a localized URL currency lacks prices Rejected: Reuse wallet tier value for recall pricing | Localized Stripe prices can differ from the tier value Confidence: high Scope-risk: moderate Directive: Treat touched currency as a language-default guard only; still validate it against configured checkout prices Tested: bun test src/features/wallet/components/recharge-form-card.test.tsx src/features/wallet/index.test.tsx src/features/wallet/lib/stripe-currency.test.ts Tested: bun test src/features/wallet/components/subscription-plans-card.test.tsx Tested: bun run typecheck Not-tested: Full web/default test suite
Constraint: Bun module mocks are process-global across files in the same test invocation Rejected: Mock shared lucide/UI/component modules narrowly | Later wallet tests import additional exports and fail by order Rejected: Split the relevant suite as the only gate | The normal runner may execute these files in one process Confidence: high Scope-risk: narrow Directive: Wallet integration tests must either use real shared modules or provide compatible complete mock surfaces Tested: bun test src/features/wallet/components/recharge-form-card.test.tsx src/features/wallet/index.test.tsx src/features/wallet/lib/stripe-currency.test.ts Tested: bun test src/features/wallet/index.test.tsx src/features/wallet/components/subscription-plans-card.test.tsx Tested: bun test src/features/wallet/components/subscription-plans-card.test.tsx src/features/wallet/index.test.tsx Tested: bun run typecheck Not-tested: Full web/default suite
Constraint: Bun wallet tests can share one process with process-global browser shims Rejected: Assigning storage through window Object.assign | captures the mock descriptor and misses sessionStorage restoration Confidence: high Scope-risk: narrow Directive: Register global shims through descriptor restore helpers before any globalThis mutation Tested: bun test src/features/wallet/index.test.tsx; bun test src/features/wallet/components/recharge-form-card.test.tsx src/features/wallet/index.test.tsx src/features/wallet/lib/stripe-currency.test.ts; bun test src/features/wallet/index.test.tsx src/features/wallet/components/subscription-plans-card.test.tsx; bun test src/features/wallet/components/subscription-plans-card.test.tsx src/features/wallet/index.test.tsx; bun run typecheck Not-tested: Full bun test suite
Constraint: Monthly pool and media credit enforcement must remain active Rejected: Dropping legacy Redis helpers | historical records still need compatibility Confidence: high Scope-risk: moderate Directive: Keep async task window compatibility helpers until persisted historical task data no longer needs them Tested: go test ./service -run 'Test(SubscriptionFundingWeightedRounding|SubscriptionFundingDoesNotExposeLegacyWindowSnapshot|BillingSession)' -count=1; git diff --check Not-tested: full go test ./service; GitNexus impact/detect-changes blocked by stale incompatible index
Constraint: Weighted monthly-pool settlement must remain restart-safe Rejected: Removing TaskBillingContext.SubscriptionWindow | legacy serialized tasks still need to deserialize Confidence: high Scope-risk: moderate Directive: Do not reintroduce async task Redis window adjustment; keep monthly pool settlement weighted by SubscriptionWeight Tested: go test ./service ./controller -run 'Test.*(Task.*Subscription.*Window|SubscriptionSnapshot|AcceptedTaskSubscription)' -count=1; go test ./service -run 'Test(RefundTaskSubscriptionWindowSnapshotLeavesRedisCounters|AcceptedTaskSubscriptionWindowStepOnlyMarksCompatibilityLedger)$' -count=1; go test ./controller -run 'Test(AssetTaskQueuePersistsSubscriptionSnapshot|AssetTaskAcceptedAccountingExternalStepsAreIdempotent|AssetTaskWorkerAcceptedSubscriptionUsesSnapshotForSettlement)$' -count=1; git diff --check Not-tested: Full go test ./service ./controller -count=1 was interrupted after more than two minutes per parent instruction because focused verification already passed
Constraint: Legacy columns stay readable but new plan writes normalize them to zero Rejected: Removing model or admin legacy fields | database compatibility still requires them Confidence: high Scope-risk: moderate Directive: Keep monthly_bucket, quota, media_credits, and admin legacy structs available while short windows are absent from public/self contracts Tested: go test ./controller -run 'Test.*Subscription(Self|Plan).*Window' -count=1; split public response and plan lifecycle tests; git diff --check Not-tested: go test ./controller -count=1 has unrelated existing asset worker and test environment failures
Constraint: Flatkey short windows must disappear without hiding active limits Rejected: Removing admin plan short-window amount fields | Task 5 owns admin form cleanup and current plan parsing still needs compatibility Confidence: high Scope-risk: moderate Directive: Keep wallet and profile self/public subscription summaries free of 5h/7d fallback fields Tested: bun test src/features/wallet/components/subscription-plans-card.test.tsx src/features/wallet/lib/subscription-plan-lifecycle.test.ts src/features/profile/components/profile-header.test.tsx src/features/profile/lib/subscription-summary.test.ts; bun test src/features/profile/hooks/use-profile-subscription.test.ts; bun run typecheck Not-tested: full frontend test suite
Constraint: Older API payloads cannot re-enable inactive enforcement Rejected: Removing legacy SubscriptionPlan response fields | Old admin responses still need to parse Confidence: high Scope-risk: narrow Directive: Do not reintroduce short-window admin inputs or payload fields unless enforcement is restored end to end Tested: bun test src/features/subscriptions/lib/plan-form.test.ts src/features/subscriptions/components Tested: bun run typecheck Tested: rg drawer window fields and labels returned no matches Not-tested: Full web test suite
Constraint: Task 4 review found remaining user-facing short-window semantics in profile media normalization and purchase review copy Rejected: Preserving backend media unlimited for zero total | product semantics require zero media credits to mean Not included Confidence: high Scope-risk: narrow Directive: Do not reintroduce 5h/7d copy or zero-media unlimited fallback on wallet/profile purchase surfaces Tested: bun test src/features/profile/lib/subscription-summary.test.ts; bun test src/features/wallet/components/subscription-plans-card.test.tsx; bun test src/features/wallet/components/subscription-plans-card.test.tsx src/features/wallet/lib/subscription-plan-lifecycle.test.ts src/features/profile/components/profile-header.test.tsx src/features/profile/lib/subscription-summary.test.ts; bun run typecheck Not-tested: full frontend test suite
Constraint: Subscription short-window removal must not hide visible top-up packages when a localized currency is only partially priced. Rejected: Keeping partial local-currency package display | It hid unpriced visible presets instead of falling back the whole checkout tier to USD. Confidence: high Scope-risk: moderate Directive: Keep legacy subscription window snapshots compatibility-only; do not reintroduce active short-window wallet/profile/admin surfaces. Tested: focused wallet currency tests; focused subscription window Go tests; frontend typecheck; production build; changed-file lint; git diff --check. Not-tested: Exact broad Go command stalled and was interrupted; full frontend directory test command remains affected by existing Bun module mock leakage; full lint has pre-existing repo-wide violations.
Constraint: Inbound or manual localized checkout currency must not render or submit a partial preset tier, and wallet/profile/subscriptions tests must run in one Bun process. Rejected: Correcting invalid currencies with a post-render timer | It allowed a partial BRL UI to commit before fallback and triggered React compiler lint pressure. Rejected: Keeping wallet integration tests on top-level shared module mocks | Bun keeps those mocks process-global and they polluted neighboring wallet tests. Confidence: high Scope-risk: moderate Directive: Derive Stripe display and submission currency from the same synchronous effective currency resolver; keep Bun test mocks complete when they target shared modules. Tested: bun test wallet resolver/card focus; bun test wallet/profile/subscriptions directories; bun test subscription-purchase then billing-history order; bun run typecheck; changed-file eslint; bun run build; git diff --check. Not-tested: Full repo-wide lint in Fix Round 1; original Go broad/split concerns unchanged because this round touched only frontend currency/tests.
Constraint: Bun module mocks are process-global, so subscription dialog tests must not replace shared pure format exports used by later plan-form tests. Rejected: Adding only quotaUnitsToDollars and parseQuotaFromDollars to the mock | The shared format module can drift and break the next consumer again. Confidence: high Scope-risk: narrow Directive: Prefer real pure modules over partial top-level mocks in shared Bun test processes. Tested: bun test subscription-purchase plus plan-form --randomize --seed 1; reverse order --seed 2; bun test wallet/profile/subscriptions directories; bun run typecheck; changed-file eslint; git diff --check. Not-tested: Full repo-wide lint/build in Fix Round 2; no production code changed.
Constraint: JPY fixed discounts are zero-decimal in Stripe, while USD/BRL/INR remain two-decimal currencies. Rejected: Keeping the Button test via a shared UI mock | Bun module mocks leak process-wide and caused order-dependent failures. Rejected: Removing Codex upstream 5-Hour Window and generic 7d copy | Call-site search shows they still serve non-Flatkey UI paths. Confidence: high Scope-risk: moderate Directive: Keep fixed-discount amount conversions currency-aware and avoid process-global mocks for shared UI modules. Tested: bun test src/features/wallet/lib/recall-claim.test.ts src/features/wallet/components/recharge-form-card.test.tsx src/i18n/config.test.ts; bun test src/features/wallet/components/recharge-form-card.test.tsx src/features/wallet/index.test.tsx src/features/wallet/lib/recall-claim.test.ts --randomize --seed 1; bun test src/features/wallet/index.test.tsx src/features/wallet/components/recharge-form-card.test.tsx src/features/wallet/lib/recall-claim.test.ts --randomize --seed 2; bun test src/features/wallet src/features/profile src/features/subscriptions; bun run typecheck; bun x eslint changed files; bun run build; go test ./i18n; git diff --check. Not-tested: Full repository Go suite was not rerun in this final wave; earlier Task 6 report documents broad Go command constraints.
Constraint: Display only configured plan prices and fall back the full grid to USD when a language currency is incomplete. Rejected: Client-side currency conversion | It can diverge from configured and charged amounts. Confidence: high Scope-risk: narrow Directive: Keep server-issued checkout quotes authoritative over language-derived display prices. Tested: Spec self-review for placeholders, contract consistency, fallback behavior, and verification coverage. Not-tested: Implementation and staging behavior are covered by the following execution plan.
Read supported Stripe Price currency options on the server, merge explicit BRL and INR plan prices, and select one fully covered language currency for the wallet plan grid. Constraint: Japanese uses JPY, Portuguese uses BRL, other languages use USD, and incomplete plan sets fall back entirely to USD. Rejected: Client-side exchange-rate conversion | It can diverge from configured and charged prices. Confidence: high Scope-risk: moderate Directive: Keep signed payment preview quotes authoritative over language-derived card prices. Tested: Targeted Go controller tests; 206 wallet tests; TypeScript typecheck; production frontend build; git diff check. Not-tested: Live Stripe currency options and staging browser rendering require the staging deployment.
Use R.90 and R.90 for the 100 and 200 credit Stripe top-up tiers. Constraint: The wallet must validate against the exact Stripe BRL minor-unit amounts. Rejected: Frontend-only formatting | Checkout validation would still reject the configured Stripe prices. Confidence: high Scope-risk: narrow Directive: Keep top-up display and Stripe validation driven by the same minor-unit contract. Tested: Stripe top-up price contract, top-up info filtering, and top-up info response tests. Not-tested: Live staging values require the next deployment.
Constraint: Pull requests must pass git diff --check before review. Confidence: high Scope-risk: narrow Tested: git diff --check origin/main...HEAD Not-tested: Functional behavior is unchanged.
Constraint: Bun module mocks remain process-global across the full frontend suite. Rejected: Assert less in the SMTP test | The placeholder is user-facing behavior and should stay covered. Confidence: high Scope-risk: narrow Directive: Shared component mocks must forward unrelated native props. Tested: bun test; bun run typecheck; targeted eslint; bun run build Not-tested: Full Go suite remains blocked by missing web/classic/dist and long-running unrelated packages.
Preserve staging onboarding and model-handoff behavior while routing implemented image and video models through session-authenticated Playground endpoints with model-specific controls. Constraint: Only expose media families backed by concrete relay support. Rejected: Broadly expose image and video names by pattern | Unsupported models would present controls that cannot complete requests. Confidence: high Scope-risk: moderate Directive: Keep Playground model profiles aligned with backend relay capabilities. Tested: 82 Playground tests, targeted ESLint and Prettier, TypeScript typecheck, web production build, targeted Go relay/middleware/router tests, controller build. Not-tested: Live upstream media generation before staging deployment.
Reuse existing Resolution and seconds translation keys so image and Seedance controls do not leak English labels in localized Playground sessions. Constraint: Avoid adding duplicate locale entries when shared translations already exist. Confidence: high Scope-risk: narrow Tested: 83 Playground tests, targeted ESLint and Prettier, TypeScript typecheck, web production build. Not-tested: Live UI recheck before the updated staging revision deploys.
Use the existing anchored popover surface so generation parameters stay next to their trigger without blurring the full workspace. Constraint: Match the supplied parameter-panel prototype and deploy staging only. Rejected: Remove blur from the shared Dialog overlay | That would alter unrelated dialogs globally. Confidence: high Scope-risk: narrow Directive: Keep media parameter controls anchored and non-modal unless product design explicitly changes. Tested: 84 Playground tests, targeted ESLint and Prettier, TypeScript typecheck, production web build. Not-tested: Live staging interaction before deployment.
Request construction must serialize visible user configuration instead of normalizing it again immediately before the backend call. Constraint: Apply model constraints while editing and deploy to staging only. Rejected: Keep defense-in-depth normalization in the request builder | It creates a hidden submit-time mutation. Confidence: high Scope-risk: narrow Directive: Keep model parameter normalization in Playground configuration state; request builders remain serialization-only. Tested: 85 Playground tests, targeted ESLint and Prettier, TypeScript typecheck, web production build. Not-tested: Live staging behavior before deployment.
Constraint: Port only Sub2 v0.1.178 identity-risk behavior; exclude account scheduling and capacity failover. Rejected: Channel setting JSON seed storage | dedicated hidden column prevents API leakage and accidental replacement. Confidence: high Scope-risk: moderate Directive: Preserve seed across edits and credential refreshes; never expose it to clients. Tested: Spec self-review, placeholder scan, and git diff --check. Not-tested: Implementation and runtime behavior are deferred to the execution plan.
Constraint: Existing channels must not change mode during deployment. Rejected: Treating missing persisted mode as full | that would mass-switch existing subscriptions. Confidence: high Scope-risk: narrow Directive: Persist full on new-channel creation while preserving explicit or missing legacy modes. Tested: Spec consistency scan and git diff --check. Not-tested: Frontend and backend implementation remain pending.
Constraint: Full mode must not forward original client identity through metadata, headers, alternate paths, or cloned database seeds. Rejected: Rejecting every unknown metadata key | stripping unknown keys preserves compatibility while failing closed on leakage. Confidence: medium Scope-risk: broad Directive: Keep the allowlists explicit and apply finalization after header overrides on every Codex subscription egress path. Tested: Spec contradiction scan and git diff --check. Not-tested: Runtime compatibility of strict full-mode sanitization remains to be proven by TDD and staging.
…t-routing fix: route TokenSpace real-person assets through Doubao video channels
Prevent duplicate Google accounts for verified emails
…quota Unify subscription quota and retire media credits
…sibility feat(visibility): apply hidden models to public model catalogs
Filter administratively hidden models only for Playground display, add the backend-safe Seedance 2.5 profile, and route image/video quick starts through visible compatible models. Constraint: Seedance 2.5 must match the current relay contract: 480p/720p, 4-30 seconds, no 21:9 or seed. Rejected: Reusing the Seedance 2.0 profile | it exposes unsupported 2.5 parameters. Confidence: high Scope-risk: moderate Directive: Keep /api/user/models hidden filtering opt-in so availability semantics remain unchanged for other consumers. Tested: Go operation_setting tests; targeted controller tests; 1725 frontend tests; scoped ESLint and Prettier; TypeScript typecheck; production build. Not-tested: Browser E2E against the deployed console.
…y-seedance25 feat(playground): honor hidden models and support Seedance 2.5
Parse numeric subscription tiers without float coercion and expose the two supported Grok video models through the existing Playground video flow. Constraint: Media writes remain single-submit and account status refresh remains explicit. Rejected: Treat usage percentages as paid evidence | display-only usage can authorize unknown or free accounts. Confidence: high Scope-risk: narrow Directive: Keep Grok video payload fields synchronized with the strict task DTO; never rename aspect_ratio to ratio. Tested: Grok relay/task tests; Playground 106 tests; TypeScript; ESLint; Go vet; frontend production build. Not-tested: Production Grok video generation awaits deployment and authoritative paid-tier refresh.
Fix Grok numeric tier eligibility and Playground video access
…d language Constraint: Preserve existing save, retry, restore, and toast trigger behavior. Rejected: Component-scoped translation hooks | persistence warnings run inside async hook callbacks and the repo already uses the i18next singleton for this pattern. Confidence: high Scope-risk: narrow Directive: Keep new Playground persistence warnings covered across every supported locale. Tested: 1732 Bun tests; TypeScript typecheck; targeted ESLint and Prettier; production frontend build. Not-tested: Manual fault injection of browser storage failure in every browser locale.
Localize Playground persistence warnings
TokenSpace legacy real-person assets already carry a channel-owned upstream asset id, but strict worker materialization was falling through to the generic asset table and failing before provider submit. Failed preparation also exposed no structured task error to video polling clients. Constraint: TokenSpace real-person groups are upstream LivenessFace groups while normal material assets use scoped AIGC bindings. Rejected: Converting legacy real-person rows into generic assets in this fix | would widen migration and ownership risk under production pressure. Confidence: high Scope-risk: moderate Directive: Keep TokenSpace real-person fallback limited to enabled DoubaoVideo TokenSpace channels with a same-channel active upstream binding. Tested: go test ./service -run "TestMaterializeAssetBindingsForChannel|TestAssetReference|TestTokenSpace|TestRealPerson" -count=1 Tested: go test ./controller -run "TestTechMobiAssetTaskWorker|TestAssetTaskWorkerPreparationFailureRefundsOnceForLateResult" -count=1 Tested: go test ./model -run "TestTaskQueuedFailureCAS|TestTaskToOpenAIVideo" -count=1 Not-tested: go test ./... because the root package still requires generated web/classic/dist assets in this worktree.
The async worker must validate current profile ownership and status before direct TokenSpace reuse, and the default non-strict path must recognize an authorized same-channel real-person binding before materializer scoring rejects it. Constraint: TokenSpace real-person assets remain channel-owned legacy bindings and are not recoverable ordinary AIGC sources. Rejected: Enabling strict coverage as an operational workaround | production defaults to non-strict and authorization must not depend on that feature flag. Confidence: high Scope-risk: moderate Directive: Keep direct reuse gated by legacy provenance, active owning profile, matching channel, active binding, and TokenSpace capability. Tested: targeted service and controller real-person worker tests, middleware routing tests, model failure/refund tests, go vet on affected packages. Not-tested: full go test ./... because generated web/classic/dist assets are absent and an overbroad service regex triggers unrelated million-row tests.
…er-routing Fix TokenSpace real-person asset worker routing
Route active real-person profiles through provider bindings while retaining credential-backed native storage and provider-independent persisted GCS cleanup. Constraint: Preserve the existing client contract and native BytePlus TOS/GCS behavior. Rejected: Requiring clients to pre-upload media | The public multipart endpoint already owns temporary private storage. Confidence: high Scope-risk: moderate Directive: Keep persisted GCS cleanup independent of current channel ability. Tested: gofmt; eight focused multipart, resume, provider, final-probe, and cleanup regressions; go build ./...; go test ./service/... (baseline failures disclosed). Baseline-failure: Representative full-service failures reproduce on unchanged origin/main.
Constraint: Only server-rewritten asset URI occurrences may cross the ModelAPI boundary. Rejected: Trust every asset URI value present in the rewrite map | it permits same-request direct URI smuggling. Confidence: high Scope-risk: narrow Directive: Preserve per-occurrence rewrite provenance when changing Seedance media validation. Tested: adaptor package; targeted service middleware controller tests; go vet; affected package build; diff check. Not-tested: production end-to-end before deployment.
…rite Fix channel 156 bound asset submission
* feat(admin): add guarded user impersonation sessions * fix(admin): sync client identity during impersonation * fix(auth): keep request uid in sync with session user * feat(i18n): localize user impersonation controls --------- Co-authored-by: 1111 <a1111@1111deMac-Studio.local>
* fix(admin): keep impersonation audit out of user logs * fix(log): filter impersonation audit from user logs --------- Co-authored-by: 1111 <a1111@1111deMac-Studio.local>
fix: support TokenSpace real-person multipart assets
Keep Flatkey's existing lease-guarded billing snapshot while aligning account status with Grok2API credit fields and derived remaining balances. Constraint: Preserve existing Grok media eligibility, stale-evidence, and secret-redaction boundaries. Rejected: A new quota table or separate account service | Adds migration and duplicate lease state without improving the current channel-scoped flow. Confidence: high Scope-risk: moderate Directive: Extend the versioned sanitized snapshot only; never expose raw billing responses or credentials. Tested: Spec self-review and placeholder scan. Not-tested: Implementation behavior is intentionally pending.
Preserve Grok2API-style package balances and render them in the existing account status dialog while keeping the persisted projection strictly non-secret. Overage is retained for accounting and clamped only for display.\n\nConstraint: Keep the existing versioned snapshot, channel-scoped refresh flow, media eligibility evidence, and secret-redaction boundary backward compatible.\nRejected: Add a new quota table or expose raw upstream JSON | unnecessary schema churn and leakage risk.\nConfidence: high\nScope-risk: moderate\nDirective: Future quota fields must be added to the parser whitelist, controller projection, and frontend formatter together; never serialize credentials or raw upstream payloads.\nTested: go test ./relay/channel/groksubscription -count=1; go test ./controller -run 'TestGrok(AccountStatus|ChannelDetail|Auth)' -count=1; go test ./model -run 'TestGrok' -count=1; go build ./...; go vet ./relay/channel/groksubscription ./controller ./model; Bun Grok formatter tests; TypeScript build check; ESLint; Prettier; frontend Rsbuild build.\nNot-tested: Full controller package suite was not used because the unfiltered suite exceeded the local command window; targeted Grok controller/auth/channel tests passed.
feat(i18n): refine sidebar onboarding labels
Adds the isolated Seedance-2.5 static prototype under website/public with local-only interactions and no router/runtime changes.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
变更内容
验证
请在 staging 环境验证管理员页面与保存/刷新流程。