docs: update README with desktop requirements, helper builds, and realistic MVP usage notes

Expand README with desktop platform requirements (Windows x86, macOS ARM), helper build commands, gateway utility scripts, and updated local test flow. Add realistic MVP usage section clarifying current platform build status, gateway configuration needs, and admin debug profile behavior with client private key handling.
This commit is contained in:
2026-03-16 06:30:08 +01:00
parent 7c4bba1021
commit 6ec5133773
32 changed files with 1076 additions and 49 deletions

View File

@@ -1,4 +1,4 @@
import { useQuery } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api } from "../../api/client";
import { Page } from "../../components/Page";
@@ -13,12 +13,27 @@ const columns = [
];
export function DevicesPage() {
const queryClient = useQueryClient();
const query = useQuery({
queryKey: ["devices"],
queryFn: api.devices
});
const profileQuery = useQuery({
queryKey: ["device-profile", query.data?.[0]?.id ?? ""],
queryFn: () => api.deviceProfile(query.data?.[0]?.id ?? ""),
enabled: Boolean(query.data?.[0]?.id)
});
const revokeMutation = useMutation({
mutationFn: api.revokeDevice,
onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["devices"] })
});
const rotateMutation = useMutation({
mutationFn: api.rotateDevice,
onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["devices"] })
});
const rows = query.data?.map((device) => ({
id: device.id,
name: device.name,
owner: device.user_id ?? "assigned user",
platform: device.platform,
@@ -34,6 +49,23 @@ export function DevicesPage() {
rows={rows}
renderCell={(row, column) => <span>{row[column.key as keyof (typeof rows)[number]]}</span>}
/>
{rows.length > 0 ? (
<div className="grid two">
<div className="card">
<h4>Selected device profile</h4>
<p className="notice">Admin view shows a debug template. The client private key stays on the device.</p>
<pre className="code-block">{profileQuery.data?.profile.content ?? "Loading profile..."}</pre>
</div>
<div className="card">
<h4>Device actions</h4>
<p>Target: {rows[0].name}</p>
<div className="action-row">
<button className="button" onClick={() => rotateMutation.mutate(rows[0].id)}>Rotate profile</button>
<button className="ghost-button" onClick={() => revokeMutation.mutate(rows[0].id)}>Revoke device</button>
</div>
</div>
</div>
) : null}
</Page>
);
}