import type { Connection, HealthCheckResult } from "@executor-js/sdk/shared";// ---------------------------------------------------------------------------// Enterprise-managed connections — what a row may offer.//// An enterprise-managed connection mirrors organization policy. It holds no// durable grant of its own: renewal re-runs the ID-JAG chain from the identity// assertion, and the enterprise identity provider decides every time. Two// consequences drive everything below.//// 1. There is nothing local to delete. A "Remove" that dropped the row would// claim the user had revoked access when they had not — the identity// provider still authorizes them, and the next connect would hand it// straight back. Revocation lives at the provider.//// 2. There is no interactive route to re-run. Reconnect exists to re-consent// through the browser, and this profile has no consent step; the console// also holds no identity assertion to present. Offering it would produce// a failure the user cannot act on.//// Connect stays available for ADDITIONAL personal accounts on the same// integration: enterprise-managed authorization binds exactly one enterprise// identity, and it does not claim the integration.// ---------------------------------------------------------------------------/** Grayscale, a word, no hue — see design.md, "Status and semantics". */export const MANAGED_CONNECTION_BADGE = "Managed by your organization";/** Why the row offers no Remove. Shown as helper text, sentence case. */export const MANAGED_CONNECTION_REVOCATION_HINT = "This connection follows your organization's policy. Revoke access at your identity provider, not here.";/** What an enterprise-managed row shows when the identity provider has since * declined to renew it. The status word for this state — NOT "Expired", * which would invite a reconnect that cannot succeed. */export const MANAGED_CONNECTION_BLOCKED_LABEL = "Blocked by your organization";export interface ConnectionRowPolicy { /** The connection was minted through enterprise-managed authorization. */ readonly managed: boolean; /** An administrator decision is the CURRENT state of this connection: the * last credential resolution was refused by the identity provider. */ readonly blockedByAdmin: boolean; /** The provider's RFC 6749 §5.2 code, for support traceability. */ readonly oauthErrorCode: string | null; /** Whether the row may offer to delete this connection. */ readonly canRemove: boolean; /** Whether the row may offer to re-run an interactive OAuth flow. */ readonly canReconnect: boolean; /** The connection is stalled because the shared WORK IDENTITY behind it died, * not because anything about this connection did. The row's recovery is one * re-link — which revives every connection pointing at the same identity — * and emphatically not N reconnects, none of which could succeed. */ readonly needsWorkIdentityRelink: boolean;}/** * What one connection row may offer, from the connection and its freshest * health verdict. * * Both inputs are read STRUCTURALLY: `enterpriseManaged` is projected from the * connection's persisted provider state, and `blockedByAdmin` is a typed field * on the health result. Neither is inferred from a message, a status word, or * the grant of the OAuth app behind the connection — an `id_jag` app still * falls back to the interactive flow against a server that does not advertise * the profile, and such a connection is ordinary in every way. */export const connectionRowPolicy = ( connection: Connection, health: HealthCheckResult | null | undefined,): ConnectionRowPolicy => { const managed = connection.enterpriseManaged === true; const blockedByAdmin = health?.blockedByAdmin === true; return { managed, blockedByAdmin, oauthErrorCode: blockedByAdmin ? (health?.oauthErrorCode ?? null) : null, canRemove: !managed, // A blocked connection is never reconnectable either, managed or not: the // interactive flow is exactly the route the enterprise just closed. canReconnect: !managed && !blockedByAdmin, // An administrator denial outranks it: both stall the connection, but only // one of them is fixable by the member, and offering a link against a // client the identity provider has denied would waste a sign-in. needsWorkIdentityRelink: health?.workIdentityRelinkRequired === true && !blockedByAdmin, };};/** The one action a stalled work identity offers, and the whole reason it is * not "Reconnect": it is about the IDENTITY, and it is not per connection. */export const MANAGED_CONNECTION_RELINK_ACTION = "Re-link Work Identity";/** Said in full where there is room for a sentence, because "re-link" alone * reads as a per-row repair and this is the opposite of one. */export const MANAGED_CONNECTION_RELINK_HINT = "Your work identity was rejected. One re-link restores every connection your organization manages.";
import type { Connection, HealthCheckResult } from "@executor-js/sdk/shared";
// ---------------------------------------------------------------------------
// Enterprise-managed connections — what a row may offer.
//
// An enterprise-managed connection mirrors organization policy. It holds no
// durable grant of its own: renewal re-runs the ID-JAG chain from the identity
// assertion, and the enterprise identity provider decides every time. Two
// consequences drive everything below.
//
// 1. There is nothing local to delete. A "Remove" that dropped the row would
// claim the user had revoked access when they had not — the identity
// provider still authorizes them, and the next connect would hand it
// straight back. Revocation lives at the provider.
//
// 2. There is no interactive route to re-run. Reconnect exists to re-consent
// through the browser, and this profile has no consent step; the console
// also holds no identity assertion to present. Offering it would produce
// a failure the user cannot act on.
//
// Connect stays available for ADDITIONAL personal accounts on the same
// integration: enterprise-managed authorization binds exactly one enterprise
// identity, and it does not claim the integration.
// ---------------------------------------------------------------------------
/** Grayscale, a word, no hue — see design.md, "Status and semantics". */
export const MANAGED_CONNECTION_BADGE = "Managed by your organization";
/** Why the row offers no Remove. Shown as helper text, sentence case. */
export const MANAGED_CONNECTION_REVOCATION_HINT =
"This connection follows your organization's policy. Revoke access at your identity provider, not here.";
/** What an enterprise-managed row shows when the identity provider has since
* declined to renew it. The status word for this state — NOT "Expired",
* which would invite a reconnect that cannot succeed. */
export const MANAGED_CONNECTION_BLOCKED_LABEL = "Blocked by your organization";
export interface ConnectionRowPolicy {
/** The connection was minted through enterprise-managed authorization. */
readonly managed: boolean;
/** An administrator decision is the CURRENT state of this connection: the
* last credential resolution was refused by the identity provider. */
readonly blockedByAdmin: boolean;
/** The provider's RFC 6749 §5.2 code, for support traceability. */
readonly oauthErrorCode: string | null;
/** Whether the row may offer to delete this connection. */
readonly canRemove: boolean;
/** Whether the row may offer to re-run an interactive OAuth flow. */
readonly canReconnect: boolean;
/** The connection is stalled because the shared WORK IDENTITY behind it died,
* not because anything about this connection did. The row's recovery is one
* re-link — which revives every connection pointing at the same identity —
* and emphatically not N reconnects, none of which could succeed. */
readonly needsWorkIdentityRelink: boolean;
}
/**
* What one connection row may offer, from the connection and its freshest
* health verdict.
*
* Both inputs are read STRUCTURALLY: `enterpriseManaged` is projected from the
* connection's persisted provider state, and `blockedByAdmin` is a typed field
* on the health result. Neither is inferred from a message, a status word, or
* the grant of the OAuth app behind the connection — an `id_jag` app still
* falls back to the interactive flow against a server that does not advertise
* the profile, and such a connection is ordinary in every way.
*/
export const connectionRowPolicy = (
connection: Connection,
health: HealthCheckResult | null | undefined,
): ConnectionRowPolicy => {
const managed = connection.enterpriseManaged === true;
const blockedByAdmin = health?.blockedByAdmin === true;
return {
managed,
blockedByAdmin,
oauthErrorCode: blockedByAdmin ? (health?.oauthErrorCode ?? null) : null,
canRemove: !managed,
// A blocked connection is never reconnectable either, managed or not: the
// interactive flow is exactly the route the enterprise just closed.
canReconnect: !managed && !blockedByAdmin,
// An administrator denial outranks it: both stall the connection, but only
// one of them is fixable by the member, and offering a link against a
// client the identity provider has denied would waste a sign-in.
needsWorkIdentityRelink: health?.workIdentityRelinkRequired === true && !blockedByAdmin,
};
};
/** The one action a stalled work identity offers, and the whole reason it is
* not "Reconnect": it is about the IDENTITY, and it is not per connection. */
export const MANAGED_CONNECTION_RELINK_ACTION = "Re-link Work Identity";
/** Said in full where there is room for a sentence, because "re-link" alone
* reads as a per-row repair and this is the opposite of one. */
export const MANAGED_CONNECTION_RELINK_HINT =
"Your work identity was rejected. One re-link restores every connection your organization manages.";