feat: harden podman deployment orchestration

This commit is contained in:
Yahya Alhinai
2026-06-28 01:44:26 +00:00
parent 5185845090
commit c818d5081e
37 changed files with 1796 additions and 273 deletions
+4 -4
View File
@@ -50,10 +50,10 @@ export function CreatePodForm({
if (!open) {
return (
<button
className="group flex min-h-64 flex-col items-center justify-center gap-3 rounded-xl border border-dashed bg-card p-6 text-center transition hover:bg-muted/30"
className="group flex min-h-64 flex-col items-center justify-center gap-3 rounded-lg border border-dashed bg-card p-6 text-center shadow-sm transition hover:bg-muted/30 hover:ring-1 hover:ring-black/10"
onClick={() => setOpen(true)}
>
<span className="grid size-9 place-items-center rounded-lg bg-muted transition group-hover:bg-background">
<span className="grid size-9 place-items-center rounded-md bg-muted transition group-hover:bg-background">
<PlusIcon className="size-4 text-muted-foreground" />
</span>
<span className="text-sm font-medium">New pod</span>
@@ -68,7 +68,7 @@ export function CreatePodForm({
<Card className={cn(compact && 'w-full border-0 shadow-none ring-0')}>
<CardHeader>
<CardTitle>New pod</CardTitle>
<CardDescription>Keep the room name short and specific.</CardDescription>
<CardDescription>Create a focused room.</CardDescription>
</CardHeader>
<CardContent>
<FieldGroup>
@@ -117,7 +117,7 @@ export function CreatePodForm({
Cancel
</Button>
)}
<Button onClick={submit} disabled={busy || !name.trim()}>
<Button className="min-w-20" onClick={submit} disabled={busy || !name.trim()}>
Create
</Button>
</CardFooter>
+11 -5
View File
@@ -84,10 +84,12 @@ export function PodCard({
return (
<>
<Card className="min-h-64 transition duration-200 hover:-translate-y-0.5 hover:ring-foreground/15">
<Card className="min-h-64 transition duration-200 hover:-translate-y-0.5 hover:shadow-[0_2px_6px_rgba(0,0,0,0.06),0_28px_70px_rgba(0,0,0,0.06)] hover:ring-black/15">
<CardHeader>
<CardTitle className="truncate">{pod.name}</CardTitle>
<CardDescription className="truncate">{pod.repo || 'No repository set'}</CardDescription>
<CardTitle className="truncate text-[1.05rem]">{pod.name}</CardTitle>
<CardDescription className="truncate font-mono text-xs">
{pod.repo || 'No repository set'}
</CardDescription>
<CardAction>
<DropdownMenu>
<DropdownMenuTrigger asChild>
@@ -121,7 +123,7 @@ export function PodCard({
{pod.description || 'Focused workspace for live engineering coordination.'}
</p>
</div>
<Badge variant={active ? 'default' : 'secondary'}>
<Badge variant={active ? 'default' : 'secondary'} className="rounded-md">
{active ? `${presence.length} live` : 'quiet'}
</Badge>
</div>
@@ -175,7 +177,11 @@ export function PodCard({
<VideoIcon data-icon="inline-start" />
Join
</Button>
<Button onClick={() => submitMember(true)} disabled={busy || !newMember.trim()}>
<Button
className="min-w-28"
onClick={() => submitMember(true)}
disabled={busy || !newMember.trim()}
>
Add and join
</Button>
</CardFooter>
+16 -14
View File
@@ -185,8 +185,8 @@ export function PodView({
return (
<div className="min-h-screen bg-background text-foreground">
<div className="mx-auto flex min-h-screen w-full max-w-7xl flex-col gap-5 px-4 py-4 sm:px-6 lg:px-8">
<header className="flex items-center justify-between gap-4 border-b pb-4">
<div className="mx-auto flex min-h-screen w-full max-w-[1440px] flex-col gap-5 px-4 py-4 sm:px-6 lg:px-8">
<header className="sticky top-0 z-10 -mx-4 flex flex-col gap-3 border-b bg-background/86 px-4 pb-4 pt-2 backdrop-blur-xl sm:-mx-6 sm:px-6 md:flex-row md:items-center md:justify-between lg:-mx-8 lg:px-8">
<div className="flex min-w-0 items-center gap-3">
<Tooltip>
<TooltipTrigger asChild>
@@ -200,13 +200,15 @@ export function PodView({
<div className="min-w-0">
<div className="flex items-center gap-2">
<h1 className="truncate text-xl font-semibold tracking-tight">{team.name}</h1>
<Badge variant={room ? 'default' : 'secondary'}>{room ? 'live' : 'local'}</Badge>
<Badge variant={room ? 'default' : 'secondary'} className="rounded-md">
{room ? 'live' : 'local'}
</Badge>
</div>
<p className="truncate text-sm text-muted-foreground">{team.repo}</p>
<p className="truncate font-mono text-xs text-muted-foreground">{team.repo}</p>
</div>
</div>
<div className="flex items-center gap-2">
<div className="grid grid-cols-2 gap-2 sm:flex sm:items-center">
<Button variant="outline" onClick={toggleBeat} disabled={!room}>
<Volume2Icon data-icon="inline-start" />
{playingBeat ? 'Stop audio' : 'Test audio'}
@@ -244,8 +246,8 @@ export function PodView({
<Card className="flex-1">
<CardHeader>
<CardTitle>Room</CardTitle>
<CardDescription>Only the signals that matter right now.</CardDescription>
<CardTitle>Room state</CardTitle>
<CardDescription>People and media currently visible to PodMan.</CardDescription>
</CardHeader>
<CardContent>
{participants.length === 0 ? (
@@ -278,9 +280,9 @@ export function PodView({
<Card>
<CardHeader>
<CardTitle>Intervention</CardTitle>
<CardDescription>PodMan stays quiet until the signal is useful.</CardDescription>
<CardDescription>Card first, voice only for urgent escalation.</CardDescription>
<CardAction>
<Badge variant={active ? 'default' : 'secondary'}>
<Badge variant={active ? 'default' : 'secondary'} className="rounded-md">
{active ? 'active' : 'clear'}
</Badge>
</CardAction>
@@ -288,7 +290,7 @@ export function PodView({
<CardContent>
{active ? (
<div className="flex flex-col gap-4">
<div className="rounded-xl border bg-muted/30 p-3">
<div className="rounded-lg border bg-muted/35 p-3">
<p className="text-sm leading-6">{active.message}</p>
</div>
<div className="flex items-center justify-between gap-3 text-sm">
@@ -306,8 +308,8 @@ export function PodView({
</EmptyMedia>
<EmptyTitle>No collision detected</EmptyTitle>
<EmptyDescription>
Share your screen when ready. The agent will surface only meaningful
overlap.
Share your screen when ready. PodMan will stay quiet until there is a useful
signal.
</EmptyDescription>
</EmptyHeader>
</Empty>
@@ -372,7 +374,7 @@ function Participant({ participant }: { participant: PInfo }) {
return (
<div
className={cn(
'flex min-h-16 items-center justify-between gap-3 rounded-xl border bg-muted/20 px-3 transition',
'flex min-h-16 items-center justify-between gap-3 rounded-lg border bg-muted/20 px-3 transition',
participant.speaking && 'bg-muted',
)}
>
@@ -386,7 +388,7 @@ function Participant({ participant }: { participant: PInfo }) {
<p className="text-xs text-muted-foreground">{participant.isLocal ? 'you' : 'remote'}</p>
</div>
</div>
<Badge variant={participant.speaking ? 'default' : 'secondary'}>
<Badge variant={participant.speaking ? 'default' : 'secondary'} className="rounded-md">
{participant.speaking ? 'speaking' : 'connected'}
</Badge>
</div>
+5 -6
View File
@@ -5,7 +5,7 @@ import { Slot } from 'radix-ui';
import { cn } from '@/lib/utils';
const buttonVariants = cva(
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
@@ -23,14 +23,13 @@ const buttonVariants = cva(
size: {
default:
'h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
xs: "h-6 gap-1 rounded-md px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
sm: "h-7 gap-1 rounded-md px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
lg: 'h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
icon: 'size-8',
'icon-xs':
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
'icon-sm':
'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',
"size-6 rounded-md in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
'icon-sm': 'size-7 rounded-md in-data-[slot=button-group]:rounded-md',
'icon-lg': 'size-9',
},
},
+3 -3
View File
@@ -12,7 +12,7 @@ function Card({
data-slot="card"
data-size={size}
className={cn(
'group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl',
'group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-lg bg-card py-(--card-spacing) text-sm text-card-foreground shadow-[0_1px_2px_rgba(0,0,0,0.04),0_20px_60px_rgba(0,0,0,0.04)] ring-1 ring-black/[0.07] [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg',
className,
)}
{...props}
@@ -25,7 +25,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
<div
data-slot="card-header"
className={cn(
'group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)',
'group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)',
className,
)}
{...props}
@@ -77,7 +77,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
<div
data-slot="card-footer"
className={cn(
'flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)',
'flex items-center rounded-b-lg border-t bg-muted/35 p-(--card-spacing)',
className,
)}
{...props}