feat(audience): add pull, push, and validate commands#728
feat(audience): add pull, push, and validate commands#728meryldakin wants to merge 1 commit intomeryldakin/audience-read-commandsfrom
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
|
||
| await Promise.all(writeAudienceDirPromises); | ||
| } catch (error) { | ||
| console.log(error); |
There was a problem hiding this comment.
Debug console.log left in error handler
Medium Severity
A console.log(error) statement is left in the catch block of writeAudiencesIndexDir. The equivalent writeWorkflowsIndexDir function in workflow/writer.ts does not have this, and the error is already re-thrown on the next line. This will leak raw error objects to stdout in production when a write failure occurs during a bulk pull operation.
a72033c to
f2d954f
Compare
e88e4ae to
48a559a
Compare
| } | ||
|
|
||
| return undefined; | ||
| }; |
There was a problem hiding this comment.
Exported validateAudienceKey function is never used
Low Severity
validateAudienceKey is exported from helpers.ts (and re-exported via index.ts) but is never called anywhere in the codebase. A grep for validateAudienceKey returns only its definition. This is dead code in the current PR, likely intended for the next PR in the stack (PR 4: new command), but adds unused surface area.
f2d954f to
38cdfb4
Compare
48a559a to
dfca967
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
|
|
||
| const promises = dirents.map(async (dirent) => { | ||
| const direntName = dirent.name.toLowerCase(); | ||
| const direntPath = path.resolve(indexDirCtx.abspath, direntName); |
There was a problem hiding this comment.
Lowercased path breaks pruning on case-sensitive filesystems
Medium Severity
In pruneAudiencesIndexDir, dirent.name is lowercased before constructing direntPath. On case-sensitive filesystems (Linux), if a directory has mixed-case naming (e.g., "VIP-Users"), direntPath points to a non-existent lowercased path. This causes isAudienceDir to check the wrong path and fs.remove to target a path that doesn't exist, meaning directories that should be pruned survive, and valid audience directories might not be recognized.
Add filesystem-based audience commands: - audience pull: Download audiences from Knock to local filesystem - audience push: Upload audiences from filesystem to Knock - audience validate: Validate local audience files against API Supporting changes: - Add audience marshal layer (processor, reader, writer, helpers) - Add audience directory detection in run-context loader - Add audience to project config resource directories - Update pull/push commands to handle audience resource type - Add audience factory for tests Includes full test coverage for all commands.
38cdfb4 to
765af13
Compare
dfca967 to
d7d638b
Compare
|
Superseded by #730 (combined PR) |



Summary
audience pull: Download audiences from Knock to local filesystemaudience push: Upload audiences from filesystem to Knockaudience validate: Validate local audience files against APIpull/pushcommands to handle audience resource typeaudiencefactory for testsStack
This is PR 3 of 4 in the audience resource implementation stack:
list,get,opencommandspull,push,validatecommands + marshal layernew,archivecommands + generatorDepends on: #727
Test Plan
🤖 Generated with Claude Code