fix(nodes): "Invalid input" when saving a node with inbound sync mode "all"

NodeFormSchema required inboundTags, but the inboundTags Form.Item is only
mounted when inboundSyncMode is "selected" - antd onFinish omits unmounted
fields, so saving with the default "all" mode failed schema validation with
Zod generic "Invalid input" (regression from #5178; same class as the
earlier pinnedCertSha256 fix).

Also tolerate null inboundTags (Go nil slice) for nodes saved before #5178,
both in the form schema and NodeRecordSchema, and normalize edit-mode values.
This commit is contained in:
MHSanaei
2026-06-12 02:29:46 +02:00
parent 60da6bed15
commit 5c29851be1
4 changed files with 10 additions and 9 deletions
+6 -3
View File
@@ -32,7 +32,8 @@ export const NodeRecordSchema = z.object({
tlsVerifyMode: z.enum(['verify', 'skip', 'pin']).optional(),
pinnedCertSha256: z.string().optional(),
inboundSyncMode: z.enum(['all', 'selected']).optional(),
inboundTags: z.array(z.string()).optional(),
// Backend serializes a nil []string as null for nodes saved before #5178.
inboundTags: z.array(z.string()).nullish(),
// Multi-hop node tree (#4983): a node's stable GUID, its parent's GUID, and
// whether it's a read-only transitive sub-node surfaced from a downstream node.
guid: z.string().optional(),
@@ -65,8 +66,10 @@ export const NodeFormSchema = z.object({
allowPrivateAddress: z.boolean(),
tlsVerifyMode: z.enum(['verify', 'skip', 'pin']),
pinnedCertSha256: z.string().optional().default(''),
inboundSyncMode: z.enum(['all', 'selected']),
inboundTags: z.array(z.string()),
inboundSyncMode: z.enum(['all', 'selected']).optional().default('all'),
// Unmounted when sync mode is "all" (absent from antd onFinish values) and
// serialized as null by the backend for a nil slice — tolerate both.
inboundTags: z.array(z.string()).nullish().transform((tags) => tags ?? []),
});
export type NodeRecord = z.infer<typeof NodeRecordSchema>;