mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 08:19:59 +00:00
fix(safety): unify add-account typed risk phrase
- change required acknowledgement phrase to "I ACCEPT RISK" - apply typed phrase requirement to Gemini and Antigravity add-account flows - keep CLI/server and UI phrase validation aligned - update antigravity responsibility unit test
This commit is contained in:
@@ -14,7 +14,8 @@ import { getCliproxySafetyConfig } from '../config/unified-config-loader';
|
|||||||
|
|
||||||
export const ANTIGRAVITY_RISK_ISSUE_URL = 'https://github.com/kaitranntt/ccs/issues/509';
|
export const ANTIGRAVITY_RISK_ISSUE_URL = 'https://github.com/kaitranntt/ccs/issues/509';
|
||||||
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
|
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
|
||||||
export const ANTIGRAVITY_ACK_PHRASE = 'I ACCEPT AGY RISK';
|
export const RISK_ACK_PHRASE = 'I ACCEPT RISK';
|
||||||
|
export const ANTIGRAVITY_ACK_PHRASE = RISK_ACK_PHRASE;
|
||||||
export const ANTIGRAVITY_ACCEPT_RISK_FLAGS = ['--accept-agr-risk', '--accept-antigravity-risk'];
|
export const ANTIGRAVITY_ACCEPT_RISK_FLAGS = ['--accept-agr-risk', '--accept-antigravity-risk'];
|
||||||
|
|
||||||
type AgyRiskContext = 'oauth' | 'run';
|
type AgyRiskContext = 'oauth' | 'run';
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ describe('antigravity-responsibility', () => {
|
|||||||
reviewedIssue509: true,
|
reviewedIssue509: true,
|
||||||
understandsBanRisk: true,
|
understandsBanRisk: true,
|
||||||
acceptsFullResponsibility: true,
|
acceptsFullResponsibility: true,
|
||||||
typedPhrase: ' i accept agy risk ',
|
typedPhrase: ' i accept risk ',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.valid).toBeTrue();
|
expect(result.valid).toBeTrue();
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { AlertTriangle, ExternalLink, Settings2 } from 'lucide-react';
|
import { AlertTriangle, ExternalLink, Settings2 } from 'lucide-react';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import { RISK_ACK_PHRASE } from '@/components/account/antigravity-responsibility-constants';
|
||||||
|
|
||||||
interface AccountSafetyWarningCardProps {
|
interface AccountSafetyWarningCardProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
showAcknowledgement?: boolean;
|
showAcknowledgement?: boolean;
|
||||||
acknowledged?: boolean;
|
acknowledgementPhrase?: string;
|
||||||
onAcknowledgedChange?: (value: boolean) => void;
|
acknowledgementText?: string;
|
||||||
|
onAcknowledgementTextChange?: (value: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
showProxySettingsLink?: boolean;
|
showProxySettingsLink?: boolean;
|
||||||
}
|
}
|
||||||
@@ -16,8 +18,9 @@ interface AccountSafetyWarningCardProps {
|
|||||||
export function AccountSafetyWarningCard({
|
export function AccountSafetyWarningCard({
|
||||||
className,
|
className,
|
||||||
showAcknowledgement = false,
|
showAcknowledgement = false,
|
||||||
acknowledged = false,
|
acknowledgementPhrase = RISK_ACK_PHRASE,
|
||||||
onAcknowledgedChange,
|
acknowledgementText = '',
|
||||||
|
onAcknowledgementTextChange,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
showProxySettingsLink = false,
|
showProxySettingsLink = false,
|
||||||
}: AccountSafetyWarningCardProps) {
|
}: AccountSafetyWarningCardProps) {
|
||||||
@@ -99,20 +102,22 @@ export function AccountSafetyWarningCard({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showAcknowledgement && onAcknowledgedChange && (
|
{showAcknowledgement && onAcknowledgementTextChange && (
|
||||||
<div className="rounded-lg border border-amber-500/25 bg-amber-500/5 p-2.5">
|
<div className="rounded-lg border border-amber-500/25 bg-amber-500/5 p-2.5">
|
||||||
<div className="flex items-start gap-2">
|
<Label htmlFor="account-risk-ack-text" className="text-xs leading-5">
|
||||||
<Checkbox
|
Type exact phrase to continue:{' '}
|
||||||
id="account-risk-ack"
|
<code className="rounded bg-muted px-1 py-0.5 font-mono">
|
||||||
checked={acknowledged}
|
{acknowledgementPhrase}
|
||||||
onCheckedChange={(checked) => onAcknowledgedChange(Boolean(checked))}
|
</code>
|
||||||
disabled={disabled}
|
</Label>
|
||||||
/>
|
<Input
|
||||||
<Label htmlFor="account-risk-ack" className="text-xs leading-5">
|
id="account-risk-ack-text"
|
||||||
I understand this risk and that CCS takes no responsibility if I continue this
|
value={acknowledgementText}
|
||||||
setup.
|
onChange={(e) => onAcknowledgementTextChange(e.target.value)}
|
||||||
</Label>
|
placeholder={acknowledgementPhrase}
|
||||||
</div>
|
disabled={disabled}
|
||||||
|
className="mt-2 font-mono text-xs"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import { AntigravityResponsibilityChecklist } from '@/components/account/antigra
|
|||||||
import {
|
import {
|
||||||
ANTIGRAVITY_ACK_VERSION,
|
ANTIGRAVITY_ACK_VERSION,
|
||||||
DEFAULT_ANTIGRAVITY_RISK_CHECKLIST,
|
DEFAULT_ANTIGRAVITY_RISK_CHECKLIST,
|
||||||
|
RISK_ACK_PHRASE,
|
||||||
isAntigravityRiskChecklistComplete,
|
isAntigravityRiskChecklistComplete,
|
||||||
} from '@/components/account/antigravity-responsibility-constants';
|
} from '@/components/account/antigravity-responsibility-constants';
|
||||||
import {
|
import {
|
||||||
@@ -55,6 +56,10 @@ interface AddAccountDialogProps {
|
|||||||
isFirstAccount?: boolean;
|
isFirstAccount?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeRiskPhrase(value: string): string {
|
||||||
|
return value.trim().replace(/\s+/g, ' ').toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
export function AddAccountDialog({
|
export function AddAccountDialog({
|
||||||
open,
|
open,
|
||||||
onClose,
|
onClose,
|
||||||
@@ -66,7 +71,7 @@ export function AddAccountDialog({
|
|||||||
const [callbackUrl, setCallbackUrl] = useState('');
|
const [callbackUrl, setCallbackUrl] = useState('');
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const [localError, setLocalError] = useState<string | null>(null);
|
const [localError, setLocalError] = useState<string | null>(null);
|
||||||
const [acknowledgedRisk, setAcknowledgedRisk] = useState(false);
|
const [riskAcknowledgementText, setRiskAcknowledgementText] = useState('');
|
||||||
const [agyRiskChecklist, setAgyRiskChecklist] = useState(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
|
const [agyRiskChecklist, setAgyRiskChecklist] = useState(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
|
||||||
const [agyAckBypassEnabled, setAgyAckBypassEnabled] = useState(false);
|
const [agyAckBypassEnabled, setAgyAckBypassEnabled] = useState(false);
|
||||||
const [agyAckBypassLoading, setAgyAckBypassLoading] = useState(false);
|
const [agyAckBypassLoading, setAgyAckBypassLoading] = useState(false);
|
||||||
@@ -80,6 +85,7 @@ export function AddAccountDialog({
|
|||||||
const requiresAgyResponsibilityFlow = provider === 'agy' && !agyAckBypassEnabled;
|
const requiresAgyResponsibilityFlow = provider === 'agy' && !agyAckBypassEnabled;
|
||||||
const isAgyBypassStatePending = provider === 'agy' && agyAckBypassLoading;
|
const isAgyBypassStatePending = provider === 'agy' && agyAckBypassLoading;
|
||||||
const isAgyRiskChecklistComplete = isAntigravityRiskChecklistComplete(agyRiskChecklist);
|
const isAgyRiskChecklistComplete = isAntigravityRiskChecklistComplete(agyRiskChecklist);
|
||||||
|
const isGeminiRiskAcknowledged = normalizeRiskPhrase(riskAcknowledgementText) === RISK_ACK_PHRASE;
|
||||||
const defaultDeviceCode = isDeviceCodeProvider(provider);
|
const defaultDeviceCode = isDeviceCodeProvider(provider);
|
||||||
const requiresNickname = isNicknameRequiredProvider(provider);
|
const requiresNickname = isNicknameRequiredProvider(provider);
|
||||||
const kiroMethodOption = getKiroAuthMethodOption(kiroAuthMethod);
|
const kiroMethodOption = getKiroAuthMethodOption(kiroAuthMethod);
|
||||||
@@ -102,7 +108,7 @@ export function AddAccountDialog({
|
|||||||
setCallbackUrl('');
|
setCallbackUrl('');
|
||||||
setCopied(false);
|
setCopied(false);
|
||||||
setLocalError(null);
|
setLocalError(null);
|
||||||
setAcknowledgedRisk(false);
|
setRiskAcknowledgementText('');
|
||||||
setAgyRiskChecklist(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
|
setAgyRiskChecklist(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
|
||||||
setAgyAckBypassEnabled(false);
|
setAgyAckBypassEnabled(false);
|
||||||
setAgyAckBypassLoading(false);
|
setAgyAckBypassLoading(false);
|
||||||
@@ -113,7 +119,7 @@ export function AddAccountDialog({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
setAcknowledgedRisk(false);
|
setRiskAcknowledgementText('');
|
||||||
setAgyRiskChecklist(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
|
setAgyRiskChecklist(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
|
||||||
setLocalError(null);
|
setLocalError(null);
|
||||||
}
|
}
|
||||||
@@ -252,9 +258,9 @@ export function AddAccountDialog({
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (requiresSafetyAcknowledgement && !acknowledgedRisk) {
|
if (requiresSafetyAcknowledgement && !isGeminiRiskAcknowledged) {
|
||||||
setLocalError(
|
setLocalError(
|
||||||
'Please acknowledge the account safety warning before authenticating this provider.'
|
`Type "${RISK_ACK_PHRASE}" to acknowledge the account safety warning before authenticating this provider.`
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -348,9 +354,10 @@ export function AddAccountDialog({
|
|||||||
{requiresSafetyAcknowledgement && !showAuthUI && (
|
{requiresSafetyAcknowledgement && !showAuthUI && (
|
||||||
<AccountSafetyWarningCard
|
<AccountSafetyWarningCard
|
||||||
showAcknowledgement
|
showAcknowledgement
|
||||||
acknowledged={acknowledgedRisk}
|
acknowledgementPhrase={RISK_ACK_PHRASE}
|
||||||
onAcknowledgedChange={(value) => {
|
acknowledgementText={riskAcknowledgementText}
|
||||||
setAcknowledgedRisk(value);
|
onAcknowledgementTextChange={(value) => {
|
||||||
|
setRiskAcknowledgementText(value);
|
||||||
setLocalError(null);
|
setLocalError(null);
|
||||||
}}
|
}}
|
||||||
disabled={isPending}
|
disabled={isPending}
|
||||||
@@ -549,7 +556,7 @@ export function AddAccountDialog({
|
|||||||
isAgyBypassStatePending ||
|
isAgyBypassStatePending ||
|
||||||
(requiresNickname && !nicknameTrimmed) ||
|
(requiresNickname && !nicknameTrimmed) ||
|
||||||
(requiresAgyResponsibilityFlow && !isAgyRiskChecklistComplete) ||
|
(requiresAgyResponsibilityFlow && !isAgyRiskChecklistComplete) ||
|
||||||
(requiresSafetyAcknowledgement && !acknowledgedRisk)
|
(requiresSafetyAcknowledgement && !isGeminiRiskAcknowledged)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ExternalLink className="w-4 h-4 mr-2" />
|
<ExternalLink className="w-4 h-4 mr-2" />
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
|
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
|
||||||
export const ANTIGRAVITY_ACK_PHRASE = 'I ACCEPT AGY RISK';
|
export const RISK_ACK_PHRASE = 'I ACCEPT RISK';
|
||||||
|
export const ANTIGRAVITY_ACK_PHRASE = RISK_ACK_PHRASE;
|
||||||
|
|
||||||
export interface AntigravityRiskChecklistValue {
|
export interface AntigravityRiskChecklistValue {
|
||||||
reviewedIssue509: boolean;
|
reviewedIssue509: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user