sf-plugin-permission-sets 0.0.0-dev.6 → 0.0.0-dev.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/LICENSE.md +28 -0
  2. package/README.md +243 -85
  3. package/lib/adapters/connection-org-client.d.ts +21 -0
  4. package/lib/adapters/connection-org-client.d.ts.map +1 -0
  5. package/lib/adapters/connection-org-client.js +265 -0
  6. package/lib/adapters/connection-org-client.js.map +1 -0
  7. package/lib/adapters/index.d.ts +2 -0
  8. package/lib/adapters/index.d.ts.map +1 -0
  9. package/lib/adapters/index.js +2 -0
  10. package/lib/adapters/index.js.map +1 -0
  11. package/lib/commands/ps/apply.d.ts +41 -0
  12. package/lib/commands/ps/apply.d.ts.map +1 -0
  13. package/lib/commands/ps/apply.js +178 -0
  14. package/lib/commands/ps/apply.js.map +1 -0
  15. package/lib/commands/ps/check.d.ts +21 -0
  16. package/lib/commands/ps/check.d.ts.map +1 -0
  17. package/lib/commands/ps/check.js +55 -0
  18. package/lib/commands/ps/check.js.map +1 -0
  19. package/lib/commands/ps/export.d.ts +26 -0
  20. package/lib/commands/ps/export.d.ts.map +1 -0
  21. package/lib/commands/ps/export.js +74 -0
  22. package/lib/commands/ps/export.js.map +1 -0
  23. package/lib/commands/ps/plan.d.ts +61 -0
  24. package/lib/commands/ps/plan.d.ts.map +1 -0
  25. package/lib/commands/ps/plan.js +212 -0
  26. package/lib/commands/ps/plan.js.map +1 -0
  27. package/lib/commands/ps/validate.d.ts +21 -0
  28. package/lib/commands/ps/validate.d.ts.map +1 -0
  29. package/lib/commands/ps/validate.js +56 -0
  30. package/lib/commands/ps/validate.js.map +1 -0
  31. package/lib/core/diff.d.ts +10 -0
  32. package/lib/core/diff.d.ts.map +1 -0
  33. package/lib/core/diff.js +54 -0
  34. package/lib/core/diff.js.map +1 -0
  35. package/lib/core/finding.d.ts +41 -0
  36. package/lib/core/finding.d.ts.map +1 -0
  37. package/lib/core/finding.js +76 -0
  38. package/lib/core/finding.js.map +1 -0
  39. package/lib/core/index.d.ts +10 -0
  40. package/lib/core/index.d.ts.map +1 -0
  41. package/lib/core/index.js +9 -0
  42. package/lib/core/index.js.map +1 -0
  43. package/lib/core/load.d.ts +4 -0
  44. package/lib/core/load.d.ts.map +1 -0
  45. package/lib/core/load.js +60 -0
  46. package/lib/core/load.js.map +1 -0
  47. package/lib/core/mode.d.ts +18 -0
  48. package/lib/core/mode.d.ts.map +1 -0
  49. package/lib/core/mode.js +16 -0
  50. package/lib/core/mode.js.map +1 -0
  51. package/lib/core/model.d.ts +78 -0
  52. package/lib/core/model.d.ts.map +1 -0
  53. package/lib/core/model.js +2 -0
  54. package/lib/core/model.js.map +1 -0
  55. package/lib/core/normalize.d.ts +17 -0
  56. package/lib/core/normalize.d.ts.map +1 -0
  57. package/lib/core/normalize.js +72 -0
  58. package/lib/core/normalize.js.map +1 -0
  59. package/lib/core/parse.d.ts +10 -0
  60. package/lib/core/parse.d.ts.map +1 -0
  61. package/lib/core/parse.js +20 -0
  62. package/lib/core/parse.js.map +1 -0
  63. package/lib/core/report.d.ts +15 -0
  64. package/lib/core/report.d.ts.map +1 -0
  65. package/lib/core/report.js +122 -0
  66. package/lib/core/report.js.map +1 -0
  67. package/lib/core/resolve.d.ts +20 -0
  68. package/lib/core/resolve.d.ts.map +1 -0
  69. package/lib/core/resolve.js +88 -0
  70. package/lib/core/resolve.js.map +1 -0
  71. package/lib/core/schema.d.ts +23 -0
  72. package/lib/core/schema.d.ts.map +1 -0
  73. package/lib/core/schema.js +35 -0
  74. package/lib/core/schema.js.map +1 -0
  75. package/lib/core/serialize.d.ts +9 -0
  76. package/lib/core/serialize.d.ts.map +1 -0
  77. package/lib/core/serialize.js +36 -0
  78. package/lib/core/serialize.js.map +1 -0
  79. package/lib/index.d.ts +1 -0
  80. package/lib/index.d.ts.map +1 -0
  81. package/lib/services/adapters/index.d.ts +2 -0
  82. package/lib/services/adapters/index.d.ts.map +1 -0
  83. package/lib/services/adapters/index.js +2 -0
  84. package/lib/services/adapters/index.js.map +1 -0
  85. package/lib/services/adapters/org-client.d.ts +22 -0
  86. package/lib/services/adapters/org-client.d.ts.map +1 -0
  87. package/lib/services/adapters/org-client.js +2 -0
  88. package/lib/services/adapters/org-client.js.map +1 -0
  89. package/lib/services/apply.d.ts +39 -0
  90. package/lib/services/apply.d.ts.map +1 -0
  91. package/lib/services/apply.js +85 -0
  92. package/lib/services/apply.js.map +1 -0
  93. package/lib/services/check.d.ts +14 -0
  94. package/lib/services/check.d.ts.map +1 -0
  95. package/lib/services/check.js +18 -0
  96. package/lib/services/check.js.map +1 -0
  97. package/lib/services/export.d.ts +19 -0
  98. package/lib/services/export.d.ts.map +1 -0
  99. package/lib/services/export.js +29 -0
  100. package/lib/services/export.js.map +1 -0
  101. package/lib/services/index.d.ts +6 -0
  102. package/lib/services/index.d.ts.map +1 -0
  103. package/lib/services/index.js +6 -0
  104. package/lib/services/index.js.map +1 -0
  105. package/lib/services/plan.d.ts +29 -0
  106. package/lib/services/plan.d.ts.map +1 -0
  107. package/lib/services/plan.js +51 -0
  108. package/lib/services/plan.js.map +1 -0
  109. package/lib/services/resolution.d.ts +17 -0
  110. package/lib/services/resolution.d.ts.map +1 -0
  111. package/lib/services/resolution.js +48 -0
  112. package/lib/services/resolution.js.map +1 -0
  113. package/lib/services/validate.d.ts +21 -0
  114. package/lib/services/validate.d.ts.map +1 -0
  115. package/lib/services/validate.js +50 -0
  116. package/lib/services/validate.js.map +1 -0
  117. package/messages/ps.apply.md +85 -0
  118. package/messages/ps.check.md +33 -0
  119. package/messages/ps.export.md +45 -0
  120. package/messages/ps.plan.md +85 -0
  121. package/messages/ps.validate.md +29 -0
  122. package/package.json +115 -180
  123. package/lib/commands/ps/info.d.ts +0 -11
  124. package/lib/commands/ps/info.js +0 -17
  125. package/lib/commands/ps/info.js.map +0 -1
  126. package/messages/ps.info.md +0 -17
  127. package/oclif.lock +0 -7781
  128. package/oclif.manifest.json +0 -51
@@ -0,0 +1,51 @@
1
+ import { loadFiles, diffAssignments, countFindings } from '../core/index.js';
2
+ import { ResolutionService, managedTargets } from './resolution.js';
3
+ const emptyDiff = { toAdd: [], toUpdate: [], toRemove: [], unchanged: [] };
4
+ /** An aborted-before-the-diff result, carrying the findings that explain why. */
5
+ function invalidResult(files, findings) {
6
+ return {
7
+ files,
8
+ findings,
9
+ diff: emptyDiff,
10
+ drift: { adds: 0, updates: 0, removes: 0 },
11
+ status: 'invalid',
12
+ };
13
+ }
14
+ /**
15
+ * Read-only preview: load the files, resolve every reference to an org id, fetch the
16
+ * current state, and diff. The full diff (adds and would-be removes) is always returned
17
+ * regardless of mode; drift is whatever the chosen mode would not act on. Never changes
18
+ * the org. This is the apply pipeline stopping before any DML.
19
+ */
20
+ export class PlanService {
21
+ org;
22
+ constructor(org) {
23
+ this.org = org;
24
+ }
25
+ async run(files, mode) {
26
+ const loaded = await loadFiles(files);
27
+ const loadCounts = countFindings(loaded.findings);
28
+ if (loadCounts.errors > 0) {
29
+ return invalidResult(loaded.files, loaded.findings);
30
+ }
31
+ const resolutionService = new ResolutionService(this.org);
32
+ const resolution = await resolutionService.run(loaded.assignments);
33
+ const findings = [
34
+ ...loaded.findings,
35
+ ...resolution.findings,
36
+ ];
37
+ const findingCounts = countFindings(findings);
38
+ if (findingCounts.errors > 0) {
39
+ return invalidResult(loaded.files, findings);
40
+ }
41
+ const actual = await this.org.currentAssignments(managedTargets(resolution));
42
+ const diff = diffAssignments(loaded.assignments, actual);
43
+ const drift = {
44
+ adds: mode === 'destructive' ? diff.toAdd.length : 0,
45
+ updates: mode === 'destructive' ? diff.toUpdate.length : 0,
46
+ removes: mode === 'additive' ? diff.toRemove.length : 0,
47
+ };
48
+ return { files: loaded.files, findings, diff, drift, status: 'planned' };
49
+ }
50
+ }
51
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/services/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAiB,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE5F,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAgBpE,MAAM,SAAS,GAAS,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAEjF,iFAAiF;AACjF,SAAS,aAAa,CAAC,KAAe,EAAE,QAAmB;IACvD,OAAO;QACH,KAAK;QACL,QAAQ;QACR,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1C,MAAM,EAAE,SAAS;KACpB,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACgB;IAApC,YAAoC,GAAc;QAAd,QAAG,GAAH,GAAG,CAAW;IAAG,CAAC;IAE/C,KAAK,CAAC,GAAG,CAAC,KAAe,EAAE,IAAc;QAC5C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1D,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG;YACb,GAAG,MAAM,CAAC,QAAQ;YAClB,GAAG,UAAU,CAAC,QAAQ;SACzB,CAAC;QACF,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7E,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG;YACV,IAAI,EAAE,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACpD,OAAO,EAAE,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO,EAAE,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SAC1D,CAAC;QAEF,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC7E,CAAC;CACJ"}
@@ -0,0 +1,17 @@
1
+ import { DesiredAssignment, Kind, ResolvedAddition, TargetRef, Finding } from '../core/index.js';
2
+ import { OrgClient } from './adapters/index.js';
3
+ export type Resolution = {
4
+ findings: Finding[];
5
+ userIds: Map<string, string>;
6
+ targetIds: Record<Kind, Map<string, string>>;
7
+ };
8
+ export declare function managedTargets(resolution: Resolution): TargetRef[];
9
+ /** Attach the resolved assignee and target ids to each addition, so it can be inserted. */
10
+ export declare function resolveAdditions(additions: DesiredAssignment[], resolution: Resolution): ResolvedAddition[];
11
+ /** Look every declared reference up in the org, returning findings and the resolved id maps. */
12
+ export declare class ResolutionService {
13
+ private readonly org;
14
+ constructor(org: OrgClient);
15
+ run(assignments: DesiredAssignment[]): Promise<Resolution>;
16
+ }
17
+ //# sourceMappingURL=resolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution.d.ts","sourceRoot":"","sources":["../../src/services/resolution.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,iBAAiB,EACjB,IAAI,EAGJ,gBAAgB,EAChB,SAAS,EACT,OAAO,EAQV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAChD,CAAC;AAEF,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,EAAE,CAQlE;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,EAAE,EAAE,UAAU,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAM3G;AAED,gGAAgG;AAChG,qBAAa,iBAAiB;IACP,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,SAAS;IAErC,GAAG,CAAC,WAAW,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CAoC1E"}
@@ -0,0 +1,48 @@
1
+ import { kinds, distinctAssignees, distinctTargets, evaluateUsers, evaluateTargets, indexUsersById, indexTargetsById, } from '../core/index.js';
2
+ export function managedTargets(resolution) {
3
+ const refs = [];
4
+ for (const kind of kinds) {
5
+ for (const id of resolution.targetIds[kind].values()) {
6
+ refs.push({ kind, id });
7
+ }
8
+ }
9
+ return refs;
10
+ }
11
+ /** Attach the resolved assignee and target ids to each addition, so it can be inserted. */
12
+ export function resolveAdditions(additions, resolution) {
13
+ return additions.map((addition) => ({
14
+ ...addition,
15
+ assigneeId: resolution.userIds.get(addition.assignee.toLowerCase()) ?? '',
16
+ targetId: resolution.targetIds[addition.kind].get(addition.target.toLowerCase()) ?? '',
17
+ }));
18
+ }
19
+ /** Look every declared reference up in the org, returning findings and the resolved id maps. */
20
+ export class ResolutionService {
21
+ org;
22
+ constructor(org) {
23
+ this.org = org;
24
+ }
25
+ async run(assignments) {
26
+ const usernames = distinctAssignees(assignments);
27
+ const targetsByKind = kinds.map((kind) => ({ kind, targets: distinctTargets(assignments, kind) }));
28
+ const usersTask = usernames.length > 0 ? this.org.findUsers(usernames) : Promise.resolve([]);
29
+ const targetsTask = Promise.all(targetsByKind.map(async ({ kind, targets }) => {
30
+ const found = targets.length > 0 ? await this.org.findTargets(kind, targets) : [];
31
+ return { kind, targets, found };
32
+ }));
33
+ const [foundUsers, perKind] = await Promise.all([
34
+ usersTask,
35
+ targetsTask,
36
+ ]);
37
+ const findings = [...evaluateUsers(usernames, foundUsers)];
38
+ for (const { kind, targets, found } of perKind) {
39
+ findings.push(...evaluateTargets(kind, targets, found.map((target) => target.name)));
40
+ }
41
+ const targetIds = {};
42
+ for (const { kind, found } of perKind) {
43
+ targetIds[kind] = indexTargetsById(found);
44
+ }
45
+ return { findings, userIds: indexUsersById(foundUsers), targetIds };
46
+ }
47
+ }
48
+ //# sourceMappingURL=resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution.js","sourceRoot":"","sources":["../../src/services/resolution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { DesiredAssignment, Finding } from '../core/index.js';
2
+ import { OrgClient } from './adapters/index.js';
3
+ export type ValidateResult = {
4
+ files: string[];
5
+ assignments: DesiredAssignment[];
6
+ findings: Finding[];
7
+ errors: number;
8
+ warnings: number;
9
+ failed: boolean;
10
+ };
11
+ /** Load the files, then resolve every reference against the org. */
12
+ export declare class ValidateService {
13
+ private readonly org;
14
+ constructor(org: OrgClient);
15
+ run(files: string[]): Promise<ValidateResult>;
16
+ /** Look every reference up in the org (in parallel) and evaluate the results. */
17
+ private resolve;
18
+ private evaluateUserRefs;
19
+ private evaluateTargetRefs;
20
+ }
21
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/services/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAOH,iBAAiB,EACjB,OAAO,EAGV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,MAAM,cAAc,GAAG;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,oEAAoE;AACpE,qBAAa,eAAe;IACL,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,SAAS;IAErC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAoB1D,iFAAiF;YACnE,OAAO;YAmBP,gBAAgB;YAKhB,kBAAkB;CAQnC"}
@@ -0,0 +1,50 @@
1
+ import { loadFiles, kinds, distinctAssignees, distinctTargets, evaluateUsers, evaluateTargets, countFindings, } from '../core/index.js';
2
+ /** Load the files, then resolve every reference against the org. */
3
+ export class ValidateService {
4
+ org;
5
+ constructor(org) {
6
+ this.org = org;
7
+ }
8
+ async run(files) {
9
+ const loaded = await loadFiles(files);
10
+ const resolved = await this.resolve(loaded.assignments);
11
+ const findings = [
12
+ ...loaded.findings,
13
+ ...resolved,
14
+ ];
15
+ const { errors, warnings } = countFindings(findings);
16
+ return {
17
+ files: loaded.files,
18
+ assignments: loaded.assignments,
19
+ findings,
20
+ errors,
21
+ warnings,
22
+ failed: errors > 0,
23
+ };
24
+ }
25
+ /** Look every reference up in the org (in parallel) and evaluate the results. */
26
+ async resolve(assignments) {
27
+ const tasks = [];
28
+ const usernames = distinctAssignees(assignments);
29
+ if (usernames.length > 0) {
30
+ tasks.push(this.evaluateUserRefs(usernames));
31
+ }
32
+ for (const kind of kinds) {
33
+ const targets = distinctTargets(assignments, kind);
34
+ if (targets.length > 0) {
35
+ tasks.push(this.evaluateTargetRefs(kind, targets));
36
+ }
37
+ }
38
+ const results = await Promise.all(tasks);
39
+ return results.flat();
40
+ }
41
+ async evaluateUserRefs(usernames) {
42
+ const found = await this.org.findUsers(usernames);
43
+ return evaluateUsers(usernames, found);
44
+ }
45
+ async evaluateTargetRefs(kind, targets) {
46
+ const found = await this.org.findTargets(kind, targets);
47
+ return evaluateTargets(kind, targets, found.map((target) => target.name));
48
+ }
49
+ }
50
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/services/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,SAAS,EACT,KAAK,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,eAAe,EAIf,aAAa,GAChB,MAAM,kBAAkB,CAAC;AAY1B,oEAAoE;AACpE,MAAM,OAAO,eAAe;IACY;IAApC,YAAoC,GAAc;QAAd,QAAG,GAAH,GAAG,CAAW;IAAG,CAAC;IAE/C,KAAK,CAAC,GAAG,CAAC,KAAe;QAC5B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAExD,MAAM,QAAQ,GAAG;YACb,GAAG,MAAM,CAAC,QAAQ;YAClB,GAAG,QAAQ;SACd,CAAC;QACF,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAErD,OAAO;YACH,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,QAAQ;YACR,MAAM;YACN,QAAQ;YACR,MAAM,EAAE,MAAM,GAAG,CAAC;SACrB,CAAC;IACN,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,OAAO,CAAC,WAAgC;QAClD,MAAM,KAAK,GAA8B,EAAE,CAAC;QAE5C,MAAM,SAAS,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACnD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;YACvD,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,SAAmB;QAC9C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAClD,OAAO,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,IAAU,EAAE,OAAiB;QAC1D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,eAAe,CAClB,IAAI,EACJ,OAAO,EACP,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CACrC,CAAC;IACN,CAAC;CACJ"}
@@ -0,0 +1,85 @@
1
+ # summary
2
+
3
+ Reconcile a target org to match the permission set assignment files.
4
+
5
+ # description
6
+
7
+ Load the files, resolve every user and target against the org, diff the desired state against what the org currently has, then add, update expirations, and/or remove assignments per the mode. Additions, expiration updates, and removals run through the sObject Collections API with partial success, so one bad record does not roll back the rest. Deletions are capped by --max-deletes and confirmed before they run. Run validate and a --dry-run first.
8
+
9
+ # flags.file.summary
10
+
11
+ YAML file or glob to apply. Repeatable.
12
+
13
+ # flags.mode.summary
14
+
15
+ Which half of the reconcile to run: additive adds missing assignments and updates expirations, destructive removes only, sync does both.
16
+
17
+ # flags.max-deletes.summary
18
+
19
+ Abort before any change if the run would remove more than this many assignments.
20
+
21
+ # flags.dry-run.summary
22
+
23
+ Resolve and diff, print the plan, and change nothing.
24
+
25
+ # flags.show-unchanged.summary
26
+
27
+ List assignments that already match, instead of only counting them.
28
+
29
+ # flags.no-prompt.summary
30
+
31
+ Skip the deletion confirmation prompt. Required to delete in JSON or other non-interactive runs.
32
+
33
+ # confirm.delete
34
+
35
+ This will remove %s assignment(s) from the org. Continue?
36
+
37
+ # summary.dryRun
38
+
39
+ Dry run: %s to add, %s to update, %s to remove. Nothing was changed.
40
+
41
+ # summary.applied
42
+
43
+ Applied: %s added, %s updated, %s removed.
44
+
45
+ # summary.declined
46
+
47
+ Aborted at the confirmation prompt. Nothing was changed.
48
+
49
+ # drift.note
50
+
51
+ %s change(s) the %s mode does not act on were skipped (drift). Run plan to see them.
52
+
53
+ # failure.line
54
+
55
+ failed to %s %s on %s: %s
56
+
57
+ # error.invalid
58
+
59
+ The files do not resolve cleanly against the org. Fix the errors above, then re-run.
60
+
61
+ # error.maxDeletes
62
+
63
+ Refusing to remove %s assignment(s): over the --max-deletes limit of %s. Raise the limit or narrow the change.
64
+
65
+ # error.promptInJson
66
+
67
+ Refusing to delete without confirmation in a non-interactive run. Re-run with --no-prompt.
68
+
69
+ # error.failed
70
+
71
+ Some changes failed. See the per-record errors above.
72
+
73
+ # examples
74
+
75
+ - Preview a full reconcile of the dev org without changing anything:
76
+
77
+ <%= config.bin %> <%= command.id %> --file "permissions/*.yml" --target-org dev --mode sync --dry-run
78
+
79
+ - Grant any missing assignments (additive, the default):
80
+
81
+ <%= config.bin %> <%= command.id %> --file "permissions/*.yml" --target-org dev
82
+
83
+ - Full reconcile of production in CI, without prompts:
84
+
85
+ <%= config.bin %> <%= command.id %> --file "permissions/*.yml" --target-org prod --mode sync --no-prompt
@@ -0,0 +1,33 @@
1
+ # summary
2
+
3
+ Statically check permission set assignment files, with no org connection.
4
+
5
+ # description
6
+
7
+ Parse and validate the YAML files, no org needed. Reports invalid YAML, schema violations, duplicate keys, duplicate targets, and empty entries. Run it in a pre-commit hook or in CI before validate, plan, or apply.
8
+
9
+ # flags.file.summary
10
+
11
+ YAML file or glob to check. Repeatable.
12
+
13
+ # flags.strict.summary
14
+
15
+ Treat warnings as errors.
16
+
17
+ # summary.counts
18
+
19
+ %s errors, %s warnings.
20
+
21
+ # error.failed
22
+
23
+ Check found problems. See the output above.
24
+
25
+ # examples
26
+
27
+ - Check every file under permissions:
28
+
29
+ <%= config.bin %> <%= command.id %> --file "permissions/*.yml"
30
+
31
+ - Check specific files:
32
+
33
+ <%= config.bin %> <%= command.id %> --file permissions/sales.yml --file permissions/service.yml
@@ -0,0 +1,45 @@
1
+ # summary
2
+
3
+ Generate a YAML file from the current org's permission set assignments.
4
+
5
+ # description
6
+
7
+ Query the target org for every assignable permission set, group, and license assignment held by active users and write them to a single user-keyed YAML file. The result is valid input for check, validate, plan, and apply, so it is a read-only way to bootstrap adoption from an org's current state. Profile-owned permission sets and inactive users are skipped.
8
+
9
+ # flags.output-file.summary
10
+
11
+ Path of the YAML file to write. Created (and its parent directories) if missing, overwritten if present. Omit to write the document to stdout.
12
+
13
+ # flags.user.summary
14
+
15
+ Only export these users, matched on exact username. Repeatable; multiple values are a union.
16
+
17
+ # flags.kind.summary
18
+
19
+ Only export these scopes: permissionSets, permissionSetGroups, or permissionSetLicenses. Repeatable; combined with --user as an intersection.
20
+
21
+ # success
22
+
23
+ Exported %s assignments across %s users to %s.
24
+
25
+ # warnNoAssignments
26
+
27
+ No assignments in scope for user %s, it was skipped.
28
+
29
+ # examples
30
+
31
+ - Export the dev org's assignments to permissions.yml:
32
+
33
+ <%= config.bin %> <%= command.id %> --target-org dev --output-file permissions.yml
34
+
35
+ - Export a production org into an environment folder:
36
+
37
+ <%= config.bin %> <%= command.id %> --target-org prod --output-file permissions/prod.yml
38
+
39
+ - Write to stdout and diff against a committed snapshot:
40
+
41
+ <%= config.bin %> <%= command.id %> --target-org prod | diff - permissions/prod.yml
42
+
43
+ - Export two users' permission sets and groups only:
44
+
45
+ <%= config.bin %> <%= command.id %> --target-org prod --output-file team.yml --user jdoe@acme.com --user asmith@acme.com --kind permissionSets --kind permissionSetGroups
@@ -0,0 +1,85 @@
1
+ # summary
2
+
3
+ Preview the changes that would reconcile a target org to the assignment files.
4
+
5
+ # description
6
+
7
+ Load the files, resolve every user and target against the org, fetch the org's current assignments, and diff the desired state against them. Read-only: it queries the org but never changes it, so it is the apply pipeline stopping before any DML. The body shows only what the chosen mode would do, so what plan shows is what apply does. Anything the mode would not touch is reported beneath the plan as drift. Run it before apply to preview what would change.
8
+
9
+ # flags.file.summary
10
+
11
+ YAML file or glob to plan. Repeatable.
12
+
13
+ # flags.mode.summary
14
+
15
+ Which half of the reconcile to preview: additive adds and updates expirations, destructive removes only, sync does both. The plan shows only what the chosen mode would do; anything it skips is reported as drift.
16
+
17
+ # flags.show-unchanged.summary
18
+
19
+ List assignments that already match, instead of only counting them.
20
+
21
+ # header.title
22
+
23
+ Permission Set Assignments Plan
24
+
25
+ # header.org
26
+
27
+ Org: %s (%s) Mode: %s
28
+
29
+ # summary.counts.additive
30
+
31
+ Plan: %s to add, %s to update. %s users affected.
32
+
33
+ # summary.counts.destructive
34
+
35
+ Plan: %s to remove. %s users affected.
36
+
37
+ # summary.counts.sync
38
+
39
+ Plan: %s to add, %s to update, %s to remove. %s users affected.
40
+
41
+ # summary.unchanged
42
+
43
+ Unchanged: %s assignments (--show-unchanged to list).
44
+
45
+ # summary.unchangedListed
46
+
47
+ Unchanged: %s assignments.
48
+
49
+ # summary.next
50
+
51
+ Next: %s
52
+
53
+ # drift.additive
54
+
55
+ Drift: %s undeclared assignment(s) not removed in additive mode. Run --mode sync to remove them.
56
+
57
+ # drift.destructive
58
+
59
+ Drift: %s declared assignment(s) not applied in destructive mode. Run --mode additive or sync to apply them.
60
+
61
+ # empty.noChanges
62
+
63
+ No changes. %s already matches your files.
64
+
65
+ # empty.nothingToApply
66
+
67
+ Nothing to apply in %s mode.
68
+
69
+ # error.invalid
70
+
71
+ The files do not resolve cleanly against the org. Fix the errors above, then re-run.
72
+
73
+ # examples
74
+
75
+ - Preview a full reconcile of the dev org:
76
+
77
+ <%= config.bin %> <%= command.id %> --file "permissions/*.yml" --target-org dev --mode sync
78
+
79
+ - Preview only the additions the default additive run would make:
80
+
81
+ <%= config.bin %> <%= command.id %> --file "permissions/*.yml" --target-org dev
82
+
83
+ - Preview a full reconcile of production before applying it:
84
+
85
+ <%= config.bin %> <%= command.id %> --file "permissions/*.yml" --target-org prod --mode sync
@@ -0,0 +1,29 @@
1
+ # summary
2
+
3
+ Validate permission set assignment files against a target org.
4
+
5
+ # description
6
+
7
+ Run the same file checks as check, then resolve each referenced user, permission set, group, and license against the org. Reports users that are missing or inactive and targets that are missing or not unique. Read-only: it queries the org but never changes it. Run it before plan or apply.
8
+
9
+ # flags.file.summary
10
+
11
+ YAML file or glob to validate. Repeatable.
12
+
13
+ # summary.counts
14
+
15
+ %s errors, %s warnings.
16
+
17
+ # error.failed
18
+
19
+ Validation found problems. See the output above.
20
+
21
+ # examples
22
+
23
+ - Validate every file under permissions against the dev org:
24
+
25
+ <%= config.bin %> <%= command.id %> --file "permissions/\*.yml" --target-org dev
26
+
27
+ - Validate specific files against a named org:
28
+
29
+ <%= config.bin %> <%= command.id %> --file permissions/sales.yml --file permissions/service.yml --target-org prod