source: advance the checked projection

Source-Sha: 194a59adfd6c901635da7a9c18253bb2210e2426
Policy-Sha: b9b0be0ee74e55f561a803b8aef6be3c2134f5a83b46816a069a372f2eb04f4d
Tree-Digest: 4697f2e281c1c6ecafff17cf6eeb391a0a1ac0fa6e5fc429f5b473f4579c252c
This commit is contained in:
Source publisher 2026-09-21 14:39:08 +00:00
commit ffdccba10f
42 changed files with 2516 additions and 554 deletions

View file

@ -204,13 +204,15 @@ const AgentsEnrollment: React.FC = () => {
const [installPlatform, setInstallPlatform] = useState<string>('linux');
const [installTokenId, setInstallTokenId] = useState<string>('');
const [copiedCommand, setCopiedCommand] = useState<string | null>(null);
const [createdToken, setCreatedToken] = useState<{ token: string; label: string } | null>(null);
const [createdToken, setCreatedToken] = useState<{ token: string; label: string; fleetJoin: boolean } | null>(null);
// Create-key form
const [formData, setFormData] = useState<CreateRegistrationTokenRequest>({
label: '',
expires_in: '168h',
max_seats: 1,
fleet_join: false,
totp_seed: '',
});
// Signing keys (preserved from the old Agent Management page — now its own
@ -249,7 +251,7 @@ const AgentsEnrollment: React.FC = () => {
const availableTokens = React.useMemo(
() =>
allTokens.filter(
(t) => !t.revoked && t.status === 'active' && t.seats_used < t.max_seats,
(t) => !t.revoked && t.status === 'active' && t.seats_used < t.max_seats && !t.metadata?.fleet_join,
),
[allTokens],
);
@ -293,11 +295,17 @@ const AgentsEnrollment: React.FC = () => {
const handleCreateToken = (e: React.FormEvent) => {
e.preventDefault();
createToken.mutate(formData, {
const request: CreateRegistrationTokenRequest = {
...formData,
max_seats: formData.fleet_join ? 1 : formData.max_seats,
totp_seed: formData.fleet_join ? formData.totp_seed?.trim().toUpperCase() : undefined,
};
createToken.mutate(request, {
onSuccess: (data: any) => {
const label = formData.label || data.label;
setFormData({ label: '', expires_in: '168h', max_seats: 1 });
setCreatedToken({ token: data.token, label });
const fleetJoin = Boolean(formData.fleet_join);
setFormData({ label: '', expires_in: '168h', max_seats: 1, fleet_join: false, totp_seed: '' });
setCreatedToken({ token: data.token, label, fleetJoin });
refetch();
},
});
@ -435,8 +443,10 @@ const AgentsEnrollment: React.FC = () => {
<div className="space-y-4">
<div className="alert alert-success flex items-start justify-between gap-3">
<p className="text-sm text-success-800">
<span className="font-medium">Key "{createdToken.label}" created.</span> Copy the
token now — it cannot be retrieved again, only a hash is stored.
<span className="font-medium">Key "{createdToken.label}" created.</span>{' '}
{createdToken.fleetJoin
? 'Return to the standalone Desktop and enter this token.'
: 'Copy the token now, then choose the target platform and copy its install command.'}
</p>
<button
onClick={() => setCreatedToken(null)}
@ -460,13 +470,21 @@ const AgentsEnrollment: React.FC = () => {
</button>
</div>
</div>
<PlatformPicker value={installPlatform} onChange={setInstallPlatform} />
<InstallCommandBox
command={installCommand}
platform={installPlatform}
copied={copiedCommand === 'install'}
onCopy={() => copyToClipboard(installCommand, 'install')}
/>
{createdToken.fleetJoin ? (
<div className="rounded-lg border border-primary-200 bg-primary-50 p-4 text-sm text-primary-900">
This one-seat key can join only the standalone Agent whose host seed you entered. It is not an install key.
</div>
) : (
<>
<PlatformPicker value={installPlatform} onChange={setInstallPlatform} />
<InstallCommandBox
command={installCommand}
platform={installPlatform}
copied={copiedCommand === 'install'}
onCopy={() => copyToClipboard(installCommand, 'install')}
/>
</>
)}
</div>
) : (
<div className="space-y-4">
@ -551,6 +569,18 @@ const AgentsEnrollment: React.FC = () => {
)
) : (
<form onSubmit={handleCreateToken} className="space-y-4">
<label className="flex items-start gap-3 rounded-lg border border-gray-200 bg-gray-50 p-4 cursor-pointer">
<input
type="checkbox"
checked={Boolean(formData.fleet_join)}
onChange={(e) => setFormData({ ...formData, fleet_join: e.target.checked, max_seats: e.target.checked ? 1 : formData.max_seats })}
className="mt-1"
/>
<span>
<span className="block text-sm font-medium text-gray-900">Join an existing standalone machine</span>
<span className="block text-xs text-gray-500 mt-1">Creates one key for one existing Agent ID. Generate the host seed in RedFlag Desktop first.</span>
</span>
</label>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Label *</label>
@ -584,13 +614,29 @@ const AgentsEnrollment: React.FC = () => {
type="number"
min="1"
max="100"
value={formData.max_seats || 1}
value={formData.fleet_join ? 1 : formData.max_seats || 1}
disabled={Boolean(formData.fleet_join)}
onChange={(e) => setFormData({ ...formData, max_seats: parseInt(e.target.value) || 1 })}
className="form-input"
/>
<p className="mt-1 text-xs text-gray-500">Number of agents that can enroll with this key</p>
<p className="mt-1 text-xs text-gray-500">{formData.fleet_join ? 'Fleet join keys always have one seat' : 'Number of agents that can enroll with this key'}</p>
</div>
</div>
{formData.fleet_join && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Standalone host seed *</label>
<input
type="text"
required
autoComplete="off"
spellCheck={false}
value={formData.totp_seed || ''}
onChange={(e) => setFormData({ ...formData, totp_seed: e.target.value.toUpperCase().replace(/\s/g, '') })}
placeholder="Paste the seed shown by RedFlag Desktop"
className="form-input font-mono"
/>
</div>
)}
<button type="submit" disabled={createToken.isPending} className="btn-primary">
{createToken.isPending ? 'Creating...' : 'Create key'}
</button>
@ -690,6 +736,7 @@ const AgentsEnrollment: React.FC = () => {
<div className="mt-1 flex items-center gap-1.5 text-xs text-gray-500">
<span className={cn('inline-block w-2 h-2 rounded-full', STATUS_DOT[t.status] || 'bg-gray-400')} />
<span>{getStatusText(t)}</span>
{t.metadata?.fleet_join && <span className="text-primary-700 font-medium">Fleet join</span>}
<span>·</span>
<span>
{t.seats_used}/{t.max_seats} seats
@ -728,10 +775,13 @@ const AgentsEnrollment: React.FC = () => {
<span className={cn('badge badge-lg', tokenStatusColor(selectedToken.status))}>
{getStatusText(selectedToken)}
</span>
{selectedToken.metadata?.fleet_join && (
<span className="badge badge-lg ml-2 bg-primary-100 text-primary-800">Fleet join</span>
)}
</div>
</div>
<div className="flex items-center gap-2 shrink-0">
{selectedToken.status === 'active' && selectedToken.seats_used < selectedToken.max_seats && (
{selectedToken.status === 'active' && selectedToken.seats_used < selectedToken.max_seats && !selectedToken.metadata?.fleet_join && (
<button
onClick={() => installWithKey(selectedToken.id)}
className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm text-primary-700 bg-primary-50 border border-primary-200 rounded-md hover:bg-primary-100"

View file

@ -525,6 +525,8 @@ export interface CreateRegistrationTokenRequest {
expires_in?: string;
max_seats?: number;
metadata?: Record<string, any>;
fleet_join?: boolean;
totp_seed?: string;
}
export interface RegistrationTokenStats {