@microsoft/managed-apps-cli 0.8.0 → 0.9.0

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 (88) hide show
  1. package/README.md +13 -7
  2. package/dist/ArgumentProvider.d.ts.map +1 -1
  3. package/dist/ArgumentProvider.js +26 -19
  4. package/dist/ArgumentProvider.js.map +1 -1
  5. package/dist/Authentication/NodeMsalAuthenticationProvider.d.ts +16 -0
  6. package/dist/Authentication/NodeMsalAuthenticationProvider.d.ts.map +1 -1
  7. package/dist/Authentication/NodeMsalAuthenticationProvider.js +58 -6
  8. package/dist/Authentication/NodeMsalAuthenticationProvider.js.map +1 -1
  9. package/dist/Cli.d.ts.map +1 -1
  10. package/dist/Cli.js +22 -7
  11. package/dist/Cli.js.map +1 -1
  12. package/dist/CliSettings.d.ts +2 -2
  13. package/dist/CliSettings.d.ts.map +1 -1
  14. package/dist/CliSettings.js +2 -2
  15. package/dist/CliUtils.d.ts +16 -6
  16. package/dist/CliUtils.d.ts.map +1 -1
  17. package/dist/CliUtils.js +15 -23
  18. package/dist/CliUtils.js.map +1 -1
  19. package/dist/Constants/HelpStrings.d.ts +1 -1
  20. package/dist/Constants/HelpStrings.d.ts.map +1 -1
  21. package/dist/Constants/HelpStrings.js +12 -12
  22. package/dist/Constants/HelpStrings.js.map +1 -1
  23. package/dist/Constants.d.ts +1 -1
  24. package/dist/Constants.d.ts.map +1 -1
  25. package/dist/Constants.js +5 -2
  26. package/dist/Constants.js.map +1 -1
  27. package/dist/Errors/GitHubErrorMap.d.ts.map +1 -1
  28. package/dist/Errors/GitHubErrorMap.js +17 -10
  29. package/dist/Errors/GitHubErrorMap.js.map +1 -1
  30. package/dist/HttpClient/CliHttpClient.d.ts +13 -0
  31. package/dist/HttpClient/CliHttpClient.d.ts.map +1 -1
  32. package/dist/HttpClient/CliHttpClient.js +24 -0
  33. package/dist/HttpClient/CliHttpClient.js.map +1 -1
  34. package/dist/Logger/CliLogger.d.ts +50 -8
  35. package/dist/Logger/CliLogger.d.ts.map +1 -1
  36. package/dist/Logger/CliLogger.js +92 -37
  37. package/dist/Logger/CliLogger.js.map +1 -1
  38. package/dist/Logger/ConsoleWriter.d.ts +5 -0
  39. package/dist/Logger/ConsoleWriter.d.ts.map +1 -1
  40. package/dist/Logger/ConsoleWriter.js +22 -14
  41. package/dist/Logger/ConsoleWriter.js.map +1 -1
  42. package/dist/Middletier/FunctionsBundler.js +5 -1
  43. package/dist/Middletier/FunctionsBundler.js.map +1 -1
  44. package/dist/Middletier/PackFunctions.d.ts +5 -4
  45. package/dist/Middletier/PackFunctions.d.ts.map +1 -1
  46. package/dist/Middletier/PackFunctions.js +8 -7
  47. package/dist/Middletier/PackFunctions.js.map +1 -1
  48. package/dist/Types/Cli.types.d.ts +1 -1
  49. package/dist/Types/Cli.types.d.ts.map +1 -1
  50. package/dist/Utils/DcfRecovery.d.ts.map +1 -1
  51. package/dist/Utils/DcfRecovery.js +12 -4
  52. package/dist/Utils/DcfRecovery.js.map +1 -1
  53. package/dist/Utils/EnvVars.d.ts +1 -1
  54. package/dist/Utils/EnvVars.d.ts.map +1 -1
  55. package/dist/Utils/EnvVars.js.map +1 -1
  56. package/dist/Utils/RepoUrl.d.ts +11 -6
  57. package/dist/Utils/RepoUrl.d.ts.map +1 -1
  58. package/dist/Utils/RepoUrl.js +1 -1
  59. package/dist/Utils/RepoUrl.js.map +1 -1
  60. package/dist/Utils/ResolveCommand.d.ts +32 -2
  61. package/dist/Utils/ResolveCommand.d.ts.map +1 -1
  62. package/dist/Utils/ResolveCommand.js +70 -11
  63. package/dist/Utils/ResolveCommand.js.map +1 -1
  64. package/dist/Verbs/CreateMaafApp.d.ts +5 -5
  65. package/dist/Verbs/CreateMaafApp.d.ts.map +1 -1
  66. package/dist/Verbs/CreateMaafApp.js +43 -25
  67. package/dist/Verbs/CreateMaafApp.js.map +1 -1
  68. package/dist/Verbs/GetSettings.d.ts.map +1 -1
  69. package/dist/Verbs/GetSettings.js +9 -18
  70. package/dist/Verbs/GetSettings.js.map +1 -1
  71. package/dist/Verbs/Init.d.ts.map +1 -1
  72. package/dist/Verbs/Init.js +27 -52
  73. package/dist/Verbs/Init.js.map +1 -1
  74. package/dist/Verbs/MaafAppPermissions.d.ts +12 -6
  75. package/dist/Verbs/MaafAppPermissions.d.ts.map +1 -1
  76. package/dist/Verbs/MaafAppPermissions.js +208 -66
  77. package/dist/Verbs/MaafAppPermissions.js.map +1 -1
  78. package/dist/Verbs/RefreshGitAuth.d.ts.map +1 -1
  79. package/dist/Verbs/RefreshGitAuth.js +30 -15
  80. package/dist/Verbs/RefreshGitAuth.js.map +1 -1
  81. package/dist/Verbs/SetSetting.d.ts.map +1 -1
  82. package/dist/Verbs/SetSetting.js +39 -49
  83. package/dist/Verbs/SetSetting.js.map +1 -1
  84. package/dist/Verbs/VerbConstants.d.ts +13 -12
  85. package/dist/Verbs/VerbConstants.d.ts.map +1 -1
  86. package/dist/Verbs/VerbConstants.js +10 -15
  87. package/dist/Verbs/VerbConstants.js.map +1 -1
  88. package/package.json +5 -5
@@ -5,7 +5,7 @@ import { createAsync, getEnvironmentByName, getPlayerServiceConfig, resolveAppSe
5
5
  import { AppConfigFileName, VERSION } from '@microsoft/managed-apps-common/config';
6
6
  import { getUserRoutingEnvironmentAsync } from '@microsoft/managed-apps-common/services';
7
7
  import { getCliLogger, getSettings } from '../CliSettings.js';
8
- import { createDefaultStringOption } from '../CliUtils.js';
8
+ import { createDefaultStringOption, resolveEnvironmentId } from '../CliUtils.js';
9
9
  import { CLI_CLIENT_ID } from '../Constants.js';
10
10
  import { CLI_BINARY_NAME } from '../Constants/CliConstants.js';
11
11
  import { HelpStrings } from '../Constants/HelpStrings.js';
@@ -14,7 +14,6 @@ import { printInfo, printSuccess } from '../Utils/ConsoleOutput.js';
14
14
  import { withGitHubDcfRecoveryAsync } from '../Utils/DcfRecovery.js';
15
15
  import { resolveRoutingEnvironmentIdAsync } from '../Utils/EnvironmentRoutingUtils.js';
16
16
  import { getCurrentGitRemoteUrl } from '../Utils/GitUtils.js';
17
- import { parseGitHubRepoUrl } from '../Utils/RepoUrl.js';
18
17
  import { InitArguments } from './VerbConstants.js';
19
18
  export async function initAsync(argumentProvider) {
20
19
  const settings = getSettings();
@@ -31,8 +30,9 @@ export async function initAsync(argumentProvider) {
31
30
  throw new UsageError('Unable to determine tenant ID. Ensure you are logged in.');
32
31
  }
33
32
  // Validate required options.
34
- const preResolvedEnvironmentId = normalizeOptionalString(argumentProvider.getEnvironmentId()) ??
35
- normalizeOptionalString(await argumentProvider.getOption('environmentId', true));
33
+ const preResolvedEnvironmentId = await resolveEnvironmentId(argumentProvider, {
34
+ failIfMissing: false,
35
+ });
36
36
  if (preResolvedEnvironmentId && !(await validateEnvironmentExists(preResolvedEnvironmentId))) {
37
37
  throw new NotFoundError(`Environment '${preResolvedEnvironmentId}' not found. Please verify the environment ID and ensure you have access to it.`);
38
38
  }
@@ -47,41 +47,24 @@ export async function initAsync(argumentProvider) {
47
47
  });
48
48
  });
49
49
  // determine the repoType to use for this app.
50
- // if there is a .git in the current project, read the remote URL.
51
- // if GHE - ask user if they want to use this, or provision a platform managed repo.
52
- // if not GHE - offer to provision a platform managed repo or continue without source control integration & user will have to upload build artifacts manually when they want to publish.
53
- // if there is no .git, provision a platform managed repo and link it to the app
50
+ // if there is a .git in the current project, read the remote URL. If
51
+ // `--use-existing-git-repo` is set, link it to the app. Otherwise (or if
52
+ // there is no .git), a platform-managed repo will be provisioned and linked
53
+ // to the app instead. URL shape is no longer validated here the server is
54
+ // the authority and will reject anything it can't bind.
54
55
  const remoteUrl = getCurrentGitRemoteUrl();
55
56
  let selectedRemoteUrl;
56
57
  let repoType = 'native';
57
58
  if (remoteUrl) {
58
- try {
59
- parseGitHubRepoUrl(remoteUrl);
60
- printInfo(`Detected git remote URL: ${remoteUrl}`);
61
- const useExistingGitRepo = await argumentProvider.getOption('useExistingGitRepo', false);
62
- if (useExistingGitRepo) {
63
- printInfo(`Will use the existing git repo and link it to the app.`);
64
- repoType = 'github';
65
- selectedRemoteUrl = remoteUrl;
66
- }
67
- else {
68
- printInfo(`Will not use the existing git repo. A new platform-managed git repo will be provisioned and linked to the app instead.`);
69
- }
59
+ printInfo(`Detected git remote URL: ${remoteUrl}`);
60
+ const useExistingGitRepo = await argumentProvider.getOption('useExistingGitRepo', false);
61
+ if (useExistingGitRepo) {
62
+ printInfo(`Will use the existing git repo and link it to the app.`);
63
+ repoType = 'github';
64
+ selectedRemoteUrl = remoteUrl;
70
65
  }
71
- catch (error) {
72
- logger.trackErrorEvent('Init.GitRemoteUrlParseFailure', {
73
- error: error instanceof Error ? error.message : String(error),
74
- gitRemoteUrl: remoteUrl,
75
- });
76
- printInfo(`Detected git remote URL '${remoteUrl}' is not a valid GitHub Enterprise URL.`);
77
- const provisionGitRepo = await argumentProvider.getOption('provisionGitRepo', false);
78
- if (provisionGitRepo) {
79
- printInfo(`A new platform-managed git repo will be provisioned and linked to the app. The existing git repo will not be used.`);
80
- }
81
- else {
82
- printInfo(`No git repo will be linked to the app. You will be able to upload build artifacts manually when you want to publish the app.`);
83
- repoType = 'none';
84
- }
66
+ else {
67
+ printInfo(`Will not use the existing git repo. A new platform-managed git repo will be provisioned and linked to the app instead.`);
85
68
  }
86
69
  }
87
70
  // not ignoring prompts for these options
@@ -109,6 +92,7 @@ export async function initAsync(argumentProvider) {
109
92
  repositoryId: undefined,
110
93
  remoteUrl: selectedRemoteUrl,
111
94
  repoType,
95
+ origin: settings.origin,
112
96
  };
113
97
  // On `repoType: 'github'`, wrap createAsync with the DCF catch-and-retry:
114
98
  // a missing/expired GitHub identity mapping is recovered in-band by running
@@ -152,14 +136,15 @@ export async function initAsync(argumentProvider) {
152
136
  await writeRepoConfig(settings.fileConfig.appConfigPath, appConfig);
153
137
  printSuccess(`Created ${AppConfigFileName} for ${displayName}.`);
154
138
  printInfo(`Hint: Run 'npx ${CLI_BINARY_NAME} app add connection' to connect data, or 'npx ${CLI_BINARY_NAME} dev' to start the app locally.`);
155
- if (repoType !== 'none') {
156
- // Use `git push -u origin HEAD` (not bare `git push`) so the hint works
157
- // even when no upstream is configured for the current branch — common in
158
- // freshly-cloned or freshly-init'd projects. Mirrors what `ms app create`
159
- // runs automatically.
160
- printInfo(`Hint: Commit and push to wire your app to the remote repository: ` +
161
- `git add . && git commit -m '<message>' && git push -u origin HEAD.`);
162
- }
139
+ // Use `git push -u origin HEAD` (not bare `git push`) so the hint works
140
+ // even when no upstream is configured for the current branch common in
141
+ // freshly-cloned or freshly-init'd projects. Mirrors what `ms app create`
142
+ // runs automatically. Always printed: `repoType` here is `'native' | 'github'`
143
+ // (Init's local `'none'` branch was removed when CLI-side URL validation was
144
+ // dropped — `repoType: 'none'` still exists for `ms app create --repo none`.)
145
+ // and both flows benefit from the commit-and-push reminder.
146
+ printInfo(`Hint: Commit and push to wire your app to the remote repository: ` +
147
+ `git add . && git commit -m '<message>' && git push -u origin HEAD.`);
163
148
  }
164
149
  function createOptionSchema(argumentProvider) {
165
150
  argumentProvider.setDescription(HelpStrings.app.init.description);
@@ -244,12 +229,6 @@ function createOptionSchema(argumentProvider) {
244
229
  },
245
230
  description: HelpStrings.app.init.options.useExistingGitRepo,
246
231
  },
247
- {
248
- flags: {
249
- key: InitArguments.ProvisionGitRepo.name,
250
- },
251
- description: HelpStrings.app.init.options.provisionGitRepo,
252
- },
253
232
  ]);
254
233
  argumentProvider.addSwitch({
255
234
  flags: { key: InitArguments.OpenBrowser.name },
@@ -274,8 +253,4 @@ async function validateEnvironmentExists(environmentId) {
274
253
  return false;
275
254
  }
276
255
  }
277
- function normalizeOptionalString(value) {
278
- const normalized = value?.trim();
279
- return normalized ? normalized : undefined;
280
- }
281
256
  //# sourceMappingURL=Init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Init.js","sourceRoot":"","sources":["../../src/Verbs/Init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Init.js","sourceRoot":"","sources":["../../src/Verbs/Init.ts"],"names":[],"mappings":"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"}
@@ -7,10 +7,13 @@ export type MaafAppPermissionsMode = 'share' | 'unshare';
7
7
  /**
8
8
  * Selects which access level the caller wants to grant/revoke:
9
9
  *
10
- * - `play` — read-only access to the MAAF app itself (the `MicrosoftAppReader`
11
- * role granted at the app scope via PowerApps RP).
12
- * - `edit` — read + write access to the underlying git repository (the
13
- * `RepositoryContributor` role granted at the repo scope via GRS).
10
+ * - `play` — read-only access to the MAAF app itself, granted at the app scope
11
+ * via PowerApps RP (`MicrosoftAppReader` role).
12
+ * - `edit` — read + write access to the app's code. The concrete scope depends
13
+ * on `repoType`: for `native` repositories the `RepositoryContributor` role
14
+ * is granted at the GRS repo scope; for `none` / `github` repositories the
15
+ * `MicrosoftAppContributor` role is granted at the MAAF app scope instead
16
+ * (since there is no platform-managed repository to attach a role to).
14
17
  *
15
18
  * Each invocation targets exactly one access level; the two scopes are
16
19
  * independent.
@@ -32,8 +35,11 @@ export type MaafAppAccessLevel = 'play' | 'edit';
32
35
  * to AAD object ids via Graph, pass GUID-shaped inputs through unchanged.
33
36
  * 5. Dispatch to the matching share/unshare path:
34
37
  * - `play` → MAAF `modifyRoleAssignments` (`MicrosoftAppReader` at app scope).
35
- * - `edit` → fetch the app's `repositoryId` then GRS `modifyRoleAssignments`
36
- * (`RepositoryContributor` at repo scope).
38
+ * - `edit` + `repoType === 'native'` → fetch the app's `repositoryId` then
39
+ * GRS `modifyRoleAssignments` (`RepositoryContributor` at repo scope).
40
+ * - `edit` + `repoType === 'none' | 'github'` → MAAF `modifyRoleAssignments`
41
+ * (`MicrosoftAppContributor` at app scope); GRS is skipped because the
42
+ * platform does not manage the repository.
37
43
  * For unshare, paginate the matching list endpoint and pass through the
38
44
  * full `RoleAssignment[]` records on `delete` (the strict wire contract
39
45
  * requires `roleAssignmentId`, which only the list endpoint provides).
@@ -1 +1 @@
1
- {"version":3,"file":"MaafAppPermissions.d.ts","sourceRoot":"","sources":["../../src/Verbs/MaafAppPermissions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwBH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,4EAA4E;AAC5E,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,SAAS,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,CAAC;AAuBjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,8BAA8B,CAClD,gBAAgB,EAAE,gBAAgB,EAClC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAsFf"}
1
+ {"version":3,"file":"MaafAppPermissions.d.ts","sourceRoot":"","sources":["../../src/Verbs/MaafAppPermissions.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2BH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,4EAA4E;AAC5E,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,SAAS,CAAC;AAEzD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,CAAC;AAuBjD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,8BAA8B,CAClD,gBAAgB,EAAE,gBAAgB,EAClC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA+If"}
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * Copyright (C) Microsoft Corporation. All rights reserved.
3
3
  */
4
- import { GrsRepositoryContributorRoleName, infoAsync, MaafAppReaderRoleName, modifyGrsRoleAssignmentsAsync, modifyMaafRoleAssignmentsAsync, resolvePrincipalByEmailAsync, unshareGrsRepoByPrincipalsAsync, unshareMaafAppByPrincipalsAsync, } from '@microsoft/managed-apps-actions';
4
+ import { GrsRepositoryContributorRoleName, infoAsync, MaafAppContributorRoleName, MaafAppReaderRoleName, modifyGrsRoleAssignmentsAsync, modifyMaafRoleAssignmentsAsync, resolvePrincipalByEmailAsync, unshareGrsRepoByPrincipalsAsync, unshareMaafAppByPrincipalsAsync, } from '@microsoft/managed-apps-actions';
5
5
  import { AppConfigFileName } from '@microsoft/managed-apps-common/config';
6
6
  import { HttpClientError } from '@microsoft/managed-apps-common/services';
7
7
  import { getCliLogger, getSettings } from '../CliSettings.js';
@@ -27,8 +27,11 @@ import { ShareMaafAppArguments, UnshareMaafAppArguments } from './VerbConstants.
27
27
  * to AAD object ids via Graph, pass GUID-shaped inputs through unchanged.
28
28
  * 5. Dispatch to the matching share/unshare path:
29
29
  * - `play` → MAAF `modifyRoleAssignments` (`MicrosoftAppReader` at app scope).
30
- * - `edit` → fetch the app's `repositoryId` then GRS `modifyRoleAssignments`
31
- * (`RepositoryContributor` at repo scope).
30
+ * - `edit` + `repoType === 'native'` → fetch the app's `repositoryId` then
31
+ * GRS `modifyRoleAssignments` (`RepositoryContributor` at repo scope).
32
+ * - `edit` + `repoType === 'none' | 'github'` → MAAF `modifyRoleAssignments`
33
+ * (`MicrosoftAppContributor` at app scope); GRS is skipped because the
34
+ * platform does not manage the repository.
32
35
  * For unshare, paginate the matching list endpoint and pass through the
33
36
  * full `RoleAssignment[]` records on `delete` (the strict wire contract
34
37
  * requires `roleAssignmentId`, which only the list endpoint provides).
@@ -50,72 +53,144 @@ export async function executeMaafAppPermissionsAsync(argumentProvider, mode) {
50
53
  }
51
54
  const appName = await resolveAppNameAsync(argumentProvider);
52
55
  const access = parseAccessLevel(await argumentProvider.getOption('access'));
53
- const repoType = cliSettings.appConfig.repoType ?? 'native';
54
- if (access === 'edit' && repoType === 'none') {
55
- throw new UsageError(`App '${appName}' has no associated repository in the platform, so edit access cannot be modified.`);
56
- }
56
+ // `repoType` only affects edit routing. For play we should never fail on the
57
+ // strict migration check for legacy config shape.
58
+ const repoType = access === 'edit'
59
+ ? resolveRepoType(cliSettings.appConfig)
60
+ : (cliSettings.appConfig.repoType ?? 'none');
57
61
  const inputs = parseInputs(argumentProvider.getPositionalArg(0));
58
62
  if (inputs.length === 0) {
59
63
  throw new UsageError('Provide at least one principal as a comma-separated list (AAD object IDs or email addresses).');
60
64
  }
61
- // Failures (bad shape, no Graph match, transport error) are collected here so
62
- // we can warn the user but still proceed with the entries that resolved.
63
- const failures = [];
64
- const refs = await resolveAllAsync(inputs, failures);
65
- // If nothing resolved, the operation has no inputs to apply — abort with a
66
- // single error listing every failure rather than calling the RP with an empty
67
- // array.
68
- if (refs.length === 0) {
69
- throw new UsageError(formatFailures(failures));
70
- }
71
- // Otherwise warn about the unresolved entries up front (so they're visible
72
- // before the success line), then proceed with the resolved subset.
73
- if (failures.length > 0) {
74
- printWarning(formatFailures(failures));
75
- }
76
- const dispatch = mode === 'share' ? shareDispatchAsync : unshareDispatchAsync;
77
- const outcome = await dispatch({ tenantId, environmentId, appName, access, refs });
78
- if (argumentProvider.isJsonMode()) {
79
- // Envelope semantics for this verb: `success: true` means the modify call
80
- // reached the RP and returned. When some inputs failed to resolve before
81
- // the modify, `partialFailure` is `true` and `warnings` lists the
82
- // unresolved entries. Consumers requiring full success must check both
83
- // `success === true && partialFailure === false`. `warnings` is always
84
- // present (empty array on full success) so consumers can treat its
85
- // length uniformly. The server response is spread flat into the envelope
86
- // (matching every other verb that emits JSON) instead of nested under a
87
- // `result` key. For unshare we also include the action-layer bookkeeping
88
- // (`revokedCount`, `revokedPrincipalCount`, `notFound`, `skipped`) that
89
- // would otherwise only appear in the human summary — so automation gets
90
- // the same fidelity as text mode.
91
- printJsonSuccess({
65
+ // Top-level scenario that ties together every server call the verb makes:
66
+ // Graph principal resolution (`ResolvePrincipalByEmail` per email), optional
67
+ // app-info fetch (`GetMaafApp`) when the edit path needs the `repositoryId`,
68
+ // and the final modify call (one of `ModifyMaafRoleAssignments`,
69
+ // `ModifyGrsRepositoryRoleAssignments`, `UnshareMaafAppByPrincipals`, or
70
+ // `UnshareGrsRepoByPrincipals`). Each of those actions already emits its own
71
+ // wire-scoped scenario; this scenario captures the verb-level outcome plus
72
+ // the routing decision (scope/role) so we can correlate. All properties are
73
+ // PII-safe — counts and routing flags only, no emails / GUIDs / app names.
74
+ const logger = getCliLogger();
75
+ const scenario = logger.trackScenario('MaafApp.SharePermissions', {
76
+ mode,
77
+ access,
78
+ repoType,
79
+ inputCount: inputs.length,
80
+ });
81
+ try {
82
+ // Failures (bad shape, no Graph match, transport error) are collected here so
83
+ // we can warn the user but still proceed with the entries that resolved.
84
+ const failures = [];
85
+ const refs = await resolveAllAsync(inputs, failures);
86
+ // Verb-level summary of the Graph fan-out. Each underlying lookup also
87
+ // emits a `ResolvePrincipalByEmail` scenario; this event makes the
88
+ // aggregate result queryable per share/unshare invocation.
89
+ logger.trackActivityEvent('MaafApp.SharePermissions.PrincipalResolution', {
90
+ mode,
91
+ inputCount: inputs.length,
92
+ resolvedCount: refs.length,
93
+ failedCount: failures.length,
94
+ });
95
+ // If nothing resolved, the operation has no inputs to apply — abort with a
96
+ // single error listing every failure rather than calling the RP with an empty
97
+ // array.
98
+ if (refs.length === 0) {
99
+ throw new UsageError(formatFailures(failures));
100
+ }
101
+ // Otherwise warn about the unresolved entries up front (so they're visible
102
+ // before the success line), then proceed with the resolved subset.
103
+ if (failures.length > 0) {
104
+ printWarning(formatFailures(failures));
105
+ }
106
+ const dispatch = mode === 'share' ? shareDispatchAsync : unshareDispatchAsync;
107
+ const outcome = await dispatch({
108
+ tenantId,
109
+ environmentId,
110
+ appName,
92
111
  access,
93
- partialFailure: failures.length > 0,
94
- ...outcome.result,
112
+ refs,
113
+ repoType,
114
+ jsonMode: argumentProvider.isJsonMode(),
115
+ });
116
+ scenario.complete({
117
+ resolvedCount: refs.length,
118
+ failedResolutionCount: failures.length,
119
+ scope: outcome.scope,
120
+ role: outcome.role,
121
+ // App-scope contributor fallback for `edit` is the noteworthy routing
122
+ // case introduced for non-native `repoType`. Tagged here so it's a
123
+ // simple boolean filter on the success event.
124
+ appScopeContributorFallback: access === 'edit' && outcome.scope === 'app',
95
125
  ...(mode === 'unshare' && {
96
126
  revokedCount: outcome.revokedCount ?? 0,
97
127
  revokedPrincipalCount: outcome.revokedPrincipalCount ?? 0,
98
- notFound: (outcome.notFound ?? []).map(toJsonRef),
99
- skipped: (outcome.skipped ?? []).map(toJsonRef),
128
+ notFoundCount: outcome.notFound?.length ?? 0,
129
+ skippedCount: outcome.skipped?.length ?? 0,
100
130
  }),
101
- warnings: failures,
102
131
  });
132
+ if (argumentProvider.isJsonMode()) {
133
+ // Envelope semantics for this verb: `success: true` means the modify call
134
+ // reached the RP and returned. When some inputs failed to resolve before
135
+ // the modify, `partialFailure` is `true` and `warnings` lists the
136
+ // unresolved entries. Consumers requiring full success must check both
137
+ // `success === true && partialFailure === false`. `warnings` is always
138
+ // present (empty array on full success) so consumers can treat its
139
+ // length uniformly. The server response is spread flat into the envelope
140
+ // (matching every other verb that emits JSON) instead of nested under a
141
+ // `result` key. For unshare we also include the action-layer bookkeeping
142
+ // (`revokedCount`, `revokedPrincipalCount`, `notFound`, `skipped`) that
143
+ // would otherwise only appear in the human summary — so automation gets
144
+ // the same fidelity as text mode.
145
+ printJsonSuccess({
146
+ access,
147
+ partialFailure: failures.length > 0,
148
+ ...outcome.result,
149
+ ...(mode === 'unshare' && {
150
+ revokedCount: outcome.revokedCount ?? 0,
151
+ revokedPrincipalCount: outcome.revokedPrincipalCount ?? 0,
152
+ notFound: (outcome.notFound ?? []).map(toJsonRef),
153
+ skipped: (outcome.skipped ?? []).map(toJsonRef),
154
+ }),
155
+ warnings: failures,
156
+ });
157
+ }
158
+ else {
159
+ printSummary({ appName, mode, access, inputCount: refs.length, outcome });
160
+ }
103
161
  }
104
- else {
105
- printSummary({ appName, mode, access, inputCount: refs.length, outcome });
162
+ catch (error) {
163
+ scenario.failure(error);
164
+ throw error;
106
165
  }
107
166
  }
108
167
  async function shareDispatchAsync(inputs) {
109
- const { tenantId, environmentId, appName, access, refs } = inputs;
168
+ const { tenantId, environmentId, appName, access, refs, repoType, jsonMode } = inputs;
110
169
  if (access === 'play') {
111
- const entries = refs.map(toMaafPermissionEntry);
170
+ const entries = refs.map((r) => toMaafPermissionEntry(r, MaafAppReaderRoleName));
171
+ const result = await modifyMaafRoleAssignmentsAsync({
172
+ tenantId,
173
+ environmentId,
174
+ logger: getCliLogger(),
175
+ actionsParams: { appName, put: entries, delete: [] },
176
+ });
177
+ return { result, scope: 'app', role: MaafAppReaderRoleName };
178
+ }
179
+ // access === 'edit': route by repoType.
180
+ if (repoType !== 'native') {
181
+ // The app has no platform-managed repository, so grant contributor access
182
+ // at the app scope instead of going through GRS.
183
+ if (!jsonMode) {
184
+ printInfo(`App '${appName}' has no platform-managed repository, so granting contributor access at the app scope instead of repository scope.`);
185
+ }
186
+ const entries = refs.map((r) => toMaafPermissionEntry(r, MaafAppContributorRoleName));
112
187
  const result = await modifyMaafRoleAssignmentsAsync({
113
188
  tenantId,
114
189
  environmentId,
115
190
  logger: getCliLogger(),
116
191
  actionsParams: { appName, put: entries, delete: [] },
117
192
  });
118
- return { result };
193
+ return { result, scope: 'app', role: MaafAppContributorRoleName };
119
194
  }
120
195
  const repoId = await resolveRepositoryIdAsync({ tenantId, environmentId, appName });
121
196
  const entries = refs.map(toGrsPermissionEntry);
@@ -125,30 +200,49 @@ async function shareDispatchAsync(inputs) {
125
200
  logger: getCliLogger(),
126
201
  actionsParams: { repoId, put: entries, delete: [] },
127
202
  });
128
- return { result };
203
+ return { result, scope: 'repo', role: GrsRepositoryContributorRoleName };
129
204
  }
130
205
  async function unshareDispatchAsync(inputs) {
131
- const { tenantId, environmentId, appName, access, refs } = inputs;
206
+ const { tenantId, environmentId, appName, access, refs, repoType, jsonMode } = inputs;
132
207
  const principalIds = refs.map((r) => r.id);
133
208
  const refsByPrincipalId = new Map(refs.map((r) => [r.id, r]));
134
- const actionResult = access === 'play'
135
- ? await unshareMaafAppByPrincipalsAsync({
209
+ const useAppScope = access === 'play' || repoType !== 'native';
210
+ const role = useAppScope
211
+ ? access === 'play'
212
+ ? MaafAppReaderRoleName
213
+ : MaafAppContributorRoleName
214
+ : GrsRepositoryContributorRoleName;
215
+ let actionResult;
216
+ if (useAppScope) {
217
+ if (access === 'edit') {
218
+ if (!jsonMode) {
219
+ printInfo(`App '${appName}' has no platform-managed repository, so revoking contributor access at the app scope instead of repository scope.`);
220
+ }
221
+ }
222
+ actionResult = await unshareMaafAppByPrincipalsAsync({
136
223
  tenantId,
137
224
  environmentId,
138
225
  logger: getCliLogger(),
139
- actionsParams: { appName, principalIds },
140
- })
141
- : await (async () => {
142
- const repoId = await resolveRepositoryIdAsync({ tenantId, environmentId, appName });
143
- return unshareGrsRepoByPrincipalsAsync({
144
- tenantId,
145
- environmentId,
146
- logger: getCliLogger(),
147
- actionsParams: { repoId, principalIds },
148
- });
149
- })();
226
+ actionsParams: {
227
+ appName,
228
+ principalIds,
229
+ roleDefinitionName: role,
230
+ },
231
+ });
232
+ }
233
+ else {
234
+ const repoId = await resolveRepositoryIdAsync({ tenantId, environmentId, appName });
235
+ actionResult = await unshareGrsRepoByPrincipalsAsync({
236
+ tenantId,
237
+ environmentId,
238
+ logger: getCliLogger(),
239
+ actionsParams: { repoId, principalIds },
240
+ });
241
+ }
150
242
  return {
151
243
  result: actionResult.result,
244
+ scope: useAppScope ? 'app' : 'repo',
245
+ role,
152
246
  revokedCount: actionResult.revokedCount,
153
247
  revokedPrincipalCount: actionResult.revokedPrincipalCount,
154
248
  notFound: actionResult.notFoundPrincipalIds.map((id) => refsByPrincipalId.get(id) ?? { id, input: id }),
@@ -156,6 +250,27 @@ async function unshareDispatchAsync(inputs) {
156
250
  { id: s.principalObjectId, input: s.principalObjectId }),
157
251
  };
158
252
  }
253
+ /**
254
+ * Resolves the effective {@link RepoType} from an `AppConfig`.
255
+ *
256
+ * Hard rule: if `repoType` is missing AND the config carries a (non-empty,
257
+ * non-zero-GUID) `repositoryId`, refuse to guess - the user must re-run
258
+ * `app init` to migrate the config. When both are missing we treat it as
259
+ * `'none'`: there is no repo-scope to act on, and the app-scope fallback in
260
+ * the share/unshare dispatchers handles edit correctly.
261
+ */
262
+ function resolveRepoType(appConfig) {
263
+ if (appConfig.repoType) {
264
+ return appConfig.repoType;
265
+ }
266
+ const hasRepoId = !!appConfig.repositoryId && appConfig.repositoryId !== '00000000-0000-0000-0000-000000000000';
267
+ if (hasRepoId) {
268
+ throw new UsageError(`${AppConfigFileName} is missing the 'repoType' field but has a 'repositoryId' set. ` +
269
+ `This usually means the file was written by an older CLI. ` +
270
+ `Re-run "npx ${CLI_BINARY_NAME} app init" to migrate the config, then retry.`);
271
+ }
272
+ return 'none';
273
+ }
159
274
  /**
160
275
  * Fetches the app's `repositoryId` via the info action. Used by the `edit`
161
276
  * access paths to drive the GRS repo-scope share/unshare endpoints.
@@ -177,13 +292,16 @@ async function resolveRepositoryIdAsync(args) {
177
292
  * verb keeps its pre-flag behaviour for callers that haven't migrated. Throws
178
293
  * a `UsageError` on any other value — Commander.js doesn't enforce enum
179
294
  * membership by default and we want a precise error message.
295
+ *
296
+ * `play` and `edit` are the only externally visible levels. The role and scope
297
+ * the level resolves to are decided downstream (see {@link MaafAppAccessLevel}).
180
298
  */
181
299
  function parseAccessLevel(raw) {
182
300
  const value = (raw ?? 'play').trim().toLowerCase();
183
301
  if (value === 'play' || value === 'edit') {
184
302
  return value;
185
303
  }
186
- throw new UsageError(`Unknown --access value '${raw}'. Use 'play' (default — app access) or 'edit' (repository access).`);
304
+ throw new UsageError(`Unknown --access value '${raw}'. Use 'play' (default — app access) or 'edit' (edit access).`);
187
305
  }
188
306
  /**
189
307
  * Splits a comma-separated string into a deduplicated, trimmed list of inputs.
@@ -289,6 +407,15 @@ function formatFailures(failures) {
289
407
  */
290
408
  function extractGraphErrorMessage(error) {
291
409
  if (error instanceof HttpClientError) {
410
+ // A 403 from Graph is a consent/permission problem with the caller's
411
+ // sign-in, not a bad principal. Echoing Graph's opaque "Insufficient
412
+ // privileges to complete the operation" under the "Could not resolve
413
+ // <email>" heading misleads users into thinking the email is wrong, so we
414
+ // replace it with an actionable message naming the real cause and the
415
+ // ways forward. See {@link formatGraphPermissionError}.
416
+ if (error.status === 403) {
417
+ return formatGraphPermissionError(error.status);
418
+ }
292
419
  const message = extractGraphMessageFromBody(error.body);
293
420
  if (message !== undefined) {
294
421
  return `Graph ${error.status}: ${message}`;
@@ -297,6 +424,21 @@ function extractGraphErrorMessage(error) {
297
424
  }
298
425
  return error instanceof Error ? error.message : String(error);
299
426
  }
427
+ /**
428
+ * Builds the actionable reason for a Graph 403 hit during principal resolution.
429
+ * The email→object-id lookup needs the `User.ReadBasic.All` and
430
+ * `Group.Read.All` delegated Graph permissions; a 403 means the active
431
+ * account's token doesn't carry them in this tenant (consent was never
432
+ * granted). Rather than surface Graph's opaque "Insufficient privileges", we
433
+ * name the cause and the two ways forward: get those permissions consented, or
434
+ * skip the lookup entirely by passing the AAD object ID (GUID) instead of an
435
+ * email.
436
+ */
437
+ function formatGraphPermissionError(status) {
438
+ return (`Graph ${status}: your sign-in lacks permission to look up accounts by email. ` +
439
+ `Pass the AAD object ID (GUID) instead, or have an admin grant the ` +
440
+ `User.ReadBasic.All and Group.Read.All Graph permissions.`);
441
+ }
300
442
  /**
301
443
  * Parses a Graph error body string and returns the inner `error.message`. Returns
302
444
  * `undefined` if the body is missing, not valid JSON, or doesn't carry the
@@ -331,11 +473,11 @@ function looksLikeEmail(input) {
331
473
  * (when the user supplied one) keeps the wire payload self-describing for server
332
474
  * logs even though the response strips it.
333
475
  */
334
- function toMaafPermissionEntry(ref) {
476
+ function toMaafPermissionEntry(ref, role) {
335
477
  return {
336
478
  name: ref.displayName ?? ref.input,
337
479
  properties: {
338
- roleName: MaafAppReaderRoleName,
480
+ roleName: role,
339
481
  principal: ref.email ? { id: ref.id, email: ref.email } : { id: ref.id },
340
482
  },
341
483
  };