@powerportalspro/core 6.0.0 → 7.0.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.
package/dist/index.d.cts CHANGED
@@ -199,6 +199,12 @@ declare const Routes: {
199
199
  readonly externalLoginRememberChoice: "/api/auth/external-login/remember-choice";
200
200
  /** POST — swap the current cookie for the user's alt identity (the contact↔systemuser sibling). */
201
201
  readonly switchIdentity: "/api/auth/switch-identity";
202
+ /** POST — start impersonating a portal contact. Internal users holding the SystemAdmin role only. */
203
+ readonly impersonate: "/api/auth/impersonate";
204
+ /** POST — end an impersonation session. Takes no body; the user to return to comes from the session's claims. */
205
+ readonly stopImpersonation: "/api/auth/stop-impersonation";
206
+ /** POST — search portal contacts for the impersonation picker. */
207
+ readonly impersonateSearch: "/api/auth/impersonate/search";
202
208
  /** GET — snapshot of the current user (or anonymous shape). */
203
209
  readonly me: "/api/auth/me";
204
210
  /** Account-management endpoints under `/api/auth/manage/*`. */
@@ -1508,6 +1514,139 @@ interface paths {
1508
1514
  patch?: never;
1509
1515
  trace?: never;
1510
1516
  };
1517
+ "/api/auth/impersonate": {
1518
+ parameters: {
1519
+ query?: never;
1520
+ header?: never;
1521
+ path?: never;
1522
+ cookie?: never;
1523
+ };
1524
+ get?: never;
1525
+ put?: never;
1526
+ /**
1527
+ * Starts impersonating the contact named in the request. Requires an authenticated internal
1528
+ * user holding string AuthEndpoints.ImpersonationRole; see ImpersonateResult? AuthEndpoints.AuthorizeImpersonator(ClaimsPrincipal? principal) for
1529
+ * why the role alone isn't enough.
1530
+ * @description Typed to PortalUser rather than a generic `TUser`, unlike the rest of
1531
+ * the auth surface. The whole point of this endpoint is the distinction between a contact
1532
+ * and a systemuser, which a generic user type has no notion of — the safety of the feature
1533
+ * rests on resolving the target through the contact store and the caller through the
1534
+ * systemuser store, so the concrete type is load-bearing rather than incidental.
1535
+ */
1536
+ post: {
1537
+ parameters: {
1538
+ query?: never;
1539
+ header?: never;
1540
+ path?: never;
1541
+ cookie?: never;
1542
+ };
1543
+ requestBody: {
1544
+ content: {
1545
+ "application/json": components["schemas"]["ImpersonateRequest"];
1546
+ "application/x-www-form-urlencoded": components["schemas"]["ImpersonateRequest"];
1547
+ };
1548
+ };
1549
+ responses: {
1550
+ /** @description OK */
1551
+ 200: {
1552
+ headers: {
1553
+ [name: string]: unknown;
1554
+ };
1555
+ content: {
1556
+ "application/json": components["schemas"]["ImpersonateResponse"];
1557
+ };
1558
+ };
1559
+ };
1560
+ };
1561
+ delete?: never;
1562
+ options?: never;
1563
+ head?: never;
1564
+ patch?: never;
1565
+ trace?: never;
1566
+ };
1567
+ "/api/auth/stop-impersonation": {
1568
+ parameters: {
1569
+ query?: never;
1570
+ header?: never;
1571
+ path?: never;
1572
+ cookie?: never;
1573
+ };
1574
+ get?: never;
1575
+ put?: never;
1576
+ /**
1577
+ * Ends an impersonation session and signs the internal user back in. Takes no request body:
1578
+ * the user to return to comes from string PortalClaimTypes.ImpersonatorUserId on the
1579
+ * current principal, so a caller can't choose who it becomes on the way back.
1580
+ * Deliberately NOT gated on string AuthEndpoints.ImpersonationRole. The caller is currently a
1581
+ * contact — the impersonated one — and won't hold the role; more importantly, an admin whose
1582
+ * role was revoked mid-session must still be able to get out. The operation only ever
1583
+ * restores the identity that started the session, so it grants nothing.
1584
+ */
1585
+ post: {
1586
+ parameters: {
1587
+ query?: never;
1588
+ header?: never;
1589
+ path?: never;
1590
+ cookie?: never;
1591
+ };
1592
+ requestBody?: never;
1593
+ responses: {
1594
+ /** @description OK */
1595
+ 200: {
1596
+ headers: {
1597
+ [name: string]: unknown;
1598
+ };
1599
+ content: {
1600
+ "application/json": components["schemas"]["StopImpersonationResponse"];
1601
+ };
1602
+ };
1603
+ };
1604
+ };
1605
+ delete?: never;
1606
+ options?: never;
1607
+ head?: never;
1608
+ patch?: never;
1609
+ trace?: never;
1610
+ };
1611
+ "/api/auth/impersonate/search": {
1612
+ parameters: {
1613
+ query?: never;
1614
+ header?: never;
1615
+ path?: never;
1616
+ cookie?: never;
1617
+ };
1618
+ get?: never;
1619
+ put?: never;
1620
+ post: {
1621
+ parameters: {
1622
+ query?: never;
1623
+ header?: never;
1624
+ path?: never;
1625
+ cookie?: never;
1626
+ };
1627
+ requestBody: {
1628
+ content: {
1629
+ "application/json": components["schemas"]["ImpersonationSearchRequest"];
1630
+ };
1631
+ };
1632
+ responses: {
1633
+ /** @description OK */
1634
+ 200: {
1635
+ headers: {
1636
+ [name: string]: unknown;
1637
+ };
1638
+ content: {
1639
+ "application/json": components["schemas"]["ImpersonationSearchResponse"];
1640
+ };
1641
+ };
1642
+ };
1643
+ };
1644
+ delete?: never;
1645
+ options?: never;
1646
+ head?: never;
1647
+ patch?: never;
1648
+ trace?: never;
1649
+ };
1511
1650
  "/Account/Logout": {
1512
1651
  parameters: {
1513
1652
  query?: never;
@@ -3759,6 +3898,14 @@ interface components {
3759
3898
  /** @description Indicates whether this column can be modified when updating an existing record. */
3760
3899
  isValidForUpdate: boolean;
3761
3900
  };
3901
+ /**
3902
+ * @description Bit flags describing what the current user may do with one column of a record. Reported per
3903
+ * column on Dictionary<string, ColumnSecurityPermission>? TableRecord.ColumnPermissions; the two dimensions are independent, so
3904
+ * every combination is meaningful — including ColumnSecurityPermission.Write without ColumnSecurityPermission.Read for a
3905
+ * column a user fills in but never sees back.
3906
+ * @enum {integer}
3907
+ */
3908
+ ColumnSecurityPermission: 0 | 1 | 2 | 3;
3762
3909
  /**
3763
3910
  * @description A sort specification — a column to sort by and the direction. Shared
3764
3911
  * across the framework: grid UIs use it for sort state,
@@ -4171,6 +4318,29 @@ interface components {
4171
4318
  * string? CurrentUserInfo.AltIdentityTableName.
4172
4319
  */
4173
4320
  altIdentityUserId?: null | string;
4321
+ /**
4322
+ * @description `true` when this session was started by an internal user impersonating a portal
4323
+ * contact. SPA hosts treat it as the trigger to render the impersonation banner and the
4324
+ * "stop impersonating" affordance.
4325
+ * Every other field on this record describes the impersonated user, by design —
4326
+ * Guid? CurrentUserInfo.UserId, IReadOnlyList<string> CurrentUserInfo.Roles and PortalUserType? CurrentUserInfo.PortalUserType are the
4327
+ * contact's, because the session genuinely behaves as that contact. This flag and the two
4328
+ * Impersonator* fields are the only trace of who is really driving it.
4329
+ */
4330
+ isImpersonating?: boolean;
4331
+ /**
4332
+ * Format: uuid
4333
+ * @description Id of the internal user behind an active impersonation session, or `null` when the
4334
+ * session is not impersonating. Informational — `POST /api/auth/stop-impersonation`
4335
+ * re-resolves it server-side from the principal's claims, so SPAs never send it back.
4336
+ */
4337
+ impersonatorUserId?: null | string;
4338
+ /**
4339
+ * @description Display name of the internal user behind an active impersonation session, for the
4340
+ * banner's "you are viewing as … " text. `null` when the session is not impersonating,
4341
+ * or when the name could not be resolved. Display only — never an authorization input.
4342
+ */
4343
+ impersonatorName?: null | string;
4174
4344
  };
4175
4345
  /**
4176
4346
  * @description A single value plotted by Chart.js, plus optional per-point color
@@ -4611,6 +4781,73 @@ interface components {
4611
4781
  */
4612
4782
  mode?: components["schemas"]["RelationshipFilterMode"];
4613
4783
  };
4784
+ /** @description Request body for `POST /api/auth/impersonate`. */
4785
+ ImpersonateRequest: {
4786
+ /**
4787
+ * Format: uuid
4788
+ * @description The `contactid` of the portal contact to impersonate. Resolved server-side through
4789
+ * the contact store only — a systemuserid supplied here does not resolve, so the endpoint
4790
+ * cannot be used to assume another internal user's identity.
4791
+ */
4792
+ targetUserId?: string;
4793
+ };
4794
+ /** @description Outcome of `POST /api/auth/impersonate`. */
4795
+ ImpersonateResponse: {
4796
+ /** @description What happened. See ImpersonateResult. */
4797
+ result?: components["schemas"]["ImpersonateResult"];
4798
+ };
4799
+ /**
4800
+ * @description Outcome of `POST /api/auth/impersonate`. Members carry explicit integer values so the
4801
+ * JSON wire form is a stable contract across reorderings.
4802
+ * @enum {integer}
4803
+ */
4804
+ ImpersonateResult: 0 | 1 | 2 | 3 | 4 | 5;
4805
+ /**
4806
+ * @description A portal contact offered as an impersonation target. Deliberately minimal: just enough to
4807
+ * identify the right person in the picker, since this crosses the wire to an admin's browser.
4808
+ */
4809
+ ImpersonationCandidate: {
4810
+ /**
4811
+ * Format: uuid
4812
+ * @description The contact's `contactid`, sent back as the target of the impersonate call.
4813
+ */
4814
+ contactId?: string;
4815
+ /** @description The contact's `fullname`, or `null` when unset. */
4816
+ fullName?: null | string;
4817
+ /**
4818
+ * @description The first non-empty address among the contact's configured email columns, shown to
4819
+ * disambiguate people who share a name. `null` when the contact has no address.
4820
+ */
4821
+ email?: null | string;
4822
+ };
4823
+ /**
4824
+ * @description Request body for `POST /api/auth/impersonate/search` — the query behind the
4825
+ * impersonation picker.
4826
+ */
4827
+ ImpersonationSearchRequest: {
4828
+ /**
4829
+ * @description What the admin typed. A value that parses as a Guid is treated as an exact
4830
+ * `contactid` lookup; anything else is matched against the contact's full name and
4831
+ * email columns. Queries shorter than
4832
+ * int ImpersonationSearch.MinimumQueryLength characters return no results.
4833
+ */
4834
+ query?: string;
4835
+ };
4836
+ /** @description Results of `POST /api/auth/impersonate/search`. */
4837
+ ImpersonationSearchResponse: {
4838
+ /**
4839
+ * @description The matching contacts the caller is allowed to impersonate, capped at
4840
+ * int ImpersonationSearch.MaximumResults. Empty when the query was too short,
4841
+ * matched nothing, or the caller isn't permitted to impersonate.
4842
+ */
4843
+ results?: components["schemas"]["ImpersonationCandidate"][];
4844
+ /**
4845
+ * @description `true` when the result set hit int ImpersonationSearch.MaximumResults and
4846
+ * more matches may exist. The picker uses it to prompt for a narrower query rather than
4847
+ * implying the list is complete. No total count is computed — this is a picker, not a grid.
4848
+ */
4849
+ hasMore?: boolean;
4850
+ };
4614
4851
  /**
4615
4852
  * @description Join type used on a FetchXML link-entity.
4616
4853
  * @enum {integer}
@@ -5121,13 +5358,25 @@ interface components {
5121
5358
  * @description The total number of records that match the query, when the server returned a count. Null when the count was not requested or could not be computed.
5122
5359
  */
5123
5360
  totalRecordCount?: null | number | string;
5124
- /** @description The opaque paging cookie used by Dataverse to efficiently fetch the next page. Null when there are no further pages. */
5361
+ /**
5362
+ * @description The opaque paging cookie used by Dataverse to efficiently fetch the next page. Dataverse still issues a
5363
+ * cookie on the final populated page (it only comes back null once a page past the end is requested), so this
5364
+ * is not an end-of-data signal — use bool? PagingInfo.MoreRecords for that.
5365
+ */
5125
5366
  pagingCookie?: null | string;
5126
5367
  /**
5127
5368
  * Format: int32
5128
5369
  * @description The 1-based page number of the records in the response.
5129
5370
  */
5130
5371
  pageNumber?: number | string;
5372
+ /**
5373
+ * @description Whether Dataverse reports further pages beyond this one (`EntityCollection.MoreRecords`). This is the
5374
+ * authoritative end-of-data signal for sequential paging: int? PagingInfo.TotalRecordCount is computed by
5375
+ * Dataverse before the portal's per-row permission handlers drop rows, so the rows a caller accumulates can
5376
+ * legitimately total fewer than the count, and string? PagingInfo.PagingCookie is still populated on the last
5377
+ * populated page. Null when the source of the response cannot report it.
5378
+ */
5379
+ moreRecords?: null | boolean;
5131
5380
  };
5132
5381
  /**
5133
5382
  * @description Returned by `GET /api/auth/external-login/pending` when a recent OAuth
@@ -5470,6 +5719,18 @@ interface components {
5470
5719
  * "open this record"-style links without per-row metadata lookups.
5471
5720
  */
5472
5721
  isPrimaryName?: boolean;
5722
+ /**
5723
+ * @description What the current user may do with this column, from column-level
5724
+ * security. ColumnSecurityPermission.All — the default —
5725
+ * whenever no column restriction applies, which is the usual case.
5726
+ * A column missing ColumnSecurityPermission.Read is one
5727
+ * whose values arrive masked, and one missing
5728
+ * ColumnSecurityPermission.Write should not offer inline
5729
+ * editing, since the save would be rejected server-side. Columns the user
5730
+ * may not read at all are absent from the list entirely rather than
5731
+ * reported here.
5732
+ */
5733
+ permissions?: components["schemas"]["ColumnSecurityPermission"];
5473
5734
  /**
5474
5735
  * Format: int32
5475
5736
  * @description Configured display width in pixels (from the view definition).
@@ -5531,6 +5792,22 @@ interface components {
5531
5792
  */
5532
5793
  errors?: string[];
5533
5794
  };
5795
+ /**
5796
+ * @description Outcome of `POST /api/auth/stop-impersonation`. Takes no request body — the internal
5797
+ * user to return to is re-resolved server-side from
5798
+ * string PortalClaimTypes.ImpersonatorUserId, so the client can't choose who it
5799
+ * becomes on the way back.
5800
+ */
5801
+ StopImpersonationResponse: {
5802
+ /** @description What happened. See StopImpersonationResult. */
5803
+ result?: components["schemas"]["StopImpersonationResult"];
5804
+ };
5805
+ /**
5806
+ * @description Outcome of `POST /api/auth/stop-impersonation`. Members carry explicit integer values
5807
+ * so the JSON wire form is a stable contract across reorderings.
5808
+ * @enum {integer}
5809
+ */
5810
+ StopImpersonationResult: 0 | 1 | 2 | 3;
5534
5811
  /** @description Outcome of `POST /api/auth/switch-identity`. */
5535
5812
  SwitchIdentityResponse: {
5536
5813
  /** @description What happened. See SwitchIdentityResult. */
@@ -5584,6 +5861,22 @@ interface components {
5584
5861
  };
5585
5862
  /** @description The set of permissions the current user has on this record. Defaults to TableSecurityPermission.Read. */
5586
5863
  permissions?: components["schemas"]["TableSecurityPermission"];
5864
+ /**
5865
+ * @description Per-column access for the current user, keyed by column logical name — populated only for
5866
+ * the columns of this record whose access is narrowed by column-level security, so a record on
5867
+ * an unrestricted table carries nothing. Absent from the dictionary means full access, which is
5868
+ * the overwhelmingly common case; the dictionary itself is null when nothing is restricted.
5869
+ * Clients use it to render honestly rather than to enforce anything — the server has already
5870
+ * withheld what the user may not read and rejects what they may not write. A column present
5871
+ * here without ColumnSecurityPermission.Read is one whose value has been masked
5872
+ * (its real value never left the server), and one without
5873
+ * ColumnSecurityPermission.Write should render read-only rather than letting the
5874
+ * user edit into a save that will be rejected.Columns withheld by omission are deliberately NOT listed: omitting exists precisely so that
5875
+ * nothing in the response reveals the column, and naming it here would undo that.
5876
+ */
5877
+ columnPermissions?: null | {
5878
+ [key: string]: components["schemas"]["ColumnSecurityPermission"];
5879
+ };
5587
5880
  /** @description Per-column localized display strings supplied by Dataverse, keyed by column logical name. */
5588
5881
  formattedValues?: {
5589
5882
  [key: string]: string;
@@ -5906,6 +6199,12 @@ type ConfirmExternalLoginRequest = Schemas$1['ConfirmExternalLoginRequest'];
5906
6199
  type ConfirmExternalLoginResponse = Schemas$1['ConfirmExternalLoginResponse'];
5907
6200
  type SelectExternalLoginRequest = Schemas$1['SelectExternalLoginRequest'];
5908
6201
  type SwitchIdentityResponse = Schemas$1['SwitchIdentityResponse'];
6202
+ type ImpersonateRequest = Schemas$1['ImpersonateRequest'];
6203
+ type ImpersonateResponse = Schemas$1['ImpersonateResponse'];
6204
+ type StopImpersonationResponse = Schemas$1['StopImpersonationResponse'];
6205
+ type ImpersonationSearchRequest = Schemas$1['ImpersonationSearchRequest'];
6206
+ type ImpersonationSearchResponse = Schemas$1['ImpersonationSearchResponse'];
6207
+ type ImpersonationCandidate = Schemas$1['ImpersonationCandidate'];
5909
6208
  type ProfileResponse = Schemas$1['ProfileResponse'];
5910
6209
  type UpdateProfileRequest = Schemas$1['UpdateProfileRequest'];
5911
6210
  type SetPasswordRequest = Schemas$1['SetPasswordRequest'];
@@ -6014,6 +6313,32 @@ declare class AuthClient {
6014
6313
  * supplies no parameters.
6015
6314
  */
6016
6315
  switchIdentityAsync(signal?: AbortSignal): Promise<SwitchIdentityResponse>;
6316
+ /**
6317
+ * Starts impersonating a portal contact, swapping the auth cookie for theirs. Restricted
6318
+ * server-side to internal users holding the `SystemAdmin` role; the target is resolved through
6319
+ * the contact store alone, so a systemuser id can't be supplied to assume a staff identity.
6320
+ *
6321
+ * On `ImpersonateResult.Started` the session IS that contact — `/api/auth/me` reports the
6322
+ * contact's id, roles and user type, with only `isImpersonating` / `impersonator*` betraying
6323
+ * who is behind it. Reload or re-fetch the user after this resolves; anything already rendered
6324
+ * was rendered for the previous identity.
6325
+ */
6326
+ impersonateAsync(targetUserId: string, signal?: AbortSignal): Promise<ImpersonateResponse>;
6327
+ /**
6328
+ * Ends an impersonation session and signs the internal user back in. Takes no parameters — the
6329
+ * identity to return to is read from the session's own claims server-side, so a caller can't
6330
+ * choose who it becomes on the way back.
6331
+ */
6332
+ stopImpersonationAsync(signal?: AbortSignal): Promise<StopImpersonationResponse>;
6333
+ /**
6334
+ * Searches portal contacts that may be impersonated. A query that parses as a GUID is an exact
6335
+ * user-id lookup; otherwise it matches full name and email columns, and queries shorter than
6336
+ * three characters return nothing.
6337
+ *
6338
+ * Returns an empty result rather than failing when the caller isn't permitted to impersonate,
6339
+ * so a picker renders "no matches" without learning which condition applied.
6340
+ */
6341
+ searchImpersonationTargetsAsync(query: string, signal?: AbortSignal): Promise<ImpersonationSearchResponse>;
6017
6342
  /** Reads the signed-in user's manage-profile snapshot (Identity status + linked contact fields). */
6018
6343
  getProfileAsync(signal?: AbortSignal): Promise<ProfileResponse>;
6019
6344
  /** Updates first/last/mobile on the signed-in user's linked Dataverse contact. */
@@ -6158,6 +6483,23 @@ declare const ChartDateGrouping: {
6158
6483
  readonly QuarterAndYear: 10;
6159
6484
  };
6160
6485
  type ChartDateGrouping = (typeof ChartDateGrouping)[keyof typeof ChartDateGrouping];
6486
+ /**
6487
+ * Bit flags describing what the current user may do with one column of a record. Reported per
6488
+ * column on Dictionary&lt;string, ColumnSecurityPermission&gt;? TableRecord.ColumnPermissions; the two dimensions are independent, so
6489
+ * every combination is meaningful — including ColumnSecurityPermission.Write without ColumnSecurityPermission.Read for a
6490
+ * column a user fills in but never sees back.
6491
+ */
6492
+ declare const ColumnSecurityPermission: {
6493
+ /** The column can be neither read nor written. */
6494
+ readonly None: 0;
6495
+ /** The column's real value is returned. */
6496
+ readonly Read: 1;
6497
+ /** The column can be included in a create or update. */
6498
+ readonly Write: 2;
6499
+ /** Full access — the default for every column not listed in ColumnPermissions. */
6500
+ readonly All: 3;
6501
+ };
6502
+ type ColumnSecurityPermission = (typeof ColumnSecurityPermission)[keyof typeof ColumnSecurityPermission];
6161
6503
  /**
6162
6504
  * Identifies the data type of a Dataverse column. Values 0–20 mirror the Dataverse SDK's `AttributeTypeCode`; values 40+ are PowerPortalsPro-specific column types not present in Dataverse.
6163
6505
  */
@@ -6283,6 +6625,25 @@ declare const FileArchiveResponseFormat: {
6283
6625
  readonly Json: 1;
6284
6626
  };
6285
6627
  type FileArchiveResponseFormat = (typeof FileArchiveResponseFormat)[keyof typeof FileArchiveResponseFormat];
6628
+ /**
6629
+ * Outcome of `POST /api/auth/impersonate`. Members carry explicit integer values so the
6630
+ * JSON wire form is a stable contract across reorderings.
6631
+ */
6632
+ declare const ImpersonateResult: {
6633
+ /** The target contact was signed in and the auth cookie has been swapped. */
6634
+ readonly Started: 0;
6635
+ /** The current request is unauthenticated. */
6636
+ readonly NotAuthenticated: 1;
6637
+ /** The caller may not impersonate — either they don't hold the SystemAdmin role, or they aren't a real internal systemuser (a contact backed by a stub systemuser is still a portal contact and can never impersonate). */
6638
+ readonly NotAuthorized: 2;
6639
+ /** No active contact exists with the requested id. Also returned when the id belongs to a systemuser — the lookup only ever consults the contact store, so an internal user's id simply doesn't resolve. */
6640
+ readonly TargetNotFound: 3;
6641
+ /** The contact exists but the host's impersonation target filter rejected it. */
6642
+ readonly TargetNotImpersonatable: 4;
6643
+ /** The session is already impersonating. Nesting isn't supported — it would make the return path order-dependent — so stop the current impersonation first. */
6644
+ readonly AlreadyImpersonating: 5;
6645
+ };
6646
+ type ImpersonateResult = (typeof ImpersonateResult)[keyof typeof ImpersonateResult];
6286
6647
  /**
6287
6648
  * Join type used on a FetchXML link-entity.
6288
6649
  */
@@ -6400,6 +6761,21 @@ declare const ResetPasswordResult: {
6400
6761
  readonly InvalidPassword: 2;
6401
6762
  };
6402
6763
  type ResetPasswordResult = (typeof ResetPasswordResult)[keyof typeof ResetPasswordResult];
6764
+ /**
6765
+ * Outcome of `POST /api/auth/stop-impersonation`. Members carry explicit integer values
6766
+ * so the JSON wire form is a stable contract across reorderings.
6767
+ */
6768
+ declare const StopImpersonationResult: {
6769
+ /** Impersonation ended and the auth cookie is back to the internal user. */
6770
+ readonly Stopped: 0;
6771
+ /** The session wasn't impersonating — there was nothing to stop. */
6772
+ readonly NotImpersonating: 1;
6773
+ /** The internal user recorded on the session no longer resolves (disabled or removed in Dataverse mid-session). The impersonated session is signed out rather than left running, so the caller ends up anonymous and must sign in again. */
6774
+ readonly ImpersonatorNotFound: 2;
6775
+ /** The current request is unauthenticated. */
6776
+ readonly NotAuthenticated: 3;
6777
+ };
6778
+ type StopImpersonationResult = (typeof StopImpersonationResult)[keyof typeof StopImpersonationResult];
6403
6779
  /**
6404
6780
  * Outcome of `POST /api/auth/switch-identity`. Members carry explicit
6405
6781
  * integer values so the JSON wire form is a stable contract across
@@ -6457,7 +6833,7 @@ declare const ViewType: {
6457
6833
  type ViewType = (typeof ViewType)[keyof typeof ViewType];
6458
6834
 
6459
6835
  type Schemas = components['schemas'];
6460
- type TableRecord$1 = Schemas['TableRecord'];
6836
+ type TableRecord$2 = Schemas['TableRecord'];
6461
6837
  type TableRecordReference = Schemas['TableRecordReference'];
6462
6838
  type CreateResponse = Schemas['CreateResponse'];
6463
6839
  type UpdateResponse = Schemas['UpdateResponse'];
@@ -6564,12 +6940,12 @@ declare class PowerPortalsProClient {
6564
6940
  * marks every property as modified before applying so column values
6565
6941
  * arriving from JSON (which carry no dirty flags) round-trip correctly.
6566
6942
  */
6567
- createRecordAsync(record: TableRecord$1, signal?: AbortSignal): Promise<CreateResponse>;
6943
+ createRecordAsync(record: TableRecord$2, signal?: AbortSignal): Promise<CreateResponse>;
6568
6944
  /**
6569
6945
  * Reads a single record. `columns` (logical names) narrows the projection to a subset;
6570
6946
  * omit it for the table's full set of columns visible to the caller.
6571
6947
  */
6572
- retrieveRecordAsync(tableLogicalName: string, recordId: string, columns?: readonly string[], signal?: AbortSignal): Promise<TableRecord$1>;
6948
+ retrieveRecordAsync(tableLogicalName: string, recordId: string, columns?: readonly string[], signal?: AbortSignal): Promise<TableRecord$2>;
6573
6949
  /**
6574
6950
  * Probes whether the localization-translation feature is usable: whether a translation
6575
6951
  * provider is configured, whether the managed solution is installed, and the candidate
@@ -6673,7 +7049,7 @@ declare class PowerPortalsProClient {
6673
7049
  * Updates an existing record. URL is derived from `record.tableName` and `record.id`
6674
7050
  * `record.id` must be set. For a new record, use {@link createRecordAsync} instead.
6675
7051
  */
6676
- updateRecordAsync(record: TableRecord$1, signal?: AbortSignal): Promise<UpdateResponse>;
7052
+ updateRecordAsync(record: TableRecord$2, signal?: AbortSignal): Promise<UpdateResponse>;
6677
7053
  /**
6678
7054
  * Executes a batch of {@link OrganizationRequest}s as a single round-trip.
6679
7055
  * The MainContext save flow uses this to ship every dirty descendant's
@@ -6867,6 +7243,32 @@ declare class PowerPortalsProClient {
6867
7243
  getOrganizationSettingsAsync(signal?: AbortSignal): Promise<OrganizationSettings>;
6868
7244
  }
6869
7245
 
7246
+ type TableRecord$1 = components['schemas']['TableRecord'];
7247
+ /**
7248
+ * Returns what the current user may do with one of a record's columns, from column-level
7249
+ * security. Columns the server didn't narrow — the overwhelming majority — aren't carried on the
7250
+ * record at all, so anything unlisted comes back as `ColumnSecurityPermission.All`.
7251
+ *
7252
+ * Mirrors `TableRecordExtensions.GetColumnPermissions` on the .NET side.
7253
+ */
7254
+ declare function getColumnPermissions(record: Pick<TableRecord$1, 'columnPermissions'> | null | undefined, columnName: string): ColumnSecurityPermission;
7255
+ /**
7256
+ * Whether the record carries this column's real value. `false` means the value present is a mask
7257
+ * standing in for one the user may not see — render it as withheld rather than as data. A column
7258
+ * the user may not read at all isn't on the record in the first place, so it never reaches here.
7259
+ *
7260
+ * Note that for every column type but text the mask lives in the record's *formatted* value, not
7261
+ * its value: the server can't express a placeholder as a number, date or lookup, so it clears the
7262
+ * value instead. Render a withheld column through `<ColumnDisplayValue>`, which reads the
7263
+ * formatted value and therefore shows the mask whatever the column's type.
7264
+ */
7265
+ declare function canReadColumn(record: Pick<TableRecord$1, 'columnPermissions'> | null | undefined, columnName: string): boolean;
7266
+ /**
7267
+ * Whether the user may include this column in a save. `false` means an editor should render
7268
+ * read-only — the server rejects a create or update that changes it.
7269
+ */
7270
+ declare function canWriteColumn(record: Pick<TableRecord$1, 'columnPermissions'> | null | undefined, columnName: string): boolean;
7271
+
6870
7272
  type TableRecord = components['schemas']['TableRecord'];
6871
7273
  /**
6872
7274
  * Resolves the id to use when building a `TableRecordReference` (or any
@@ -6887,4 +7289,4 @@ declare function getRecordReferenceId(record: Pick<TableRecord, 'id' | '_idForCr
6887
7289
 
6888
7290
  declare const VERSION = "0.1.0";
6889
7291
 
6890
- export { type AggregateChartConfig, AggregateType, ArchiveFormat, ArgumentError, ArgumentNullError, type AssociateRequest, AuthClient, type AuthOptionsResponse, type AuthenticatorSetupResponse, type BaseDataPoint, type CacheClearResult, type ChangeEmailRequest, type ChangeEmailResponse, ChangeEmailResult, type ChangePasswordRequest, type ChangePasswordResponse, ChangePasswordResult, type ChartAggregation, type ChartData, type ChartDataRequest, type ChartDataResponse, type ChartDataset, ChartDateGrouping, type ChartGrouping, type ChartLinkedEntity, type ColumnSort, ColumnType, type ConfirmEmailRequest, type ConfirmEmailResponse, type ConfirmExternalLoginRequest, type ConfirmExternalLoginResponse, ConfirmExternalLoginResult, type CreateRequest, type CreateResponse, type Currency, type CurrentLoginInfo, type CurrentUserInfo, type DataPoint, type DataverseDataPoint, DateTimeBehavior, type DeletePersonalDataRequest, type DeletePersonalDataResponse, DeletePersonalDataResult, type DeleteRequest, type DeleteResponse, type Disable2faResponse, type DisassociateRequest, EntityRole, ExternalLoginCandidateKind, type ExternalLoginProviderInfo, type ExternalLoginsResponse, FileArchiveResponseFormat, type FileInfo, type Forget2faResponse, type GridDataRequest, type GridDataResponse, type GridFilterBase, InvalidOperationError, JoinOperator, type LocalizationFileDownload, type LocalizationOverview, type LocalizationPipelineConfiguration, type LocalizationSourceKind, type LocalizationSourceLoad, type LocalizationSourceStatus, type LoginRequest, type LoginResponse, LoginResult, type MergedLocalizationEntry, type OrganizationRequest, type OrganizationResponse, type OrganizationSettings, type PendingExternalLoginResponse, type PersonalDataResponse, PortalUserType, PowerPortalsProClient, PowerPortalsProError, type PowerPortalsProErrorInit, type ProblemDetails, type ProfileResponse, type RecoveryCodesResponse, type RegisterRequest, type RegisterResponse, RegisterResult, type RelationshipFilter, RelationshipFilterMode, type RemoveExternalLoginRequest, type RemoveExternalLoginResponse, type RequestOptions, type RequestPasswordResetRequest, RequiredLevel, type ResendEmailConfirmationRequest, type ResetAuthenticatorResponse, type ResetPasswordRequest, type ResetPasswordResponse, ResetPasswordResult, type ResolvedColumn, type RetrieveRecordsResponse, Routes, type SelectExternalLoginRequest, type SendEmailConfirmationResponse, type SetPasswordRequest, type SetPasswordResponse, type SwitchIdentityResponse, SwitchIdentityResult, type TableMetadata, type TableRecord$1 as TableRecord, type TableRecordReference, TableSecurityPermission, type TranslatedFile, type TranslationAvailability, type TranslationLanguageOption, type TranslationRequest, type TranslationResult, Transport, type TransportOptions, type TwoFactorStatusResponse, UnauthorizedAccessError, type UpdateProfileRequest, type UpdateRequest, type UpdateResponse, VERSION, type VerifyAuthenticatorRequest, type VerifyAuthenticatorResponse, type VerifyTwoFactorRequest, type VerifyTwoFactorResponse, type ViewMetadata, ViewType, type components, getRecordReferenceId, mapProblemDetails, type paths };
7292
+ export { type AggregateChartConfig, AggregateType, ArchiveFormat, ArgumentError, ArgumentNullError, type AssociateRequest, AuthClient, type AuthOptionsResponse, type AuthenticatorSetupResponse, type BaseDataPoint, type CacheClearResult, type ChangeEmailRequest, type ChangeEmailResponse, ChangeEmailResult, type ChangePasswordRequest, type ChangePasswordResponse, ChangePasswordResult, type ChartAggregation, type ChartData, type ChartDataRequest, type ChartDataResponse, type ChartDataset, ChartDateGrouping, type ChartGrouping, type ChartLinkedEntity, ColumnSecurityPermission, type ColumnSort, ColumnType, type ConfirmEmailRequest, type ConfirmEmailResponse, type ConfirmExternalLoginRequest, type ConfirmExternalLoginResponse, ConfirmExternalLoginResult, type CreateRequest, type CreateResponse, type Currency, type CurrentLoginInfo, type CurrentUserInfo, type DataPoint, type DataverseDataPoint, DateTimeBehavior, type DeletePersonalDataRequest, type DeletePersonalDataResponse, DeletePersonalDataResult, type DeleteRequest, type DeleteResponse, type Disable2faResponse, type DisassociateRequest, EntityRole, ExternalLoginCandidateKind, type ExternalLoginProviderInfo, type ExternalLoginsResponse, FileArchiveResponseFormat, type FileInfo, type Forget2faResponse, type GridDataRequest, type GridDataResponse, type GridFilterBase, type ImpersonateRequest, type ImpersonateResponse, ImpersonateResult, type ImpersonationCandidate, type ImpersonationSearchRequest, type ImpersonationSearchResponse, InvalidOperationError, JoinOperator, type LocalizationFileDownload, type LocalizationOverview, type LocalizationPipelineConfiguration, type LocalizationSourceKind, type LocalizationSourceLoad, type LocalizationSourceStatus, type LoginRequest, type LoginResponse, LoginResult, type MergedLocalizationEntry, type OrganizationRequest, type OrganizationResponse, type OrganizationSettings, type PendingExternalLoginResponse, type PersonalDataResponse, PortalUserType, PowerPortalsProClient, PowerPortalsProError, type PowerPortalsProErrorInit, type ProblemDetails, type ProfileResponse, type RecoveryCodesResponse, type RegisterRequest, type RegisterResponse, RegisterResult, type RelationshipFilter, RelationshipFilterMode, type RemoveExternalLoginRequest, type RemoveExternalLoginResponse, type RequestOptions, type RequestPasswordResetRequest, RequiredLevel, type ResendEmailConfirmationRequest, type ResetAuthenticatorResponse, type ResetPasswordRequest, type ResetPasswordResponse, ResetPasswordResult, type ResolvedColumn, type RetrieveRecordsResponse, Routes, type SelectExternalLoginRequest, type SendEmailConfirmationResponse, type SetPasswordRequest, type SetPasswordResponse, type StopImpersonationResponse, StopImpersonationResult, type SwitchIdentityResponse, SwitchIdentityResult, type TableMetadata, type TableRecord$2 as TableRecord, type TableRecordReference, TableSecurityPermission, type TranslatedFile, type TranslationAvailability, type TranslationLanguageOption, type TranslationRequest, type TranslationResult, Transport, type TransportOptions, type TwoFactorStatusResponse, UnauthorizedAccessError, type UpdateProfileRequest, type UpdateRequest, type UpdateResponse, VERSION, type VerifyAuthenticatorRequest, type VerifyAuthenticatorResponse, type VerifyTwoFactorRequest, type VerifyTwoFactorResponse, type ViewMetadata, ViewType, canReadColumn, canWriteColumn, type components, getColumnPermissions, getRecordReferenceId, mapProblemDetails, type paths };