From a1b2ae8c9a7ef64fad291ebe9033bd90edffdfb3 Mon Sep 17 00:00:00 2001 From: gadgethd <111318106+gadgethd@users.noreply.github.com> Date: Fri, 7 Aug 2026 02:30:20 +0000 Subject: [PATCH] fix(acl): render test-scope topic grants for owner devices (meshcore-test/+//...) so test-network observers can publish --- backend/src/mqtt/aclManager.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/src/mqtt/aclManager.ts b/backend/src/mqtt/aclManager.ts index bcd3d24..26a0e5f 100644 --- a/backend/src/mqtt/aclManager.ts +++ b/backend/src/mqtt/aclManager.ts @@ -139,6 +139,12 @@ function buildManagedSection(grants: OwnerAclGrant[], generation: string): strin lines.push(`topic write meshcore/+/${nodeId}/packets`); lines.push(`topic write meshcore/+/${nodeId}/status`); lines.push(`topic write meshcore/+/${nodeId}/neighbors`); + // Test-scope equivalents: grant holders may also run observer nodes in + // the isolated test network (network='test', e.g. IATA=TST) used for + // firmware bring-up and soak testing. + lines.push(`topic write meshcore-test/+/${nodeId}/packets`); + lines.push(`topic write meshcore-test/+/${nodeId}/status`); + lines.push(`topic write meshcore-test/+/${nodeId}/neighbors`); } lines.push(''); } @@ -240,7 +246,10 @@ export function validateRenderedOwnerAcl(content: string, expected: OwnerAclRend for (const nodeId of grant.nodeIds) { if (!content.includes(`topic write meshcore/+/${nodeId}/packets`) || !content.includes(`topic write meshcore/+/${nodeId}/status`) - || !content.includes(`topic write meshcore/+/${nodeId}/neighbors`)) { + || !content.includes(`topic write meshcore/+/${nodeId}/neighbors`) + || !content.includes(`topic write meshcore-test/+/${nodeId}/packets`) + || !content.includes(`topic write meshcore-test/+/${nodeId}/status`) + || !content.includes(`topic write meshcore-test/+/${nodeId}/neighbors`)) { throw new Error(`OWNER_ACL_SEMANTIC_MISMATCH:${grant.mqttUsername}:${nodeId}`); } }