feat(inbounds): expose Vision testseed field with sensible default

Add a "Vision testseed" form item to the inbound modal for TCP + TLS/reality
inbounds, normalized to positive integers and defaulting to [900,500,900,256].
Apply the same default in the outbound form adapter when no valid saved seed
is present.

Replace the http/mixed snapshot assertions in inbound-defaults with explicit
field checks so generated credentials don't break the snapshots.
This commit is contained in:
MHSanaei
2026-05-28 02:33:13 +02:00
parent 1a096d72f1
commit 486ac9c28d
4 changed files with 28 additions and 19 deletions

View File

@@ -116,7 +116,7 @@ function vlessFromWire(raw: Raw): VlessOutboundFormSettings {
const testseed = savedSeed.length === 4
&& savedSeed.every((n) => Number.isInteger(n) && (n as number) > 0)
? (savedSeed as number[])
: [];
: [900, 500, 900, 256];
return {
address,
port,

View File

@@ -1428,6 +1428,21 @@ export default function InboundFormModal({
{t('pages.inbounds.vlessAuthSelected', { auth: selectedVlessAuth })}
</Text>
</Form.Item>
{network === 'tcp' && (security === 'tls' || security === 'reality') && (
<Form.Item
label="Vision testseed"
name={['settings', 'testseed']}
initialValue={[900, 500, 900, 256]}
normalize={(v: unknown) =>
Array.isArray(v)
? v.map((x) => Number(x)).filter((n) => Number.isInteger(n) && n > 0)
: []
}
extra="Applies only to clients using the xtls-rprx-vision flow; ignored otherwise."
>
<Select mode="tags" tokenSeparators={[',', ' ']} placeholder="four positive integers" />
</Form.Item>
)}
</>
)}

View File

@@ -1,12 +1,5 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`createDefault*InboundSettings factories > http 1`] = `
{
"accounts": [],
"allowTransparent": false,
}
`;
exports[`createDefault*InboundSettings factories > hysteria (v1, defaults to v2 wire version) 1`] = `
{
"clients": [],
@@ -14,15 +7,6 @@ exports[`createDefault*InboundSettings factories > hysteria (v1, defaults to v2
}
`;
exports[`createDefault*InboundSettings factories > mixed 1`] = `
{
"accounts": [],
"auth": "password",
"ip": "127.0.0.1",
"udp": false,
}
`;
exports[`createDefault*InboundSettings factories > shadowsocks 1`] = `
{
"clients": [],

View File

@@ -112,13 +112,23 @@ describe('createDefault*InboundSettings factories', () => {
it('http', () => {
const s = createDefaultHttpInboundSettings();
expect(s).toMatchSnapshot();
expect(s.allowTransparent).toBe(false);
const accounts = s.accounts ?? [];
expect(accounts).toHaveLength(1);
expect(accounts[0].user.length).toBe(8);
expect(accounts[0].pass.length).toBe(12);
expect(HttpInboundSettingsSchema.parse(s)).toEqual(s);
});
it('mixed', () => {
const s = createDefaultMixedInboundSettings();
expect(s).toMatchSnapshot();
expect(s.auth).toBe('password');
expect(s.udp).toBe(false);
expect(s.ip).toBe('127.0.0.1');
const accounts = s.accounts ?? [];
expect(accounts).toHaveLength(1);
expect(accounts[0].user.length).toBe(8);
expect(accounts[0].pass.length).toBe(12);
expect(MixedInboundSettingsSchema.parse(s)).toEqual(s);
});