Skip to content

Commit 7261d55

Browse files
committed
fix(bridgeAccess): strip non-canonical permission fields before accesses.update
Plan 66 server's `accesses.update` schema is **strict** — it rejects extras like `defaultName` and `name` in permissions[] (asymmetric vs `accesses.create` which is lenient and `accesses.checkApp` which actually REQUIRES `defaultName`). Phase 5 e2e on demo surfaced this: POST accesses.update {permissions: [{streamId, level, defaultName}]} → invalid-parameters-format: OBJECT_ADDITIONAL_PROPERTIES ["defaultName"] Defensive strip in `ensureBridgeAccess` mirrors the pattern already in `CollectorClient.acceptUpdate` line 528: keep only the canonical `{streamId, level}` or `{feature, setting}` shape regardless of caller input. Validated by /tmp/plan58-e2e-mismatching.mjs against demo (Plan 66, schema v1). 489/489 tests pass. Lint clean.
1 parent 76f9bb1 commit 7261d55

1 file changed

Lines changed: 8 additions & 1 deletion

File tree

ts/appTemplates/bridgeAccess.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,14 @@ export async function ensureBridgeAccess (
109109
}
110110

111111
// Update in place. Server merges clientData; we only send our new keys.
112-
const updatePayload: Record<string, any> = { permissions: options.permissions };
112+
// accesses.update's permissions schema is strict (rejects defaultName / name);
113+
// strip to canonical {streamId,level} | {feature,setting} regardless of caller input.
114+
const cleanedPermissions = options.permissions.map((p: any) => {
115+
if (p.streamId) return { streamId: p.streamId, level: p.level };
116+
if (p.feature) return { feature: p.feature, setting: p.setting };
117+
return p;
118+
});
119+
const updatePayload: Record<string, any> = { permissions: cleanedPermissions };
113120
if (options.clientData != null) updatePayload.clientData = options.clientData;
114121

115122
try {

0 commit comments

Comments
 (0)