@secondlayer/shared 13.10.0 → 13.12.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.
@@ -928,6 +928,12 @@ interface Database {
928
928
  account_balance_alerts: AccountBalanceAlertsTable;
929
929
  webhook_incident_alerts: WebhookIncidentAlertsTable;
930
930
  cli_device_logins: CliDeviceLoginsTable;
931
+ oauth_clients: OauthClientsTable;
932
+ oauth_requests: OauthRequestsTable;
933
+ oauth_codes: OauthCodesTable;
934
+ oauth_grants: OauthGrantsTable;
935
+ oauth_tokens: OauthTokensTable;
936
+ oauth_refresh_retired: OauthRefreshRetiredTable;
931
937
  sentinel_accounts: SentinelAccountsTable;
932
938
  waitlists: WaitlistsTable;
933
939
  waitlist_signups: WaitlistSignupsTable;
@@ -1030,13 +1036,17 @@ interface WebhookIncidentAlertsTable {
1030
1036
  resolved_at: Date | null;
1031
1037
  }
1032
1038
  type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
1033
- /** One browser sign-in attempt from `sl login`. Only the hash of the CLI's
1034
- * device code is stored; the key is minted when the CLI polls after approval. */
1039
+ /** The product that started a CLI sign-in; null is `sl login`. */
1040
+ type CliDeviceProduct = "sentinel";
1041
+ /** One browser sign-in attempt from `sl login` (or `sentinel login`). Only the
1042
+ * hash of the CLI's device code is stored; the session is opened when the CLI
1043
+ * polls after approval. */
1035
1044
  interface CliDeviceLoginsTable {
1036
1045
  id: Generated<string>;
1037
1046
  device_code_hash: string;
1038
1047
  user_code: string;
1039
1048
  client_name: string;
1049
+ product: CliDeviceProduct | null;
1040
1050
  status: Generated<CliDeviceLoginStatus>;
1041
1051
  account_id: string | null;
1042
1052
  key_name: string | null;
@@ -1045,6 +1055,72 @@ interface CliDeviceLoginsTable {
1045
1055
  approved_at: Date | null;
1046
1056
  consumed_at: Date | null;
1047
1057
  }
1058
+ /** An app that registered itself (RFC 7591). Public clients only: no secret. */
1059
+ interface OauthClientsTable {
1060
+ id: string;
1061
+ /** The app's own claim, validated at registration; shown quoted. */
1062
+ name: string;
1063
+ redirect_uris: string[];
1064
+ created_ip: string | null;
1065
+ created_at: Generated<Date>;
1066
+ /** Set when it first gets tokens; never-used clients are purged. */
1067
+ last_used_at: Date | null;
1068
+ }
1069
+ type OauthRequestStatus = "pending" | "approved" | "denied";
1070
+ /** One authorize request waiting for (or answered on) the consent page. */
1071
+ interface OauthRequestsTable {
1072
+ id: string;
1073
+ client_id: string;
1074
+ redirect_uri: string;
1075
+ state: string | null;
1076
+ code_challenge: string;
1077
+ resource: string;
1078
+ status: Generated<OauthRequestStatus>;
1079
+ account_id: string | null;
1080
+ created_at: Generated<Date>;
1081
+ expires_at: Date;
1082
+ answered_at: Date | null;
1083
+ }
1084
+ /** A one-time authorization code, bound to its client, redirect, PKCE
1085
+ * challenge, resource and account. */
1086
+ interface OauthCodesTable {
1087
+ code_hash: string;
1088
+ client_id: string;
1089
+ account_id: string;
1090
+ redirect_uri: string;
1091
+ code_challenge: string;
1092
+ resource: string;
1093
+ /** The grant its one use made, so a replay can revoke it. */
1094
+ grant_id: string | null;
1095
+ created_at: Generated<Date>;
1096
+ expires_at: Date;
1097
+ used_at: Date | null;
1098
+ }
1099
+ /** What a person allowed one app to do: use the hosted MCP as them. */
1100
+ interface OauthGrantsTable {
1101
+ id: Generated<string>;
1102
+ account_id: string;
1103
+ client_id: string;
1104
+ scope: Generated<string>;
1105
+ resource: string;
1106
+ created_at: Generated<Date>;
1107
+ last_used_at: Date | null;
1108
+ revoked_at: Date | null;
1109
+ }
1110
+ type OauthTokenKind = "access" | "refresh";
1111
+ interface OauthTokensTable {
1112
+ token_hash: string;
1113
+ grant_id: string;
1114
+ kind: OauthTokenKind;
1115
+ created_at: Generated<Date>;
1116
+ expires_at: Date;
1117
+ }
1118
+ /** A refresh token a rotation replaced: presented again, it revokes the grant. */
1119
+ interface OauthRefreshRetiredTable {
1120
+ token_hash: string;
1121
+ grant_id: string;
1122
+ retired_at: Generated<Date>;
1123
+ }
1048
1124
  /** Accounts Sentinel's service key may touch: created by Sentinel, or the
1049
1125
  * owner opted in. */
1050
1126
  interface SentinelAccountsTable {
@@ -928,6 +928,12 @@ interface Database {
928
928
  account_balance_alerts: AccountBalanceAlertsTable;
929
929
  webhook_incident_alerts: WebhookIncidentAlertsTable;
930
930
  cli_device_logins: CliDeviceLoginsTable;
931
+ oauth_clients: OauthClientsTable;
932
+ oauth_requests: OauthRequestsTable;
933
+ oauth_codes: OauthCodesTable;
934
+ oauth_grants: OauthGrantsTable;
935
+ oauth_tokens: OauthTokensTable;
936
+ oauth_refresh_retired: OauthRefreshRetiredTable;
931
937
  sentinel_accounts: SentinelAccountsTable;
932
938
  waitlists: WaitlistsTable;
933
939
  waitlist_signups: WaitlistSignupsTable;
@@ -1030,13 +1036,17 @@ interface WebhookIncidentAlertsTable {
1030
1036
  resolved_at: Date | null;
1031
1037
  }
1032
1038
  type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
1033
- /** One browser sign-in attempt from `sl login`. Only the hash of the CLI's
1034
- * device code is stored; the key is minted when the CLI polls after approval. */
1039
+ /** The product that started a CLI sign-in; null is `sl login`. */
1040
+ type CliDeviceProduct = "sentinel";
1041
+ /** One browser sign-in attempt from `sl login` (or `sentinel login`). Only the
1042
+ * hash of the CLI's device code is stored; the session is opened when the CLI
1043
+ * polls after approval. */
1035
1044
  interface CliDeviceLoginsTable {
1036
1045
  id: Generated<string>;
1037
1046
  device_code_hash: string;
1038
1047
  user_code: string;
1039
1048
  client_name: string;
1049
+ product: CliDeviceProduct | null;
1040
1050
  status: Generated<CliDeviceLoginStatus>;
1041
1051
  account_id: string | null;
1042
1052
  key_name: string | null;
@@ -1045,6 +1055,72 @@ interface CliDeviceLoginsTable {
1045
1055
  approved_at: Date | null;
1046
1056
  consumed_at: Date | null;
1047
1057
  }
1058
+ /** An app that registered itself (RFC 7591). Public clients only: no secret. */
1059
+ interface OauthClientsTable {
1060
+ id: string;
1061
+ /** The app's own claim, validated at registration; shown quoted. */
1062
+ name: string;
1063
+ redirect_uris: string[];
1064
+ created_ip: string | null;
1065
+ created_at: Generated<Date>;
1066
+ /** Set when it first gets tokens; never-used clients are purged. */
1067
+ last_used_at: Date | null;
1068
+ }
1069
+ type OauthRequestStatus = "pending" | "approved" | "denied";
1070
+ /** One authorize request waiting for (or answered on) the consent page. */
1071
+ interface OauthRequestsTable {
1072
+ id: string;
1073
+ client_id: string;
1074
+ redirect_uri: string;
1075
+ state: string | null;
1076
+ code_challenge: string;
1077
+ resource: string;
1078
+ status: Generated<OauthRequestStatus>;
1079
+ account_id: string | null;
1080
+ created_at: Generated<Date>;
1081
+ expires_at: Date;
1082
+ answered_at: Date | null;
1083
+ }
1084
+ /** A one-time authorization code, bound to its client, redirect, PKCE
1085
+ * challenge, resource and account. */
1086
+ interface OauthCodesTable {
1087
+ code_hash: string;
1088
+ client_id: string;
1089
+ account_id: string;
1090
+ redirect_uri: string;
1091
+ code_challenge: string;
1092
+ resource: string;
1093
+ /** The grant its one use made, so a replay can revoke it. */
1094
+ grant_id: string | null;
1095
+ created_at: Generated<Date>;
1096
+ expires_at: Date;
1097
+ used_at: Date | null;
1098
+ }
1099
+ /** What a person allowed one app to do: use the hosted MCP as them. */
1100
+ interface OauthGrantsTable {
1101
+ id: Generated<string>;
1102
+ account_id: string;
1103
+ client_id: string;
1104
+ scope: Generated<string>;
1105
+ resource: string;
1106
+ created_at: Generated<Date>;
1107
+ last_used_at: Date | null;
1108
+ revoked_at: Date | null;
1109
+ }
1110
+ type OauthTokenKind = "access" | "refresh";
1111
+ interface OauthTokensTable {
1112
+ token_hash: string;
1113
+ grant_id: string;
1114
+ kind: OauthTokenKind;
1115
+ created_at: Generated<Date>;
1116
+ expires_at: Date;
1117
+ }
1118
+ /** A refresh token a rotation replaced: presented again, it revokes the grant. */
1119
+ interface OauthRefreshRetiredTable {
1120
+ token_hash: string;
1121
+ grant_id: string;
1122
+ retired_at: Generated<Date>;
1123
+ }
1048
1124
  /** Accounts Sentinel's service key may touch: created by Sentinel, or the
1049
1125
  * owner opted in. */
1050
1126
  interface SentinelAccountsTable {
@@ -928,6 +928,12 @@ interface Database {
928
928
  account_balance_alerts: AccountBalanceAlertsTable;
929
929
  webhook_incident_alerts: WebhookIncidentAlertsTable;
930
930
  cli_device_logins: CliDeviceLoginsTable;
931
+ oauth_clients: OauthClientsTable;
932
+ oauth_requests: OauthRequestsTable;
933
+ oauth_codes: OauthCodesTable;
934
+ oauth_grants: OauthGrantsTable;
935
+ oauth_tokens: OauthTokensTable;
936
+ oauth_refresh_retired: OauthRefreshRetiredTable;
931
937
  sentinel_accounts: SentinelAccountsTable;
932
938
  waitlists: WaitlistsTable;
933
939
  waitlist_signups: WaitlistSignupsTable;
@@ -1030,13 +1036,17 @@ interface WebhookIncidentAlertsTable {
1030
1036
  resolved_at: Date | null;
1031
1037
  }
1032
1038
  type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
1033
- /** One browser sign-in attempt from `sl login`. Only the hash of the CLI's
1034
- * device code is stored; the key is minted when the CLI polls after approval. */
1039
+ /** The product that started a CLI sign-in; null is `sl login`. */
1040
+ type CliDeviceProduct = "sentinel";
1041
+ /** One browser sign-in attempt from `sl login` (or `sentinel login`). Only the
1042
+ * hash of the CLI's device code is stored; the session is opened when the CLI
1043
+ * polls after approval. */
1035
1044
  interface CliDeviceLoginsTable {
1036
1045
  id: Generated<string>;
1037
1046
  device_code_hash: string;
1038
1047
  user_code: string;
1039
1048
  client_name: string;
1049
+ product: CliDeviceProduct | null;
1040
1050
  status: Generated<CliDeviceLoginStatus>;
1041
1051
  account_id: string | null;
1042
1052
  key_name: string | null;
@@ -1045,6 +1055,72 @@ interface CliDeviceLoginsTable {
1045
1055
  approved_at: Date | null;
1046
1056
  consumed_at: Date | null;
1047
1057
  }
1058
+ /** An app that registered itself (RFC 7591). Public clients only: no secret. */
1059
+ interface OauthClientsTable {
1060
+ id: string;
1061
+ /** The app's own claim, validated at registration; shown quoted. */
1062
+ name: string;
1063
+ redirect_uris: string[];
1064
+ created_ip: string | null;
1065
+ created_at: Generated<Date>;
1066
+ /** Set when it first gets tokens; never-used clients are purged. */
1067
+ last_used_at: Date | null;
1068
+ }
1069
+ type OauthRequestStatus = "pending" | "approved" | "denied";
1070
+ /** One authorize request waiting for (or answered on) the consent page. */
1071
+ interface OauthRequestsTable {
1072
+ id: string;
1073
+ client_id: string;
1074
+ redirect_uri: string;
1075
+ state: string | null;
1076
+ code_challenge: string;
1077
+ resource: string;
1078
+ status: Generated<OauthRequestStatus>;
1079
+ account_id: string | null;
1080
+ created_at: Generated<Date>;
1081
+ expires_at: Date;
1082
+ answered_at: Date | null;
1083
+ }
1084
+ /** A one-time authorization code, bound to its client, redirect, PKCE
1085
+ * challenge, resource and account. */
1086
+ interface OauthCodesTable {
1087
+ code_hash: string;
1088
+ client_id: string;
1089
+ account_id: string;
1090
+ redirect_uri: string;
1091
+ code_challenge: string;
1092
+ resource: string;
1093
+ /** The grant its one use made, so a replay can revoke it. */
1094
+ grant_id: string | null;
1095
+ created_at: Generated<Date>;
1096
+ expires_at: Date;
1097
+ used_at: Date | null;
1098
+ }
1099
+ /** What a person allowed one app to do: use the hosted MCP as them. */
1100
+ interface OauthGrantsTable {
1101
+ id: Generated<string>;
1102
+ account_id: string;
1103
+ client_id: string;
1104
+ scope: Generated<string>;
1105
+ resource: string;
1106
+ created_at: Generated<Date>;
1107
+ last_used_at: Date | null;
1108
+ revoked_at: Date | null;
1109
+ }
1110
+ type OauthTokenKind = "access" | "refresh";
1111
+ interface OauthTokensTable {
1112
+ token_hash: string;
1113
+ grant_id: string;
1114
+ kind: OauthTokenKind;
1115
+ created_at: Generated<Date>;
1116
+ expires_at: Date;
1117
+ }
1118
+ /** A refresh token a rotation replaced: presented again, it revokes the grant. */
1119
+ interface OauthRefreshRetiredTable {
1120
+ token_hash: string;
1121
+ grant_id: string;
1122
+ retired_at: Generated<Date>;
1123
+ }
1048
1124
  /** Accounts Sentinel's service key may touch: created by Sentinel, or the
1049
1125
  * owner opted in. */
1050
1126
  interface SentinelAccountsTable {
@@ -928,6 +928,12 @@ interface Database {
928
928
  account_balance_alerts: AccountBalanceAlertsTable;
929
929
  webhook_incident_alerts: WebhookIncidentAlertsTable;
930
930
  cli_device_logins: CliDeviceLoginsTable;
931
+ oauth_clients: OauthClientsTable;
932
+ oauth_requests: OauthRequestsTable;
933
+ oauth_codes: OauthCodesTable;
934
+ oauth_grants: OauthGrantsTable;
935
+ oauth_tokens: OauthTokensTable;
936
+ oauth_refresh_retired: OauthRefreshRetiredTable;
931
937
  sentinel_accounts: SentinelAccountsTable;
932
938
  waitlists: WaitlistsTable;
933
939
  waitlist_signups: WaitlistSignupsTable;
@@ -1030,13 +1036,17 @@ interface WebhookIncidentAlertsTable {
1030
1036
  resolved_at: Date | null;
1031
1037
  }
1032
1038
  type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
1033
- /** One browser sign-in attempt from `sl login`. Only the hash of the CLI's
1034
- * device code is stored; the key is minted when the CLI polls after approval. */
1039
+ /** The product that started a CLI sign-in; null is `sl login`. */
1040
+ type CliDeviceProduct = "sentinel";
1041
+ /** One browser sign-in attempt from `sl login` (or `sentinel login`). Only the
1042
+ * hash of the CLI's device code is stored; the session is opened when the CLI
1043
+ * polls after approval. */
1035
1044
  interface CliDeviceLoginsTable {
1036
1045
  id: Generated<string>;
1037
1046
  device_code_hash: string;
1038
1047
  user_code: string;
1039
1048
  client_name: string;
1049
+ product: CliDeviceProduct | null;
1040
1050
  status: Generated<CliDeviceLoginStatus>;
1041
1051
  account_id: string | null;
1042
1052
  key_name: string | null;
@@ -1045,6 +1055,72 @@ interface CliDeviceLoginsTable {
1045
1055
  approved_at: Date | null;
1046
1056
  consumed_at: Date | null;
1047
1057
  }
1058
+ /** An app that registered itself (RFC 7591). Public clients only: no secret. */
1059
+ interface OauthClientsTable {
1060
+ id: string;
1061
+ /** The app's own claim, validated at registration; shown quoted. */
1062
+ name: string;
1063
+ redirect_uris: string[];
1064
+ created_ip: string | null;
1065
+ created_at: Generated<Date>;
1066
+ /** Set when it first gets tokens; never-used clients are purged. */
1067
+ last_used_at: Date | null;
1068
+ }
1069
+ type OauthRequestStatus = "pending" | "approved" | "denied";
1070
+ /** One authorize request waiting for (or answered on) the consent page. */
1071
+ interface OauthRequestsTable {
1072
+ id: string;
1073
+ client_id: string;
1074
+ redirect_uri: string;
1075
+ state: string | null;
1076
+ code_challenge: string;
1077
+ resource: string;
1078
+ status: Generated<OauthRequestStatus>;
1079
+ account_id: string | null;
1080
+ created_at: Generated<Date>;
1081
+ expires_at: Date;
1082
+ answered_at: Date | null;
1083
+ }
1084
+ /** A one-time authorization code, bound to its client, redirect, PKCE
1085
+ * challenge, resource and account. */
1086
+ interface OauthCodesTable {
1087
+ code_hash: string;
1088
+ client_id: string;
1089
+ account_id: string;
1090
+ redirect_uri: string;
1091
+ code_challenge: string;
1092
+ resource: string;
1093
+ /** The grant its one use made, so a replay can revoke it. */
1094
+ grant_id: string | null;
1095
+ created_at: Generated<Date>;
1096
+ expires_at: Date;
1097
+ used_at: Date | null;
1098
+ }
1099
+ /** What a person allowed one app to do: use the hosted MCP as them. */
1100
+ interface OauthGrantsTable {
1101
+ id: Generated<string>;
1102
+ account_id: string;
1103
+ client_id: string;
1104
+ scope: Generated<string>;
1105
+ resource: string;
1106
+ created_at: Generated<Date>;
1107
+ last_used_at: Date | null;
1108
+ revoked_at: Date | null;
1109
+ }
1110
+ type OauthTokenKind = "access" | "refresh";
1111
+ interface OauthTokensTable {
1112
+ token_hash: string;
1113
+ grant_id: string;
1114
+ kind: OauthTokenKind;
1115
+ created_at: Generated<Date>;
1116
+ expires_at: Date;
1117
+ }
1118
+ /** A refresh token a rotation replaced: presented again, it revokes the grant. */
1119
+ interface OauthRefreshRetiredTable {
1120
+ token_hash: string;
1121
+ grant_id: string;
1122
+ retired_at: Generated<Date>;
1123
+ }
1048
1124
  /** Accounts Sentinel's service key may touch: created by Sentinel, or the
1049
1125
  * owner opted in. */
1050
1126
  interface SentinelAccountsTable {
@@ -928,6 +928,12 @@ interface Database {
928
928
  account_balance_alerts: AccountBalanceAlertsTable;
929
929
  webhook_incident_alerts: WebhookIncidentAlertsTable;
930
930
  cli_device_logins: CliDeviceLoginsTable;
931
+ oauth_clients: OauthClientsTable;
932
+ oauth_requests: OauthRequestsTable;
933
+ oauth_codes: OauthCodesTable;
934
+ oauth_grants: OauthGrantsTable;
935
+ oauth_tokens: OauthTokensTable;
936
+ oauth_refresh_retired: OauthRefreshRetiredTable;
931
937
  sentinel_accounts: SentinelAccountsTable;
932
938
  waitlists: WaitlistsTable;
933
939
  waitlist_signups: WaitlistSignupsTable;
@@ -1030,13 +1036,17 @@ interface WebhookIncidentAlertsTable {
1030
1036
  resolved_at: Date | null;
1031
1037
  }
1032
1038
  type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
1033
- /** One browser sign-in attempt from `sl login`. Only the hash of the CLI's
1034
- * device code is stored; the key is minted when the CLI polls after approval. */
1039
+ /** The product that started a CLI sign-in; null is `sl login`. */
1040
+ type CliDeviceProduct = "sentinel";
1041
+ /** One browser sign-in attempt from `sl login` (or `sentinel login`). Only the
1042
+ * hash of the CLI's device code is stored; the session is opened when the CLI
1043
+ * polls after approval. */
1035
1044
  interface CliDeviceLoginsTable {
1036
1045
  id: Generated<string>;
1037
1046
  device_code_hash: string;
1038
1047
  user_code: string;
1039
1048
  client_name: string;
1049
+ product: CliDeviceProduct | null;
1040
1050
  status: Generated<CliDeviceLoginStatus>;
1041
1051
  account_id: string | null;
1042
1052
  key_name: string | null;
@@ -1045,6 +1055,72 @@ interface CliDeviceLoginsTable {
1045
1055
  approved_at: Date | null;
1046
1056
  consumed_at: Date | null;
1047
1057
  }
1058
+ /** An app that registered itself (RFC 7591). Public clients only: no secret. */
1059
+ interface OauthClientsTable {
1060
+ id: string;
1061
+ /** The app's own claim, validated at registration; shown quoted. */
1062
+ name: string;
1063
+ redirect_uris: string[];
1064
+ created_ip: string | null;
1065
+ created_at: Generated<Date>;
1066
+ /** Set when it first gets tokens; never-used clients are purged. */
1067
+ last_used_at: Date | null;
1068
+ }
1069
+ type OauthRequestStatus = "pending" | "approved" | "denied";
1070
+ /** One authorize request waiting for (or answered on) the consent page. */
1071
+ interface OauthRequestsTable {
1072
+ id: string;
1073
+ client_id: string;
1074
+ redirect_uri: string;
1075
+ state: string | null;
1076
+ code_challenge: string;
1077
+ resource: string;
1078
+ status: Generated<OauthRequestStatus>;
1079
+ account_id: string | null;
1080
+ created_at: Generated<Date>;
1081
+ expires_at: Date;
1082
+ answered_at: Date | null;
1083
+ }
1084
+ /** A one-time authorization code, bound to its client, redirect, PKCE
1085
+ * challenge, resource and account. */
1086
+ interface OauthCodesTable {
1087
+ code_hash: string;
1088
+ client_id: string;
1089
+ account_id: string;
1090
+ redirect_uri: string;
1091
+ code_challenge: string;
1092
+ resource: string;
1093
+ /** The grant its one use made, so a replay can revoke it. */
1094
+ grant_id: string | null;
1095
+ created_at: Generated<Date>;
1096
+ expires_at: Date;
1097
+ used_at: Date | null;
1098
+ }
1099
+ /** What a person allowed one app to do: use the hosted MCP as them. */
1100
+ interface OauthGrantsTable {
1101
+ id: Generated<string>;
1102
+ account_id: string;
1103
+ client_id: string;
1104
+ scope: Generated<string>;
1105
+ resource: string;
1106
+ created_at: Generated<Date>;
1107
+ last_used_at: Date | null;
1108
+ revoked_at: Date | null;
1109
+ }
1110
+ type OauthTokenKind = "access" | "refresh";
1111
+ interface OauthTokensTable {
1112
+ token_hash: string;
1113
+ grant_id: string;
1114
+ kind: OauthTokenKind;
1115
+ created_at: Generated<Date>;
1116
+ expires_at: Date;
1117
+ }
1118
+ /** A refresh token a rotation replaced: presented again, it revokes the grant. */
1119
+ interface OauthRefreshRetiredTable {
1120
+ token_hash: string;
1121
+ grant_id: string;
1122
+ retired_at: Generated<Date>;
1123
+ }
1048
1124
  /** Accounts Sentinel's service key may touch: created by Sentinel, or the
1049
1125
  * owner opted in. */
1050
1126
  interface SentinelAccountsTable {
@@ -928,6 +928,12 @@ interface Database {
928
928
  account_balance_alerts: AccountBalanceAlertsTable;
929
929
  webhook_incident_alerts: WebhookIncidentAlertsTable;
930
930
  cli_device_logins: CliDeviceLoginsTable;
931
+ oauth_clients: OauthClientsTable;
932
+ oauth_requests: OauthRequestsTable;
933
+ oauth_codes: OauthCodesTable;
934
+ oauth_grants: OauthGrantsTable;
935
+ oauth_tokens: OauthTokensTable;
936
+ oauth_refresh_retired: OauthRefreshRetiredTable;
931
937
  sentinel_accounts: SentinelAccountsTable;
932
938
  waitlists: WaitlistsTable;
933
939
  waitlist_signups: WaitlistSignupsTable;
@@ -1030,13 +1036,17 @@ interface WebhookIncidentAlertsTable {
1030
1036
  resolved_at: Date | null;
1031
1037
  }
1032
1038
  type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
1033
- /** One browser sign-in attempt from `sl login`. Only the hash of the CLI's
1034
- * device code is stored; the key is minted when the CLI polls after approval. */
1039
+ /** The product that started a CLI sign-in; null is `sl login`. */
1040
+ type CliDeviceProduct = "sentinel";
1041
+ /** One browser sign-in attempt from `sl login` (or `sentinel login`). Only the
1042
+ * hash of the CLI's device code is stored; the session is opened when the CLI
1043
+ * polls after approval. */
1035
1044
  interface CliDeviceLoginsTable {
1036
1045
  id: Generated<string>;
1037
1046
  device_code_hash: string;
1038
1047
  user_code: string;
1039
1048
  client_name: string;
1049
+ product: CliDeviceProduct | null;
1040
1050
  status: Generated<CliDeviceLoginStatus>;
1041
1051
  account_id: string | null;
1042
1052
  key_name: string | null;
@@ -1045,6 +1055,72 @@ interface CliDeviceLoginsTable {
1045
1055
  approved_at: Date | null;
1046
1056
  consumed_at: Date | null;
1047
1057
  }
1058
+ /** An app that registered itself (RFC 7591). Public clients only: no secret. */
1059
+ interface OauthClientsTable {
1060
+ id: string;
1061
+ /** The app's own claim, validated at registration; shown quoted. */
1062
+ name: string;
1063
+ redirect_uris: string[];
1064
+ created_ip: string | null;
1065
+ created_at: Generated<Date>;
1066
+ /** Set when it first gets tokens; never-used clients are purged. */
1067
+ last_used_at: Date | null;
1068
+ }
1069
+ type OauthRequestStatus = "pending" | "approved" | "denied";
1070
+ /** One authorize request waiting for (or answered on) the consent page. */
1071
+ interface OauthRequestsTable {
1072
+ id: string;
1073
+ client_id: string;
1074
+ redirect_uri: string;
1075
+ state: string | null;
1076
+ code_challenge: string;
1077
+ resource: string;
1078
+ status: Generated<OauthRequestStatus>;
1079
+ account_id: string | null;
1080
+ created_at: Generated<Date>;
1081
+ expires_at: Date;
1082
+ answered_at: Date | null;
1083
+ }
1084
+ /** A one-time authorization code, bound to its client, redirect, PKCE
1085
+ * challenge, resource and account. */
1086
+ interface OauthCodesTable {
1087
+ code_hash: string;
1088
+ client_id: string;
1089
+ account_id: string;
1090
+ redirect_uri: string;
1091
+ code_challenge: string;
1092
+ resource: string;
1093
+ /** The grant its one use made, so a replay can revoke it. */
1094
+ grant_id: string | null;
1095
+ created_at: Generated<Date>;
1096
+ expires_at: Date;
1097
+ used_at: Date | null;
1098
+ }
1099
+ /** What a person allowed one app to do: use the hosted MCP as them. */
1100
+ interface OauthGrantsTable {
1101
+ id: Generated<string>;
1102
+ account_id: string;
1103
+ client_id: string;
1104
+ scope: Generated<string>;
1105
+ resource: string;
1106
+ created_at: Generated<Date>;
1107
+ last_used_at: Date | null;
1108
+ revoked_at: Date | null;
1109
+ }
1110
+ type OauthTokenKind = "access" | "refresh";
1111
+ interface OauthTokensTable {
1112
+ token_hash: string;
1113
+ grant_id: string;
1114
+ kind: OauthTokenKind;
1115
+ created_at: Generated<Date>;
1116
+ expires_at: Date;
1117
+ }
1118
+ /** A refresh token a rotation replaced: presented again, it revokes the grant. */
1119
+ interface OauthRefreshRetiredTable {
1120
+ token_hash: string;
1121
+ grant_id: string;
1122
+ retired_at: Generated<Date>;
1123
+ }
1048
1124
  /** Accounts Sentinel's service key may touch: created by Sentinel, or the
1049
1125
  * owner opted in. */
1050
1126
  interface SentinelAccountsTable {