@knowttl/mg-axi 0.1.6 → 0.1.7
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.
- package/dist/api.js +5 -21
- package/dist/catalogue.js +10 -10
- package/dist/docs.js +7 -2
- package/dist/entra-audit-logs.js +5 -4
- package/dist/entra-conditional-access.js +4 -3
- package/dist/entra-directory-objects.js +4 -5
- package/dist/entra-domains.js +4 -2
- package/dist/entra-group-lifecycle.js +3 -2
- package/dist/entra-roles.js +6 -5
- package/dist/graph-session.js +15 -3
- package/docs/coverage.md +5 -2
- package/package.json +1 -1
- package/skills/mg-axi/SKILL.md +1 -0
package/dist/api.js
CHANGED
|
@@ -61,7 +61,7 @@ const AUTH_METHOD_FIELDS = ["id", "createdDateTime", "displayName", "phoneNumber
|
|
|
61
61
|
const REGISTRATION_FIELDS = ["id", "userPrincipalName", "userDisplayName", "userType", "isAdmin", "isMfaRegistered", "isMfaCapable", "isPasswordlessCapable", "isSsprRegistered", "isSsprEnabled", "isSsprCapable", "userPreferredMethodForSecondaryAuthentication", "lastUpdatedDateTime"];
|
|
62
62
|
const SIGNIN_FIELDS = ["id", "createdDateTime", "userId", "userPrincipalName", "userDisplayName", "appDisplayName", "appId", "ipAddress", "location", "status", "conditionalAccessStatus", "riskDetail", "riskLevelAggregated", "riskLevelDuringSignIn", "riskState", "resourceDisplayName", "resourceId", "clientAppUsed"];
|
|
63
63
|
const AUDIT_FIELDS = ["id", "activityDateTime", "activityDisplayName", "category", "loggedByService", "operationType", "result", "resultReason", "correlationId", "initiatedBy", "targetResources"];
|
|
64
|
-
const PROVISIONING_FIELDS = ["id", "activityDateTime", "tenantId", "jobId", "cycleId", "changeId", "
|
|
64
|
+
const PROVISIONING_FIELDS = ["id", "activityDateTime", "tenantId", "jobId", "cycleId", "changeId", "provisioningAction", "durationInMilliseconds", "sourceSystem", "sourceIdentity", "targetSystem", "targetIdentity", "provisioningStatusInfo", "provisioningSteps", "modifiedProperties", "servicePrincipal", "initiatedBy"];
|
|
65
65
|
const RISKY_USER_FIELDS = ["id", "userPrincipalName", "userDisplayName", "riskDetail", "riskLastUpdatedDateTime", "riskLevel", "riskState"];
|
|
66
66
|
const RISK_DETECTION_FIELDS = ["id", "detectedDateTime", "activityDateTime", "userId", "userPrincipalName", "userDisplayName", "ipAddress", "location", "riskDetail", "riskLevel", "riskState", "riskEventType", "detectionTimingType", "lastUpdatedDateTime", "source"];
|
|
67
67
|
const RISKY_SP_FIELDS = ["id", "displayName", "appId", "servicePrincipalType", "riskDetail", "riskLastUpdatedDateTime", "riskLevel", "riskState", "isEnabled", "isProcessing"];
|
|
@@ -117,7 +117,7 @@ export const REVIEWED_ROUTES = [
|
|
|
117
117
|
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
118
118
|
note: "Conditional Access needs P1.",
|
|
119
119
|
sources: ["https://learn.microsoft.com/en-us/graph/api/authenticationstrengthroot-list-policies?view=graph-rest-1.0"] },
|
|
120
|
-
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/policies/{authenticationStrengthPolicy-id}", kind: "single", query:
|
|
120
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/policies/{authenticationStrengthPolicy-id}", kind: "single", query: [], fields: KNOWN_STRENGTH_FIELDS,
|
|
121
121
|
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
122
122
|
note: "Conditional Access needs P1.",
|
|
123
123
|
sources: ["https://learn.microsoft.com/en-us/graph/api/authenticationstrengthpolicy-get?view=graph-rest-1.0"] },
|
|
@@ -145,7 +145,7 @@ export const REVIEWED_ROUTES = [
|
|
|
145
145
|
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (for example Security Reader) is also required.",
|
|
146
146
|
note: "Conditional Access needs P1.",
|
|
147
147
|
sources: ["https://learn.microsoft.com/en-us/graph/api/conditionalaccesstemplate-get?view=graph-rest-1.0"] },
|
|
148
|
-
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationContextClassReferences", kind: "collection", query:
|
|
148
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationContextClassReferences", kind: "collection", query: ["$filter", "$orderby", "$top"], fields: KNOWN_AUTH_CONTEXT_FIELDS,
|
|
149
149
|
access: "D/A AuthenticationContext.Read.All. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Global Reader, Global Secure Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
150
150
|
note: "Conditional Access needs P1.",
|
|
151
151
|
sources: ["https://learn.microsoft.com/graph/api/conditionalaccessroot-list-authenticationcontextclassreferences?view=graph-rest-1.0"] },
|
|
@@ -187,7 +187,7 @@ export const REVIEWED_ROUTES = [
|
|
|
187
187
|
{ id: "v1.0:GET:/auditLogs/directoryAudits", kind: "collection", query: COLLECTION_QUERY, fields: AUDIT_FIELDS,
|
|
188
188
|
access: "D/A AuditLog.Read.All. Delegated callers pass it as --scopes.",
|
|
189
189
|
sources: ["https://learn.microsoft.com/graph/api/directoryaudit-list?view=graph-rest-1.0"] },
|
|
190
|
-
{ id: "v1.0:GET:/auditLogs/provisioning", kind: "collection", query:
|
|
190
|
+
{ id: "v1.0:GET:/auditLogs/provisioning", kind: "collection", query: ["$filter", "$orderby", "$top"], fields: PROVISIONING_FIELDS,
|
|
191
191
|
access: "D/A AuditLog.Read.All and Directory.Read.All. Delegated callers pass both as --scopes; Reports Reader is the least privileged directory role.",
|
|
192
192
|
note: "Entra ID P1/P2 licence prerequisite; retention is 30 days on premium and 7 days on free.",
|
|
193
193
|
sources: ["https://learn.microsoft.com/graph/api/provisioningobjectsummary-list?view=graph-rest-1.0"] },
|
|
@@ -313,14 +313,6 @@ export const REVIEWED_ROUTES = [
|
|
|
313
313
|
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
314
314
|
note: "Administrative-unit scopes need P1.",
|
|
315
315
|
sources: ["https://learn.microsoft.com/graph/api/scopedrolemembership-get?view=graph-rest-1.0"] },
|
|
316
|
-
{ id: "v1.0:GET:/scopedRoleMemberships", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_SCOPED_MEMBER_FIELDS,
|
|
317
|
-
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
318
|
-
note: "Administrative-unit-scoped admin assignments; directory-wide assignments live on roleAssignments. Administrative-unit scopes need P1.",
|
|
319
|
-
sources: ["https://learn.microsoft.com/graph/api/scopedrolemembership-list?view=graph-rest-1.0"] },
|
|
320
|
-
{ id: "v1.0:GET:/scopedRoleMemberships/{scopedRoleMembership-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_SCOPED_MEMBER_FIELDS,
|
|
321
|
-
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
322
|
-
note: "Administrative-unit scopes need P1.",
|
|
323
|
-
sources: ["https://learn.microsoft.com/graph/api/scopedrolemembership-get?view=graph-rest-1.0"] },
|
|
324
316
|
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/assignmentSchedules", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ASSIGNMENT_SCHEDULE_FIELDS,
|
|
325
317
|
access: "D/A PrivilegedAssignmentSchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
326
318
|
note: "Assignment schedules govern group membership or ownership over time; PIM for Groups needs P2 or ID Governance; lists require $filter on groupId or principalId. AssignmentScheduleRequests stay out: their least privilege is the write scope PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup.",
|
|
@@ -415,10 +407,6 @@ export const REVIEWED_ROUTES = [
|
|
|
415
407
|
access: "D/A Domain.Read.All. Delegated callers pass it as --scopes; Domain Name Administrator or Global Reader are the least-privileged delegated roles. No P1/P2 prerequisite is stated for DNS record reads.",
|
|
416
408
|
note: "No operation-level documentation page; access follows the parent service-configuration contract and the domainDnsRecord resource reference.",
|
|
417
409
|
sources: ["https://learn.microsoft.com/en-us/graph/api/domain-list-serviceconfigurationrecords?view=graph-rest-1.0", "https://learn.microsoft.com/en-us/graph/api/resources/domaindnsrecord?view=graph-rest-1.0"] },
|
|
418
|
-
{ id: "v1.0:GET:/domainDnsRecords", kind: "collection", query: COLLECTION_QUERY, fields: DNS_RECORD_FIELDS,
|
|
419
|
-
access: "D/A Domain.Read.All. Delegated callers pass it as --scopes; Domain Name Administrator or Global Reader are the least-privileged delegated roles. No P1/P2 prerequisite is stated for DNS record reads.",
|
|
420
|
-
note: "No operation-level documentation page; access follows the documented domain/DNS-read contract and the domainDnsRecord resource reference.",
|
|
421
|
-
sources: ["https://learn.microsoft.com/en-us/graph/api/domain-list?view=graph-rest-1.0", "https://learn.microsoft.com/en-us/graph/api/resources/domaindnsrecord?view=graph-rest-1.0"] },
|
|
422
410
|
{ id: "v1.0:GET:/domainDnsRecords/{domainDnsRecord-id}", kind: "single", query: SINGLE_QUERY, fields: DNS_RECORD_FIELDS,
|
|
423
411
|
access: "D/A Domain.Read.All. Delegated callers pass it as --scopes; Domain Name Administrator or Global Reader are the least-privileged delegated roles. No P1/P2 prerequisite is stated for DNS record reads.",
|
|
424
412
|
note: "No operation-level documentation page; access follows the documented domain/DNS-read contract and the domainDnsRecord resource reference.",
|
|
@@ -489,10 +477,6 @@ export const REVIEWED_ROUTES = [
|
|
|
489
477
|
delegatedOnly: true,
|
|
490
478
|
note: "No single-acceptance operation page; access follows the parent acceptance-list contract and the agreementAcceptance resource reference. Acceptance records are personal data: default rows carry id, agreementId, state and recordedDateTime only.",
|
|
491
479
|
sources: ["https://learn.microsoft.com/en-us/graph/api/agreement-list-acceptances?view=graph-rest-1.0", "https://learn.microsoft.com/en-us/graph/api/resources/agreementacceptance?view=graph-rest-1.0"] },
|
|
492
|
-
{ id: "v1.0:GET:/directoryObjects", kind: "collection", query: ["$select"], fields: KNOWN_DIRECTORY_OBJECT_FIELDS, defaultFields: ["id"], keepODataType: true,
|
|
493
|
-
access: "D/A Directory.Read.All. Delegated callers pass it as --scopes; no delegated role prerequisite is stated for directory-object reads. Personal Microsoft accounts are not supported.",
|
|
494
|
-
note: "No List operation page exists; access follows the sibling directoryobject-get contract and the directoryObject resource reference. Graph documents no collection filter contract here, so only $select is reviewed. Rows are polymorphic: the @odata.type discriminator rides along automatically and subtype properties need the subtype's named reads, never raw $select of unreviewed fields.",
|
|
495
|
-
sources: ["https://learn.microsoft.com/en-us/graph/api/directoryobject-get?view=graph-rest-1.0", "https://learn.microsoft.com/en-us/graph/api/resources/directoryobject?view=graph-rest-1.0"] },
|
|
496
480
|
{ id: "v1.0:GET:/directoryObjects/{directoryObject-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_DIRECTORY_OBJECT_FIELDS, defaultFields: ["id", "deletedDateTime"], keepODataType: true,
|
|
497
481
|
access: "D/A Directory.Read.All. Delegated callers pass it as --scopes; no delegated role prerequisite is stated for this read. Personal Microsoft accounts are not supported.",
|
|
498
482
|
note: "Single reads return the base-type properties plus the @odata.type discriminator; subtype detail needs the subtype's named reads. Only base properties are projected, so subtype secrets or credentials can never appear.",
|
|
@@ -605,7 +589,7 @@ export const REVIEWED_ROUTES = [
|
|
|
605
589
|
access: "D/A OrgContact.Read.All and Group.Read.All together least-privileged (Directory.Read.All is the documented higher-privileged alternative). Delegated callers pass both as --scopes; delegated access additionally needs a supported Entra role (Directory Readers reads basic properties; Global Reader, Directory Writers, Intune Administrator or User Administrator also work). Personal Microsoft accounts are not supported.",
|
|
606
590
|
note: "No operation-level documentation page; OData cast selects the administrativeUnit subtype and access follows the parent transitiveMemberOf contract and the administrativeUnit resource reference.",
|
|
607
591
|
sources: ["https://learn.microsoft.com/en-us/graph/api/orgcontact-list-transitivememberof?view=graph-rest-1.0", "https://learn.microsoft.com/en-us/graph/api/resources/administrativeunit?view=graph-rest-1.0"] },
|
|
608
|
-
{ id: "v1.0:GET:/groupLifecyclePolicies", kind: "collection", query:
|
|
592
|
+
{ id: "v1.0:GET:/groupLifecyclePolicies", kind: "collection", query: ["$filter", "$orderby", "$top"], fields: KNOWN_LIFECYCLE_FIELDS,
|
|
609
593
|
access: "D/A Directory.Read.All. Delegated callers pass it as --scopes; no delegated role prerequisite is stated for lifecycle-policy reads. Personal Microsoft accounts are not supported.",
|
|
610
594
|
note: "Filtering uses plain $filter with no $count or ConsistencyLevel contract; no P1/P2 prerequisite is stated for lifecycle-policy reads.",
|
|
611
595
|
sources: ["https://learn.microsoft.com/graph/api/grouplifecyclepolicy-list?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/grouplifecyclepolicy?view=graph-rest-1.0"] },
|
package/dist/catalogue.js
CHANGED
|
@@ -677,7 +677,7 @@ export const LEAVES = [
|
|
|
677
677
|
cursor: roleRead.cursor,
|
|
678
678
|
scopes: { value: "comma-separated-Graph-scopes", description: "Delegated only: explicit Graph scopes using full https://graph.microsoft.com/ names; defaults to RoleManagement.Read.Directory; delegated callers also need a supported directory role" },
|
|
679
679
|
}, examples: ["mg-axi entra directory-role member list --role <role-id> --profile soc", "mg-axi entra directory-role member list --role <role-id> --profile soc --filter \"displayName eq 'Adele Vance'\""] },
|
|
680
|
-
{ path: "entra directory-role scoped-member list", description: "List the scoped members of one activated directory role (id,
|
|
680
|
+
{ path: "entra directory-role scoped-member list", description: "List the scoped members of one activated directory role (id, roleMemberInfo, roleId, administrativeUnitId); administrative-unit scopes need P1", operation: "GET:/directoryRoles/{directoryRole-id}/scopedMembers", flags: {
|
|
681
681
|
...common, role: { value: "role-id", required: true, description: "Activated directory-role object ID whose scoped members are listed" },
|
|
682
682
|
limit: { value: "positive-integer", default: "100", description: "Cap returned rows; the remainder is buffered into an opaque cursor, never discarded; incompatible with --all" },
|
|
683
683
|
all: { description: "Follow pages within request, byte and deadline budgets" },
|
|
@@ -687,7 +687,7 @@ export const LEAVES = [
|
|
|
687
687
|
full: roleRead.full,
|
|
688
688
|
cursor: roleRead.cursor,
|
|
689
689
|
scopes: { value: "comma-separated-Graph-scopes", description: "Delegated only: explicit Graph scopes using full https://graph.microsoft.com/ names; defaults to RoleManagement.Read.Directory; delegated callers also need a supported directory role; administrative-unit scopes need P1" },
|
|
690
|
-
}, examples: ["mg-axi entra directory-role scoped-member list --role <role-id> --profile soc", "mg-axi entra directory-role scoped-member list --role <role-id> --profile soc --filter \"
|
|
690
|
+
}, examples: ["mg-axi entra directory-role scoped-member list --role <role-id> --profile soc", "mg-axi entra directory-role scoped-member list --role <role-id> --profile soc --filter \"administrativeUnitId eq '<unit-id>'\""] },
|
|
691
691
|
{ path: "entra directory-role scoped-member show", description: "Show one scoped member of an activated directory role with richer default properties", operation: "GET:/directoryRoles/{directoryRole-id}/scopedMembers/{scopedRoleMembership-id}", flags: {
|
|
692
692
|
...common, role: { value: "role-id", required: true, description: "Activated directory-role object ID owning the scoped member" },
|
|
693
693
|
id: { value: "scoped-membership-id", required: true, description: "Scoped membership object ID" },
|
|
@@ -696,7 +696,7 @@ export const LEAVES = [
|
|
|
696
696
|
full: roleRead.full,
|
|
697
697
|
scopes: { value: "comma-separated-Graph-scopes", description: "Delegated only: explicit Graph scopes using full https://graph.microsoft.com/ names; defaults to RoleManagement.Read.Directory; delegated callers also need a supported directory role; administrative-unit scopes need P1" },
|
|
698
698
|
}, examples: ["mg-axi entra directory-role scoped-member show --role <role-id> --id <scoped-membership-id> --profile soc", "mg-axi entra directory-role scoped-member show --role <role-id> --id <scoped-membership-id> --profile soc --full"] },
|
|
699
|
-
{ path: "entra scoped-role-membership list", description: "
|
|
699
|
+
{ path: "entra scoped-role-membership list", description: "Unsupported by Graph v1.0; use directory-role scoped-member list --role <role-id>", operation: "GET:/scopedRoleMemberships", flags: {
|
|
700
700
|
...common,
|
|
701
701
|
limit: { value: "positive-integer", default: "100", description: "Cap returned rows; the remainder is buffered into an opaque cursor, never discarded; incompatible with --all" },
|
|
702
702
|
all: { description: "Follow pages within request, byte and deadline budgets" },
|
|
@@ -707,7 +707,7 @@ export const LEAVES = [
|
|
|
707
707
|
cursor: roleRead.cursor,
|
|
708
708
|
scopes: { value: "comma-separated-Graph-scopes", description: "Delegated only: explicit Graph scopes using full https://graph.microsoft.com/ names; defaults to RoleManagement.Read.Directory; delegated callers also need a supported directory role; administrative-unit scopes need P1" },
|
|
709
709
|
}, examples: ["mg-axi entra scoped-role-membership list --profile soc", "mg-axi entra scoped-role-membership list --profile soc --filter \"roleId eq '<role-id>'\""] },
|
|
710
|
-
{ path: "entra scoped-role-membership show", description: "
|
|
710
|
+
{ path: "entra scoped-role-membership show", description: "Unsupported by Graph v1.0; use directory-role scoped-member show --role <role-id> --id <scoped-membership-id>", operation: "GET:/scopedRoleMemberships/{scopedRoleMembership-id}", flags: {
|
|
711
711
|
...common, id: { value: "scoped-membership-id", required: true, description: "Scoped membership object ID" },
|
|
712
712
|
select: roleRead.select,
|
|
713
713
|
fields: roleRead.fields,
|
|
@@ -981,7 +981,7 @@ export const LEAVES = [
|
|
|
981
981
|
full: dnsRead.full,
|
|
982
982
|
scopes: dnsRead.scopes,
|
|
983
983
|
}, examples: ["mg-axi entra domain service-configuration-record show --domain contoso.com --id <record-id> --profile soc"] },
|
|
984
|
-
{ path: "entra domain-dns-record list", description: "
|
|
984
|
+
{ path: "entra domain-dns-record list", description: "Unsupported by Graph v1.0; use domain verification-dns-record list or domain service-configuration-record list with --domain <domain-id>", operation: "GET:/domainDnsRecords", flags: {
|
|
985
985
|
...common,
|
|
986
986
|
limit: { value: "positive-integer", default: "100", description: "Cap returned rows; the remainder is buffered into an opaque cursor, never discarded; incompatible with --all" },
|
|
987
987
|
all: { description: "Follow pages within request, byte and deadline budgets" },
|
|
@@ -1145,7 +1145,7 @@ export const LEAVES = [
|
|
|
1145
1145
|
full: acceptanceRead.full,
|
|
1146
1146
|
scopes: acceptanceRead.scopes,
|
|
1147
1147
|
}, examples: ["mg-axi entra agreement-acceptance show --id <acceptance-id> --profile soc"] },
|
|
1148
|
-
{ path: "entra directory-object list", description: "
|
|
1148
|
+
{ path: "entra directory-object list", description: "Unsupported by Graph v1.0; use directory-object show --id <object-id> or a named user, group, device, application or service-principal list", operation: "GET:/directoryObjects", flags: {
|
|
1149
1149
|
...common,
|
|
1150
1150
|
limit: { value: "positive-integer", default: "100", description: "Cap returned rows; the remainder is buffered into an opaque cursor, never discarded; incompatible with --all" },
|
|
1151
1151
|
all: { description: "Follow pages within request, byte and deadline budgets" },
|
|
@@ -1254,7 +1254,7 @@ export const LEAVES = [
|
|
|
1254
1254
|
limit: { value: "positive-integer", default: "100", description: "Cap returned rows; the remainder is buffered into an opaque cursor, never discarded; incompatible with --all" },
|
|
1255
1255
|
all: { description: "Follow pages within request, byte and deadline budgets" },
|
|
1256
1256
|
filter: lifecycleRead.filter,
|
|
1257
|
-
select:
|
|
1257
|
+
select: { value: "comma-separated-properties", description: "Select output properties locally; no $select is sent to Graph" },
|
|
1258
1258
|
fields: lifecycleRead.fields,
|
|
1259
1259
|
full: lifecycleRead.full,
|
|
1260
1260
|
cursor: lifecycleRead.cursor,
|
|
@@ -1599,7 +1599,7 @@ export const LEAVES = [
|
|
|
1599
1599
|
since: { ...logRead.since, description: "Required for a new query (resume with --cursor instead): earliest activityDateTime bounding the server time range" },
|
|
1600
1600
|
until: logRead.until,
|
|
1601
1601
|
filter: logRead.filter,
|
|
1602
|
-
select: { value: "comma-separated-properties", description: "
|
|
1602
|
+
select: { value: "comma-separated-properties", description: "Select output properties locally from the provisioning-log set, including provisioningAction; no $select is sent to Graph" },
|
|
1603
1603
|
fields: logRead.fields,
|
|
1604
1604
|
full: logRead.full,
|
|
1605
1605
|
cursor: logRead.cursor,
|
|
@@ -1921,7 +1921,7 @@ export const LEAVES = [
|
|
|
1921
1921
|
}, examples: ["mg-axi entra conditional-access auth-strength-policy list --profile soc", "mg-axi entra conditional-access auth-strength-policy list --profile soc --limit 10", "mg-axi entra conditional-access auth-strength-policy list --profile soc --filter \"policyType eq 'builtIn'\" --select id,displayName,policyType"] },
|
|
1922
1922
|
{ path: "entra conditional-access auth-strength-policy show", description: "Show one authentication-strength policy with the full reviewed property set", operation: "GET:/identity/conditionalAccess/authenticationStrength/policies/{authenticationStrengthPolicy-id}", flags: {
|
|
1923
1923
|
...common, id: { value: "auth-strength-policy-id", required: true, description: "Authentication-strength policy object ID" },
|
|
1924
|
-
select:
|
|
1924
|
+
select: { value: "comma-separated-properties", description: "Select output properties locally; no $select is sent to Graph" },
|
|
1925
1925
|
fields: caStrengthRead.fields,
|
|
1926
1926
|
full: caStrengthRead.full,
|
|
1927
1927
|
scopes: caStrengthRead.scopes,
|
|
@@ -1987,7 +1987,7 @@ export const LEAVES = [
|
|
|
1987
1987
|
limit: { value: "positive-integer", default: "100", description: "Cap returned rows; the remainder is buffered into an opaque cursor, never discarded; incompatible with --all" },
|
|
1988
1988
|
all: { description: "Follow pages within request, byte and deadline budgets" },
|
|
1989
1989
|
filter: caAuthContextRead.filter,
|
|
1990
|
-
select:
|
|
1990
|
+
select: { value: "comma-separated-properties", description: "Select output properties locally; no $select is sent to Graph" },
|
|
1991
1991
|
fields: caAuthContextRead.fields,
|
|
1992
1992
|
full: caAuthContextRead.full,
|
|
1993
1993
|
cursor: caAuthContextRead.cursor,
|
package/dist/docs.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { DESCRIPTION, HOME_HELP, LEAVES } from "./catalogue.js";
|
|
3
|
+
const UNSUPPORTED_READ_NOTE = "Graph v1.0 does not support the legacy `entra scoped-role-membership list/show`, `entra domain-dns-record list` or `entra directory-object list` routes; those commands fail locally with supported alternatives and their root routes are not available through `api get`.";
|
|
3
4
|
// PACK-01: single source for generated release records. The committed
|
|
4
5
|
// skills/mg-axi/SKILL.md and docs/coverage.md are generated from the templates
|
|
5
6
|
// below, the executable catalogue and the discovery inventory, so help, skill
|
|
@@ -174,6 +175,7 @@ export function skillDocument() {
|
|
|
174
175
|
"Its effect is `read` for Graph read leaves and the doctor health check, `write` for the gated named writes, or `local` for home, profile, auth, config path, login-alias and setup views.",
|
|
175
176
|
"Doctor acquires credentials silently and contacts Graph; only its help view stays offline.",
|
|
176
177
|
"The list below records current executable leaves; it makes no coverage claim for other Graph operations.",
|
|
178
|
+
UNSUPPORTED_READ_NOTE,
|
|
177
179
|
"See `docs/coverage.md` for the per-operation disposition records.",
|
|
178
180
|
"`docs/coverage.md` and this file are generated from the same catalogue and inventory sources; `node tools/generate-docs.mjs --check` fails when they are stale.",
|
|
179
181
|
"",
|
|
@@ -419,9 +421,12 @@ export function capabilityDocument() {
|
|
|
419
421
|
"| `mg-axi api get` | reviewed raw reads (see src/api.ts) | reviewed-raw-read catalogue | API-01 |",
|
|
420
422
|
"| `mg-axi doctor` | bounded `GET:/users` health check | uses the named user-list read | PACK-01 |",
|
|
421
423
|
"",
|
|
424
|
+
UNSUPPORTED_READ_NOTE,
|
|
425
|
+
"",
|
|
422
426
|
"## EXT-01 domain scope decisions",
|
|
423
427
|
"",
|
|
424
428
|
"Firstmate decision R1: approve narrowing this change to the eight v1.0 domain reads above.",
|
|
429
|
+
"The root domain-dns-record list is now explicitly unsupported; use verification-dns-record or service-configuration-record list with a parent domain.",
|
|
425
430
|
"The v1.0 operations below carry the deferred disposition (out of v1) and the beta operations remain scheduled (never agreed for v1); no new commands or raw access are approved.",
|
|
426
431
|
"Federation stays out because it can carry signing-certificate material.",
|
|
427
432
|
"Firstmate decision R2: keep the write-family status section as the coverage fix added to scope (resolved-kept).",
|
|
@@ -560,10 +565,10 @@ export function capabilityDocument() {
|
|
|
560
565
|
"",
|
|
561
566
|
"## EXT-01 directory-objects scope decisions",
|
|
562
567
|
"",
|
|
563
|
-
"
|
|
568
|
+
"Directory-object show and count are available. Graph v1.0 rejects directory-object list; the legacy command fails locally and points to show or a typed list command.",
|
|
564
569
|
"The v1.0 operations below carry the deferred disposition (out of v1) and the beta operations remain scheduled (never agreed for v1); no new commands or raw access are approved.",
|
|
565
570
|
"Directory-object reads support v1.0 only; beta needs its own review.",
|
|
566
|
-
"Delta-token sync needs its own change-tracking contract beyond the approved
|
|
571
|
+
"Delta-token sync needs its own change-tracking contract beyond the approved show/count reads; the POST lookup and validation actions need their own request and projection review.",
|
|
567
572
|
"Rows are polymorphic: only the base-type properties plus the @odata.type discriminator are projected, so subtype secrets or credentials can never appear.",
|
|
568
573
|
"",
|
|
569
574
|
"| Inventory operation | Disposition | Owning slice | Deferral reason |",
|
package/dist/entra-audit-logs.js
CHANGED
|
@@ -72,7 +72,7 @@ export const KNOWN_PROVISIONING_FIELDS = [
|
|
|
72
72
|
"jobId",
|
|
73
73
|
"cycleId",
|
|
74
74
|
"changeId",
|
|
75
|
-
"
|
|
75
|
+
"provisioningAction",
|
|
76
76
|
"durationInMilliseconds",
|
|
77
77
|
"sourceSystem",
|
|
78
78
|
"sourceIdentity",
|
|
@@ -88,7 +88,7 @@ const PROVISIONING_KNOWN = new Set(KNOWN_PROVISIONING_FIELDS);
|
|
|
88
88
|
// Compact list rows: identifier, time, who/what happened, and outcome.
|
|
89
89
|
const DEFAULT_SIGNIN_LIST_SELECT = ["id", "createdDateTime", "userPrincipalName", "appDisplayName"];
|
|
90
90
|
const DEFAULT_AUDIT_LIST_SELECT = ["id", "activityDateTime", "activityDisplayName", "result"];
|
|
91
|
-
const DEFAULT_PROVISIONING_LIST_SELECT = ["id", "activityDateTime", "
|
|
91
|
+
const DEFAULT_PROVISIONING_LIST_SELECT = ["id", "activityDateTime", "provisioningAction", "provisioningStatusInfo"];
|
|
92
92
|
// Show rows: the full reviewed server set for one object.
|
|
93
93
|
const DEFAULT_SIGNIN_SHOW_SELECT = [...KNOWN_SIGNIN_FIELDS];
|
|
94
94
|
const DEFAULT_AUDIT_SHOW_SELECT = [...KNOWN_AUDIT_FIELDS];
|
|
@@ -344,7 +344,8 @@ async function listLogs(shape, session, flags, profile, operation, help, profile
|
|
|
344
344
|
const scopes = scopesFor(flags, profile, help, shape.defaultScopes);
|
|
345
345
|
const full = flags.full === true;
|
|
346
346
|
const filter = boundedFilter(shape.dateField, flags, help);
|
|
347
|
-
|
|
347
|
+
// Provisioning lists reject $select; selection remains a local projection.
|
|
348
|
+
const query = shape.noun === "provisioning" ? {} : { $select: select.join(",") };
|
|
348
349
|
const explicitFilter = filter !== undefined;
|
|
349
350
|
if (explicitFilter)
|
|
350
351
|
query.$filter = filter;
|
|
@@ -362,7 +363,7 @@ async function listLogs(shape, session, flags, profile, operation, help, profile
|
|
|
362
363
|
// The hint replays the caller's own time flags (or the cursor alone, which
|
|
363
364
|
// restores the saved query); copying back the composed $filter would wrap
|
|
364
365
|
// it a second time and conflict with the cursor context.
|
|
365
|
-
const effectiveFlags = { ...flags, select: result.query.$select ??
|
|
366
|
+
const effectiveFlags = { ...flags, select: result.query.$select ?? select.join(",") };
|
|
366
367
|
const rows = [];
|
|
367
368
|
let truncated = false;
|
|
368
369
|
for (const row of result.value) {
|
|
@@ -376,7 +376,8 @@ async function listCollection(shape, session, flags, profile, operation, help, p
|
|
|
376
376
|
const { select, fields } = selectedFields(flags, savedSelect === undefined ? shape.defaultSelect : fieldList(savedSelect, "select", shape.known, shape.knownList, shape.noun, help), shape.known, shape.knownList, shape.noun, help);
|
|
377
377
|
const scopes = scopesFor(flags, profile, help, shape.defaultScopes);
|
|
378
378
|
const full = flags.full === true;
|
|
379
|
-
|
|
379
|
+
// Authentication contexts reject $select; selection remains a local projection.
|
|
380
|
+
const query = shape.noun === "auth-context" ? {} : { $select: select.join(",") };
|
|
380
381
|
if (flags.filter !== undefined)
|
|
381
382
|
query.$filter = String(flags.filter);
|
|
382
383
|
const args = { profile, operation, query, scopes };
|
|
@@ -397,7 +398,7 @@ async function listCollection(shape, session, flags, profile, operation, help, p
|
|
|
397
398
|
args.limit = flags.limit === undefined ? 100 : Number(flags.limit);
|
|
398
399
|
}
|
|
399
400
|
const result = await withGuidance(shape.denialHints, () => session.collect(args));
|
|
400
|
-
const effectiveFlags = { ...flags, select: result.query.$select ??
|
|
401
|
+
const effectiveFlags = { ...flags, select: result.query.$select ?? select.join(",") };
|
|
401
402
|
if (result.query.$filter !== undefined)
|
|
402
403
|
effectiveFlags.filter = result.query.$filter;
|
|
403
404
|
const rows = [];
|
|
@@ -474,7 +475,7 @@ async function showSingle(shape, session, flags, profile, operation, help, profi
|
|
|
474
475
|
profile,
|
|
475
476
|
operation,
|
|
476
477
|
params,
|
|
477
|
-
query: { $select: select.join(",") },
|
|
478
|
+
query: shape.noun === "auth-strength-policy" ? {} : { $select: select.join(",") },
|
|
478
479
|
scopes,
|
|
479
480
|
}));
|
|
480
481
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AxiError } from "axi-sdk-js";
|
|
2
2
|
import { listTotals } from "./list-totals.js";
|
|
3
3
|
// EXT-01 directory-objects subfamily: the read mapping behind
|
|
4
|
-
// `mg-axi entra directory-object
|
|
4
|
+
// `mg-axi entra directory-object show/count`. Operation construction
|
|
5
5
|
// stays beside its command; the shared session owns URLs, credentials,
|
|
6
6
|
// paging, retries and error translation, and the SDK owns TOON rendering.
|
|
7
7
|
// This module only maps flags to session calls and projects rows for compact
|
|
@@ -10,10 +10,9 @@ import { listTotals } from "./list-totals.js";
|
|
|
10
10
|
// Reviewed against the v1.0 directoryobject-get operation documentation and
|
|
11
11
|
// the directoryObject resource reference on 2026-10-05. There is no dedicated
|
|
12
12
|
// List operation page: the resource Methods table documents Get, delta,
|
|
13
|
-
// Delete and the lookup/validation functions only
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// support is unreviewed. Both reads take delegated or application
|
|
13
|
+
// Delete and the lookup/validation functions only. Graph rejects the root
|
|
14
|
+
// collection GET, so the session refuses the legacy list command with
|
|
15
|
+
// supported alternatives. Detail and count reads take delegated or application
|
|
17
16
|
// Directory.Read.All, the documented least privilege in each mode; personal
|
|
18
17
|
// Microsoft accounts are not supported. No delegated role and no P1/P2
|
|
19
18
|
// prerequisite are stated for these reads. The $count scalar carries no
|
package/dist/entra-domains.js
CHANGED
|
@@ -2,7 +2,7 @@ import { AxiError } from "axi-sdk-js";
|
|
|
2
2
|
import { listTotals } from "./list-totals.js";
|
|
3
3
|
// EXT-01 domains subfamily: the read mapping behind `mg-axi entra domain
|
|
4
4
|
// list/show`, the per-domain verification and service-configuration DNS
|
|
5
|
-
// record reads, and the top-level domain DNS record
|
|
5
|
+
// record reads, and the top-level domain DNS record show. Operation
|
|
6
6
|
// construction stays beside its command; the shared session owns URLs,
|
|
7
7
|
// credentials, paging, retries and error translation, and the SDK owns TOON
|
|
8
8
|
// rendering. This module only maps flags to session calls and projects rows
|
|
@@ -17,7 +17,7 @@ import { listTotals } from "./list-totals.js";
|
|
|
17
17
|
// domain list/get support those plus Directory Readers and other directory
|
|
18
18
|
// roles). Personal Microsoft accounts are not supported. No P1/P2
|
|
19
19
|
// prerequisite is stated for these reads. The single-record GETs and the
|
|
20
|
-
// top-level /domainDnsRecords
|
|
20
|
+
// top-level /domainDnsRecords/{id} GET carries no operation-level documentation
|
|
21
21
|
// page; they read the same domainDnsRecord resource through the same
|
|
22
22
|
// permission contract, so the review cites the parent list documentation
|
|
23
23
|
// alongside the domainDnsRecord resource reference. Domain ids are fully
|
|
@@ -28,6 +28,8 @@ import { listTotals } from "./list-totals.js";
|
|
|
28
28
|
// no $count or ConsistencyLevel contract. No domain mutation exists in this
|
|
29
29
|
// slice: verify, forceDelete, promote, federation and shared-email surfaces
|
|
30
30
|
// belong to later pieces.
|
|
31
|
+
// Graph rejects the root /domainDnsRecords collection. The session refuses
|
|
32
|
+
// its legacy list command and points to the parent-domain DNS collections.
|
|
31
33
|
// Every domain property this slice may request or display, matching the
|
|
32
34
|
// reviewed raw surface. Anything else fails before credentials.
|
|
33
35
|
export const KNOWN_DOMAIN_FIELDS = [
|
|
@@ -186,7 +186,8 @@ function collectionCommon(session, flags, known, knownList, defaults, defaultSco
|
|
|
186
186
|
return { cursor, select, fields, scopes: scopesFor(flags, defaultScopes, profile, help), full: flags.full === true, filter };
|
|
187
187
|
}
|
|
188
188
|
function collectArgs(profile, operation, common, flags, help) {
|
|
189
|
-
|
|
189
|
+
// Lifecycle-policy lists reject $select; keep the selected output fields local.
|
|
190
|
+
const query = operation.path === "/groupLifecyclePolicies" ? {} : { $select: common.select.join(",") };
|
|
190
191
|
if (common.filter !== undefined)
|
|
191
192
|
query.$filter = common.filter;
|
|
192
193
|
const args = { profile, operation, query, scopes: common.scopes };
|
|
@@ -227,7 +228,7 @@ function singleResult(raw, fields, full, kind) {
|
|
|
227
228
|
export async function listLifecyclePolicies(session, flags, profile, operation, help, profileName) {
|
|
228
229
|
const common = collectionCommon(session, flags, KNOWN_LIFECYCLE, KNOWN_LIFECYCLE_FIELDS, DEFAULT_LIFECYCLE_LIST_SELECT, DEFAULT_LIFECYCLE_SCOPES, operation, help, profile, true);
|
|
229
230
|
const result = await withGuidance(LIFECYCLE_DENIAL_HINTS, () => session.collect(collectArgs(profile, operation, common, flags, help)));
|
|
230
|
-
const effectiveFlags = { ...flags, select: result.query.$select ??
|
|
231
|
+
const effectiveFlags = { ...flags, select: result.query.$select ?? common.select.join(",") };
|
|
231
232
|
if (result.query.$filter !== undefined)
|
|
232
233
|
effectiveFlags.filter = result.query.$filter;
|
|
233
234
|
const policies = [];
|
package/dist/entra-roles.js
CHANGED
|
@@ -3,8 +3,8 @@ import { listTotals } from "./list-totals.js";
|
|
|
3
3
|
// READ-09: the Entra directory-role and PIM read mapping behind
|
|
4
4
|
// `mg-axi entra directory-role list/show`, `mg-axi entra directory-role-template
|
|
5
5
|
// list/show`, `mg-axi entra directory-role member list`, `mg-axi entra
|
|
6
|
-
// directory-role scoped-member list/show`, `mg-axi entra
|
|
7
|
-
// list
|
|
6
|
+
// directory-role scoped-member list/show`, `mg-axi entra role-assignment
|
|
7
|
+
// list`, `mg-axi entra pim eligible
|
|
8
8
|
// list` and `mg-axi entra pim active list`.
|
|
9
9
|
// Operation construction stays beside its command; the shared session owns
|
|
10
10
|
// URLs, credentials, paging, retries and error translation, and the SDK owns
|
|
@@ -44,6 +44,8 @@ import { listTotals } from "./list-totals.js";
|
|
|
44
44
|
// every other PIM mutation belongs to later write slices, never to these
|
|
45
45
|
// reads. Built-in roles are base inventory; custom role assignments need P1;
|
|
46
46
|
// PIM reads need P2 or ID Governance.
|
|
47
|
+
// Direct /scopedRoleMemberships queries are unsupported by Graph v1.0;
|
|
48
|
+
// the session refuses the legacy commands with parent-role alternatives.
|
|
47
49
|
// Eligible and active instances need separate reviewed property sets:
|
|
48
50
|
// only active instances expose assignmentType.
|
|
49
51
|
export const KNOWN_ROLE_FIELDS = [
|
|
@@ -84,9 +86,8 @@ export const KNOWN_ROLE_MEMBER_FIELDS = [
|
|
|
84
86
|
];
|
|
85
87
|
export const KNOWN_SCOPED_MEMBER_FIELDS = [
|
|
86
88
|
"id",
|
|
87
|
-
"
|
|
89
|
+
"roleMemberInfo",
|
|
88
90
|
"roleId",
|
|
89
|
-
"directoryScopeId",
|
|
90
91
|
"administrativeUnitId",
|
|
91
92
|
];
|
|
92
93
|
const ROLE_KNOWN = new Set(KNOWN_ROLE_FIELDS);
|
|
@@ -106,7 +107,7 @@ const DEFAULT_ACTIVE_SELECT = ["id", "principalId", "roleDefinitionId", "assignm
|
|
|
106
107
|
const DEFAULT_TEMPLATE_LIST_SELECT = ["id", "displayName", "description"];
|
|
107
108
|
const DEFAULT_TEMPLATE_SHOW_SELECT = [...KNOWN_TEMPLATE_FIELDS];
|
|
108
109
|
const DEFAULT_MEMBER_SELECT = ["id", "displayName"];
|
|
109
|
-
const DEFAULT_SCOPED_LIST_SELECT = ["id", "
|
|
110
|
+
const DEFAULT_SCOPED_LIST_SELECT = ["id", "roleMemberInfo", "roleId", "administrativeUnitId"];
|
|
110
111
|
const DEFAULT_SCOPED_SHOW_SELECT = [...KNOWN_SCOPED_MEMBER_FIELDS];
|
|
111
112
|
export const DEFAULT_ROLE_SCOPES = ["https://graph.microsoft.com/RoleManagement.Read.Directory"];
|
|
112
113
|
export const DEFAULT_ELIGIBLE_SCOPES = ["https://graph.microsoft.com/RoleEligibilitySchedule.Read.Directory"];
|
package/dist/graph-session.js
CHANGED
|
@@ -228,6 +228,15 @@ function checkOperation(operation) {
|
|
|
228
228
|
"Resolve the operation from inventory/operations.json before executing it",
|
|
229
229
|
]);
|
|
230
230
|
}
|
|
231
|
+
const unsupported = {
|
|
232
|
+
"/domainDnsRecords": ["mg-axi entra domain verification-dns-record list --domain <domain-id>", "mg-axi entra domain service-configuration-record list --domain <domain-id>"],
|
|
233
|
+
"/directoryObjects": ["mg-axi entra directory-object show --id <object-id>", "Use the named user, group, device, application or service-principal list command"],
|
|
234
|
+
"/scopedRoleMemberships": ["mg-axi entra directory-role scoped-member list --role <role-id>"],
|
|
235
|
+
"/scopedRoleMemberships/{scopedRoleMembership-id}": ["mg-axi entra directory-role scoped-member show --role <role-id> --id <scoped-membership-id>"],
|
|
236
|
+
};
|
|
237
|
+
const alternatives = unsupported[operation.path];
|
|
238
|
+
if (alternatives)
|
|
239
|
+
throw new AxiError(`GET ${operation.path} is not supported by Microsoft Graph v1.0`, "VALIDATION_ERROR", alternatives);
|
|
231
240
|
}
|
|
232
241
|
const UNSAFE_PARAM = /[%/?\\{}()]/;
|
|
233
242
|
const CONTROL = /[\s\x00-\x1f\x7f]/;
|
|
@@ -446,10 +455,10 @@ function faultBody(body) {
|
|
|
446
455
|
try {
|
|
447
456
|
const parsed = redact(JSON.parse(body));
|
|
448
457
|
const code = typeof parsed?.error?.code === "string" ? parsed.error.code : null;
|
|
449
|
-
if (!code)
|
|
450
|
-
return "";
|
|
451
458
|
const message = typeof parsed?.error?.message === "string" ? parsed.error.message.slice(0, 300) : "";
|
|
452
|
-
|
|
459
|
+
if (!code && !message)
|
|
460
|
+
return "";
|
|
461
|
+
return `: graph${code ? ` ${code}` : ""}${message ? ` ${message}` : ""}`;
|
|
453
462
|
}
|
|
454
463
|
catch {
|
|
455
464
|
return "";
|
|
@@ -625,6 +634,7 @@ export class GraphSession {
|
|
|
625
634
|
this.files = files;
|
|
626
635
|
}
|
|
627
636
|
cursorQuery(operation, cursor) {
|
|
637
|
+
checkOperation(operation);
|
|
628
638
|
return decodeCursor(operation, cursor).query;
|
|
629
639
|
}
|
|
630
640
|
async execute(args) {
|
|
@@ -757,6 +767,7 @@ export class GraphSession {
|
|
|
757
767
|
const headersFor = () => ({
|
|
758
768
|
Authorization: `Bearer ${token}`,
|
|
759
769
|
Accept: "application/json",
|
|
770
|
+
"Accept-Language": "en-US",
|
|
760
771
|
"client-request-id": randomUUID(),
|
|
761
772
|
...(consistencyLevel === "eventual" ? { ConsistencyLevel: "eventual" } : {}),
|
|
762
773
|
});
|
|
@@ -942,6 +953,7 @@ export class GraphSession {
|
|
|
942
953
|
const headersFor = () => ({
|
|
943
954
|
Authorization: `Bearer ${token}`,
|
|
944
955
|
Accept: "application/json",
|
|
956
|
+
"Accept-Language": "en-US",
|
|
945
957
|
"client-request-id": randomUUID(),
|
|
946
958
|
...(opts.consistencyLevel === "eventual" ? { ConsistencyLevel: "eventual" } : {}),
|
|
947
959
|
// The branding GET documents Accept-Language as required; 0 selects
|
package/docs/coverage.md
CHANGED
|
@@ -316,9 +316,12 @@ The declined EXT-02c access-review history reads (ReadWrite least privilege, SAS
|
|
|
316
316
|
| `mg-axi api get` | reviewed raw reads (see src/api.ts) | reviewed-raw-read catalogue | API-01 |
|
|
317
317
|
| `mg-axi doctor` | bounded `GET:/users` health check | uses the named user-list read | PACK-01 |
|
|
318
318
|
|
|
319
|
+
Graph v1.0 does not support the legacy `entra scoped-role-membership list/show`, `entra domain-dns-record list` or `entra directory-object list` routes; those commands fail locally with supported alternatives and their root routes are not available through `api get`.
|
|
320
|
+
|
|
319
321
|
## EXT-01 domain scope decisions
|
|
320
322
|
|
|
321
323
|
Firstmate decision R1: approve narrowing this change to the eight v1.0 domain reads above.
|
|
324
|
+
The root domain-dns-record list is now explicitly unsupported; use verification-dns-record or service-configuration-record list with a parent domain.
|
|
322
325
|
The v1.0 operations below carry the deferred disposition (out of v1) and the beta operations remain scheduled (never agreed for v1); no new commands or raw access are approved.
|
|
323
326
|
Federation stays out because it can carry signing-certificate material.
|
|
324
327
|
Firstmate decision R2: keep the write-family status section as the coverage fix added to scope (resolved-kept).
|
|
@@ -644,10 +647,10 @@ Scalar counts need a separate query and response contract from the approved list
|
|
|
644
647
|
|
|
645
648
|
## EXT-01 directory-objects scope decisions
|
|
646
649
|
|
|
647
|
-
|
|
650
|
+
Directory-object show and count are available. Graph v1.0 rejects directory-object list; the legacy command fails locally and points to show or a typed list command.
|
|
648
651
|
The v1.0 operations below carry the deferred disposition (out of v1) and the beta operations remain scheduled (never agreed for v1); no new commands or raw access are approved.
|
|
649
652
|
Directory-object reads support v1.0 only; beta needs its own review.
|
|
650
|
-
Delta-token sync needs its own change-tracking contract beyond the approved
|
|
653
|
+
Delta-token sync needs its own change-tracking contract beyond the approved show/count reads; the POST lookup and validation actions need their own request and projection review.
|
|
651
654
|
Rows are polymorphic: only the base-type properties plus the @odata.type discriminator are projected, so subtype secrets or credentials can never appear.
|
|
652
655
|
|
|
653
656
|
| Inventory operation | Disposition | Owning slice | Deferral reason |
|
package/package.json
CHANGED
package/skills/mg-axi/SKILL.md
CHANGED
|
@@ -26,6 +26,7 @@ Its capability label is `native` (implemented by an mg-axi handler).
|
|
|
26
26
|
Its effect is `read` for Graph read leaves and the doctor health check, `write` for the gated named writes, or `local` for home, profile, auth, config path, login-alias and setup views.
|
|
27
27
|
Doctor acquires credentials silently and contacts Graph; only its help view stays offline.
|
|
28
28
|
The list below records current executable leaves; it makes no coverage claim for other Graph operations.
|
|
29
|
+
Graph v1.0 does not support the legacy `entra scoped-role-membership list/show`, `entra domain-dns-record list` or `entra directory-object list` routes; those commands fail locally with supported alternatives and their root routes are not available through `api get`.
|
|
29
30
|
See `docs/coverage.md` for the per-operation disposition records.
|
|
30
31
|
`docs/coverage.md` and this file are generated from the same catalogue and inventory sources; `node tools/generate-docs.mjs --check` fails when they are stale.
|
|
31
32
|
|