@agent-native/core 0.203.2-nightly-20261007213109 → 0.204.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/a2a/handlers.js +57 -1
- package/dist/a2a/server.js +37 -1
- package/dist/action.d.ts +1 -0
- package/dist/action.js +26 -3
- package/dist/agent/contain-principal.d.ts +9 -0
- package/dist/agent/contain-principal.js +53 -0
- package/dist/agent/production-agent.js +32 -2
- package/dist/agent/run-manager.js +14 -2
- package/dist/agent/run-store.js +66 -12
- package/dist/audit/actions/export-audit-events.d.ts +1 -1
- package/dist/audit/actions/export-audit-events.js +2 -2
- package/dist/audit/actions/export-audit-ocsf.d.ts +11 -0
- package/dist/audit/actions/export-audit-ocsf.js +183 -0
- package/dist/audit/actions/list-audit-events.d.ts +1 -1
- package/dist/audit/actions/list-audit-events.js +3 -3
- package/dist/audit/config.d.ts +1 -1
- package/dist/audit/config.js +5 -1
- package/dist/audit/index.d.ts +1 -0
- package/dist/audit/index.js +1 -0
- package/dist/audit/ocsf.d.ts +70 -0
- package/dist/audit/ocsf.js +228 -0
- package/dist/audit/record.js +1 -1
- package/dist/audit/store.js +9 -2
- package/dist/audit/types.d.ts +12 -1
- package/dist/cli/agent.js +2 -11
- package/dist/cli/connect.js +7 -2
- package/dist/client/use-db-sync.d.ts +13 -0
- package/dist/client/use-db-sync.js +22 -1
- package/dist/coding-tools/run-code.js +22 -1
- package/dist/coding-tools/sandbox/local-child-process-adapter.js +20 -0
- package/dist/collab/client.js +36 -3
- package/dist/collab/routes.d.ts +9 -4
- package/dist/collab/routes.js +15 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +15 -8
- package/dist/deploy/workspace-deploy.js +88 -13
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/file-upload/builder.js +18 -4
- package/dist/framework-tools.js +3 -0
- package/dist/identity/rekey.js +6 -0
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/localization/core-messages/supplemental/ar-SA.js +15 -0
- package/dist/localization/core-messages/supplemental/de-DE.js +15 -0
- package/dist/localization/core-messages/supplemental/en-US.js +15 -0
- package/dist/localization/core-messages/supplemental/es-ES.js +15 -0
- package/dist/localization/core-messages/supplemental/fr-FR.js +15 -0
- package/dist/localization/core-messages/supplemental/hi-IN.js +15 -0
- package/dist/localization/core-messages/supplemental/ja-JP.js +15 -0
- package/dist/localization/core-messages/supplemental/ko-KR.js +15 -0
- package/dist/localization/core-messages/supplemental/pt-BR.js +15 -0
- package/dist/localization/core-messages/supplemental/zh-CN.js +15 -0
- package/dist/localization/core-messages/supplemental/zh-TW.js +15 -0
- package/dist/localization/mcp-settings-messages.d.ts +15 -0
- package/dist/mcp/actions/create-org-service-token.d.ts +8 -0
- package/dist/mcp/actions/create-org-service-token.js +93 -4
- package/dist/mcp/actions/list-org-service-tokens.d.ts +2 -0
- package/dist/mcp/actions/list-org-service-tokens.js +36 -8
- package/dist/mcp/actions/service-principal-input.d.ts +48 -0
- package/dist/mcp/actions/service-principal-input.js +102 -0
- package/dist/mcp/actions/set-service-principal-lifecycle.d.ts +15 -0
- package/dist/mcp/actions/set-service-principal-lifecycle.js +150 -0
- package/dist/mcp/actions/set-service-principal-policy.d.ts +14 -0
- package/dist/mcp/actions/set-service-principal-policy.js +105 -0
- package/dist/mcp/build-server.js +117 -13
- package/dist/mcp/connect-route.js +116 -4
- package/dist/mcp/connect-store.d.ts +7 -0
- package/dist/mcp/connect-store.js +21 -14
- package/dist/mcp-client/oauth-routes.js +2 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +7 -7
- package/dist/org/index.d.ts +2 -2
- package/dist/org/service-principal-guard.d.ts +64 -0
- package/dist/org/service-principal-guard.js +140 -0
- package/dist/org/service-principal-policy.d.ts +104 -0
- package/dist/org/service-principal-policy.js +272 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
- package/dist/provider-api/actions/provider-api.d.ts +13 -13
- package/dist/scripts/dev/index.js +2 -8
- package/dist/scripts/parse-args.d.ts +7 -0
- package/dist/scripts/parse-args.js +76 -0
- package/dist/scripts/utils.d.ts +1 -1
- package/dist/scripts/utils.js +1 -1
- package/dist/secrets/routes.d.ts +11 -11
- package/dist/server/action-discovery.js +16 -42
- package/dist/server/agent-chat/script-entries.js +3 -8
- package/dist/server/agent-chat-plugin.js +8 -42
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/auth.js +5 -2
- package/dist/server/core-routes-plugin.js +25 -6
- package/dist/server/google-oauth.js +8 -4
- package/dist/server/identity-sso.js +2 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/poll.d.ts +9 -0
- package/dist/server/poll.js +86 -7
- package/dist/server/query-echo-safe-redirect.d.ts +10 -0
- package/dist/server/query-echo-safe-redirect.js +102 -0
- package/dist/server/release-schema.js +4 -0
- package/dist/server/workspace-provider-oauth.js +2 -1
- package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +1 -0
- package/dist/templates/default/.agents/skills/actions/references/action-fields.md +1 -0
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +24 -25
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +33 -0
- package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -0
- package/dist/triggers/actions/manage-automation.d.ts +7 -7
- package/dist/vite/client.js +1 -0
- package/docs/content/audit-log.mdx +15 -0
- package/docs/content/external-agents-catalog.mdx +19 -0
- package/docs/content/http-api.mdx +21 -2
- package/docs/content/pr-visual-recap.mdx +3 -1
- package/docs/content/template-clips-embed.mdx +1 -1
- package/docs/content/turn-into-app.mdx +118 -0
- package/package.json +4 -4
- package/src/templates/chat/.agents/skills/actions/references/action-fields.md +1 -0
- package/src/templates/default/.agents/skills/actions/references/action-fields.md +1 -0
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +24 -25
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +33 -0
- package/src/templates/headless/.agents/skills/actions/references/action-fields.md +1 -0
- package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -0
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "Could not create token.",
|
|
55
55
|
networkError: "Network error. Please try again.",
|
|
56
56
|
urlTitle: "Your MCP URL",
|
|
57
|
+
servicePrincipals: "Service principals",
|
|
58
|
+
principalUngoverned: "Ungoverned",
|
|
59
|
+
principalActive: "Active",
|
|
60
|
+
principalSuspended: "Suspended",
|
|
61
|
+
principalRetired: "Retired",
|
|
62
|
+
principalUngovernedHint: "No owner or action grant is set.",
|
|
63
|
+
principalOwner: "Owner",
|
|
64
|
+
principalRisk: "Risk",
|
|
65
|
+
riskLow: "low",
|
|
66
|
+
riskMedium: "medium",
|
|
67
|
+
riskHigh: "high",
|
|
68
|
+
suspend: "Suspend",
|
|
69
|
+
resume: "Resume",
|
|
70
|
+
couldNotUpdatePrincipal: "Could not update the service principal.",
|
|
71
|
+
containmentIncomplete: "Updated, but some runs or tokens could not be stopped. Try again.",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "No se pudo crear el token.",
|
|
55
55
|
networkError: "Error de red. Inténtalo de nuevo.",
|
|
56
56
|
urlTitle: "Tu URL de MCP",
|
|
57
|
+
servicePrincipals: "Principales de servicio",
|
|
58
|
+
principalUngoverned: "Sin gobernanza",
|
|
59
|
+
principalActive: "Activo",
|
|
60
|
+
principalSuspended: "Suspendido",
|
|
61
|
+
principalRetired: "Retirado",
|
|
62
|
+
principalUngovernedHint: "No hay propietario ni permisos de acciones definidos.",
|
|
63
|
+
principalOwner: "Propietario",
|
|
64
|
+
principalRisk: "Riesgo",
|
|
65
|
+
riskLow: "bajo",
|
|
66
|
+
riskMedium: "medio",
|
|
67
|
+
riskHigh: "alto",
|
|
68
|
+
suspend: "Suspender",
|
|
69
|
+
resume: "Reanudar",
|
|
70
|
+
couldNotUpdatePrincipal: "No se pudo actualizar el principal de servicio.",
|
|
71
|
+
containmentIncomplete: "Actualizado, pero no se pudieron detener algunas ejecuciones o tokens. Inténtalo de nuevo.",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "Impossible de créer le jeton.",
|
|
55
55
|
networkError: "Erreur réseau. Réessayez.",
|
|
56
56
|
urlTitle: "Votre URL MCP",
|
|
57
|
+
servicePrincipals: "Principaux de service",
|
|
58
|
+
principalUngoverned: "Non gouverné",
|
|
59
|
+
principalActive: "Actif",
|
|
60
|
+
principalSuspended: "Suspendu",
|
|
61
|
+
principalRetired: "Retiré",
|
|
62
|
+
principalUngovernedHint: "Aucun propriétaire ni autorisation d'actions n'est défini.",
|
|
63
|
+
principalOwner: "Propriétaire",
|
|
64
|
+
principalRisk: "Risque",
|
|
65
|
+
riskLow: "faible",
|
|
66
|
+
riskMedium: "moyen",
|
|
67
|
+
riskHigh: "élevé",
|
|
68
|
+
suspend: "Suspendre",
|
|
69
|
+
resume: "Reprendre",
|
|
70
|
+
couldNotUpdatePrincipal: "Impossible de mettre à jour le principal de service.",
|
|
71
|
+
containmentIncomplete: "Mis à jour, mais certaines exécutions ou certains jetons n'ont pas pu être arrêtés. Réessayez.",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "Token बनाया नहीं जा सका।",
|
|
55
55
|
networkError: "Network error. फिर से कोशिश करें।",
|
|
56
56
|
urlTitle: "आपका MCP URL",
|
|
57
|
+
servicePrincipals: "सर्विस प्रिंसिपल",
|
|
58
|
+
principalUngoverned: "अनियंत्रित",
|
|
59
|
+
principalActive: "सक्रिय",
|
|
60
|
+
principalSuspended: "निलंबित",
|
|
61
|
+
principalRetired: "सेवानिवृत्त",
|
|
62
|
+
principalUngovernedHint: "कोई स्वामी या कार्रवाई अनुमति सेट नहीं है।",
|
|
63
|
+
principalOwner: "स्वामी",
|
|
64
|
+
principalRisk: "जोखिम",
|
|
65
|
+
riskLow: "कम",
|
|
66
|
+
riskMedium: "मध्यम",
|
|
67
|
+
riskHigh: "उच्च",
|
|
68
|
+
suspend: "निलंबित करें",
|
|
69
|
+
resume: "फिर शुरू करें",
|
|
70
|
+
couldNotUpdatePrincipal: "सर्विस प्रिंसिपल अपडेट नहीं किया जा सका।",
|
|
71
|
+
containmentIncomplete: "अपडेट हो गया, लेकिन कुछ रन या टोकन रोके नहीं जा सके। फिर से प्रयास करें।",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "トークンを作成できませんでした。",
|
|
55
55
|
networkError: "ネットワークエラーです。もう一度お試しください。",
|
|
56
56
|
urlTitle: "MCP URL",
|
|
57
|
+
servicePrincipals: "サービスプリンシパル",
|
|
58
|
+
principalUngoverned: "未管理",
|
|
59
|
+
principalActive: "有効",
|
|
60
|
+
principalSuspended: "一時停止中",
|
|
61
|
+
principalRetired: "廃止済み",
|
|
62
|
+
principalUngovernedHint: "オーナーも操作の許可も設定されていません。",
|
|
63
|
+
principalOwner: "オーナー",
|
|
64
|
+
principalRisk: "リスク",
|
|
65
|
+
riskLow: "低",
|
|
66
|
+
riskMedium: "中",
|
|
67
|
+
riskHigh: "高",
|
|
68
|
+
suspend: "一時停止",
|
|
69
|
+
resume: "再開",
|
|
70
|
+
couldNotUpdatePrincipal: "サービスプリンシパルを更新できませんでした。",
|
|
71
|
+
containmentIncomplete: "更新しましたが、停止できない実行またはトークンがあります。もう一度お試しください。",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "토큰을 생성할 수 없습니다.",
|
|
55
55
|
networkError: "네트워크 오류입니다. 다시 시도하세요.",
|
|
56
56
|
urlTitle: "MCP URL",
|
|
57
|
+
servicePrincipals: "서비스 주체",
|
|
58
|
+
principalUngoverned: "미관리",
|
|
59
|
+
principalActive: "활성",
|
|
60
|
+
principalSuspended: "일시 중지됨",
|
|
61
|
+
principalRetired: "폐기됨",
|
|
62
|
+
principalUngovernedHint: "소유자 또는 작업 권한이 설정되지 않았습니다.",
|
|
63
|
+
principalOwner: "소유자",
|
|
64
|
+
principalRisk: "위험",
|
|
65
|
+
riskLow: "낮음",
|
|
66
|
+
riskMedium: "보통",
|
|
67
|
+
riskHigh: "높음",
|
|
68
|
+
suspend: "일시 중지",
|
|
69
|
+
resume: "재개",
|
|
70
|
+
couldNotUpdatePrincipal: "서비스 주체를 업데이트할 수 없습니다.",
|
|
71
|
+
containmentIncomplete: "업데이트했지만 일부 실행 또는 토큰을 중지하지 못했습니다. 다시 시도하세요.",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "Não foi possível criar o token.",
|
|
55
55
|
networkError: "Erro de rede. Tente novamente.",
|
|
56
56
|
urlTitle: "Sua URL MCP",
|
|
57
|
+
servicePrincipals: "Principais de serviço",
|
|
58
|
+
principalUngoverned: "Sem governança",
|
|
59
|
+
principalActive: "Ativo",
|
|
60
|
+
principalSuspended: "Suspenso",
|
|
61
|
+
principalRetired: "Desativado",
|
|
62
|
+
principalUngovernedHint: "Nenhum proprietário ou permissão de ações definido.",
|
|
63
|
+
principalOwner: "Proprietário",
|
|
64
|
+
principalRisk: "Risco",
|
|
65
|
+
riskLow: "baixo",
|
|
66
|
+
riskMedium: "médio",
|
|
67
|
+
riskHigh: "alto",
|
|
68
|
+
suspend: "Suspender",
|
|
69
|
+
resume: "Retomar",
|
|
70
|
+
couldNotUpdatePrincipal: "Não foi possível atualizar o principal de serviço.",
|
|
71
|
+
containmentIncomplete: "Atualizado, mas algumas execuções ou tokens não puderam ser interrompidos. Tente novamente.",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "无法创建令牌。",
|
|
55
55
|
networkError: "网络错误。请重试。",
|
|
56
56
|
urlTitle: "你的 MCP URL",
|
|
57
|
+
servicePrincipals: "服务主体",
|
|
58
|
+
principalUngoverned: "未治理",
|
|
59
|
+
principalActive: "活动",
|
|
60
|
+
principalSuspended: "已暂停",
|
|
61
|
+
principalRetired: "已停用",
|
|
62
|
+
principalUngovernedHint: "未设置所有者或操作授权。",
|
|
63
|
+
principalOwner: "所有者",
|
|
64
|
+
principalRisk: "风险",
|
|
65
|
+
riskLow: "低",
|
|
66
|
+
riskMedium: "中",
|
|
67
|
+
riskHigh: "高",
|
|
68
|
+
suspend: "暂停",
|
|
69
|
+
resume: "恢复",
|
|
70
|
+
couldNotUpdatePrincipal: "无法更新服务主体。",
|
|
71
|
+
containmentIncomplete: "已更新,但部分运行或令牌无法停止。请重试。",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -54,6 +54,21 @@ export const mcpConnectMessages = {
|
|
|
54
54
|
couldNotCreate: "無法建立權杖。",
|
|
55
55
|
networkError: "網路錯誤。請再試一次。",
|
|
56
56
|
urlTitle: "你的 MCP URL",
|
|
57
|
+
servicePrincipals: "服務主體",
|
|
58
|
+
principalUngoverned: "未治理",
|
|
59
|
+
principalActive: "啟用中",
|
|
60
|
+
principalSuspended: "已暫停",
|
|
61
|
+
principalRetired: "已停用",
|
|
62
|
+
principalUngovernedHint: "尚未設定擁有者或動作授權。",
|
|
63
|
+
principalOwner: "擁有者",
|
|
64
|
+
principalRisk: "風險",
|
|
65
|
+
riskLow: "低",
|
|
66
|
+
riskMedium: "中",
|
|
67
|
+
riskHigh: "高",
|
|
68
|
+
suspend: "暫停",
|
|
69
|
+
resume: "恢復",
|
|
70
|
+
couldNotUpdatePrincipal: "無法更新服務主體。",
|
|
71
|
+
containmentIncomplete: "已更新,但部分執行或權杖無法停止。請重試。",
|
|
57
72
|
};
|
|
58
73
|
export const mcpSettingsMessages = {
|
|
59
74
|
mcpTitle: "MCP",
|
|
@@ -41,6 +41,21 @@ export interface McpConnectMessages {
|
|
|
41
41
|
couldNotCreate: string;
|
|
42
42
|
networkError: string;
|
|
43
43
|
urlTitle: string;
|
|
44
|
+
servicePrincipals: string;
|
|
45
|
+
principalUngoverned: string;
|
|
46
|
+
principalActive: string;
|
|
47
|
+
principalSuspended: string;
|
|
48
|
+
principalRetired: string;
|
|
49
|
+
principalUngovernedHint: string;
|
|
50
|
+
principalOwner: string;
|
|
51
|
+
principalRisk: string;
|
|
52
|
+
riskLow: string;
|
|
53
|
+
riskMedium: string;
|
|
54
|
+
riskHigh: string;
|
|
55
|
+
suspend: string;
|
|
56
|
+
resume: string;
|
|
57
|
+
couldNotUpdatePrincipal: string;
|
|
58
|
+
containmentIncomplete: string;
|
|
44
59
|
}
|
|
45
60
|
export declare const MCP_CONNECT_MESSAGES: Record<BuiltinLocaleCode, McpConnectMessages>;
|
|
46
61
|
export interface McpSettingsMessages {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
declare const _default: import("../../action.js").ActionDefinition<{
|
|
2
2
|
name: string;
|
|
3
3
|
ttlDays?: number;
|
|
4
|
+
ownerEmail?: string;
|
|
5
|
+
team?: string;
|
|
6
|
+
riskTier?: "high" | "low" | "medium";
|
|
7
|
+
purpose?: string;
|
|
8
|
+
allowedActions?: string[];
|
|
4
9
|
}, {
|
|
5
10
|
token: string;
|
|
6
11
|
id: string;
|
|
@@ -8,6 +13,9 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
8
13
|
serviceEmail: string;
|
|
9
14
|
orgId: string;
|
|
10
15
|
ttlDays: number;
|
|
16
|
+
ownerEmail: string;
|
|
17
|
+
riskTier: "high" | "low" | "medium";
|
|
18
|
+
allowedActions: string[];
|
|
11
19
|
note: string;
|
|
12
20
|
}>;
|
|
13
21
|
export default _default;
|
|
@@ -14,17 +14,27 @@
|
|
|
14
14
|
* never a prompt-injection target.
|
|
15
15
|
* - Revocable via `revoke-org-service-token` — same `revoked_at` gate the
|
|
16
16
|
* personal-token revocation path uses.
|
|
17
|
+
*
|
|
18
|
+
* GOVERNANCE: every mint leaves the principal governed. A name with no policy
|
|
19
|
+
* row gets one (owner defaults to the creating admin, riskTier medium,
|
|
20
|
+
* allowedActions null = unrestricted); an existing policy only changes the
|
|
21
|
+
* fields passed explicitly. A suspended or retired name is refused, since a
|
|
22
|
+
* token minted for it could never authenticate.
|
|
17
23
|
*/
|
|
18
24
|
import { z } from "zod";
|
|
19
25
|
import { defineAction } from "../../action.js";
|
|
26
|
+
import { orgAdminAudit } from "../../audit/org-admin.js";
|
|
27
|
+
import { getServicePrincipalPolicy, upsertServicePrincipalPolicy, } from "../../org/service-principal-policy.js";
|
|
20
28
|
import { getAppProductionUrl } from "../../server/app-url.js";
|
|
21
29
|
import { CREDENTIAL_MEMBERSHIP_UNAVAILABLE_MESSAGE } from "../../server/credential-membership-unavailable.js";
|
|
22
30
|
import { getRequestContext } from "../../server/request-context.js";
|
|
23
31
|
import { mintOrgServiceToken } from "../connect-route.js";
|
|
32
|
+
import { MAX_SERVICE_TOKEN_TTL_DAYS, revokeOrgServiceToken, } from "../connect-store.js";
|
|
24
33
|
import { McpCredentialIssuanceError } from "../credential-issuance.js";
|
|
34
|
+
import { allowedActionsSchema, assertOwnerIsOrgMember, normalizeAllowedActions, ownerEmailSchema, parseServiceName, purposeSchema, riskTierSchema, teamSchema, } from "./service-principal-input.js";
|
|
25
35
|
import { requireServiceTokenCaller, SERVICE_TOKEN_MANAGE_FORBIDDEN_MESSAGE, ServiceTokenError, } from "./service-token-access.js";
|
|
26
36
|
export default defineAction({
|
|
27
|
-
description: "Create a named, org-scoped service token (for CI like PR Visual Recap's PLAN_RECAP_TOKEN). The token acts as a service principal owned by the organization, not a person. Org owner/admin only. The token value is returned ONCE and never stored — copy it immediately.",
|
|
37
|
+
description: "Create a named, org-scoped service token (for CI like PR Visual Recap's PLAN_RECAP_TOKEN). The token acts as a service principal owned by the organization, not a person. Org owner/admin only. The token value is returned ONCE and never stored — copy it immediately. The principal is created governed: owner defaults to you, risk tier to medium, allowedActions to null (unrestricted); pass ownerEmail/team/riskTier/purpose/allowedActions to set them at birth. Refused when the name is suspended or retired.",
|
|
28
38
|
schema: z.object({
|
|
29
39
|
name: z
|
|
30
40
|
.string()
|
|
@@ -35,17 +45,57 @@ export default defineAction({
|
|
|
35
45
|
.number()
|
|
36
46
|
.int()
|
|
37
47
|
.min(1)
|
|
38
|
-
.max(
|
|
48
|
+
.max(MAX_SERVICE_TOKEN_TTL_DAYS)
|
|
39
49
|
.optional()
|
|
40
|
-
.describe("Token lifetime in days (1-
|
|
50
|
+
.describe("Token lifetime in days (1-3650, default 365)"),
|
|
51
|
+
ownerEmail: ownerEmailSchema.optional(),
|
|
52
|
+
team: teamSchema.optional(),
|
|
53
|
+
riskTier: riskTierSchema.optional(),
|
|
54
|
+
purpose: purposeSchema.optional(),
|
|
55
|
+
allowedActions: allowedActionsSchema.nullable().optional(),
|
|
41
56
|
}),
|
|
57
|
+
requiresAuth: true,
|
|
42
58
|
toolCallable: false,
|
|
59
|
+
audit: orgAdminAudit({
|
|
60
|
+
targetType: "service-principal",
|
|
61
|
+
targetId: (_args, result) => result?.serviceName,
|
|
62
|
+
recordInputs: false,
|
|
63
|
+
summary: () => "Created or re-minted an organization service token.",
|
|
64
|
+
}),
|
|
43
65
|
run: async (args, ctx) => {
|
|
44
66
|
const caller = await requireServiceTokenCaller({
|
|
45
67
|
userEmail: ctx?.userEmail,
|
|
46
68
|
orgId: ctx?.orgId,
|
|
47
69
|
level: "manage",
|
|
48
70
|
});
|
|
71
|
+
const serviceName = parseServiceName(args.name);
|
|
72
|
+
let existing;
|
|
73
|
+
try {
|
|
74
|
+
existing = await getServicePrincipalPolicy(caller.orgId, serviceName);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error("[service-principal] Policy lookup failed:", error);
|
|
78
|
+
throw new ServiceTokenError("Could not read service principal governance. Try again.", 503);
|
|
79
|
+
}
|
|
80
|
+
if (existing && existing.lifecycle !== "active") {
|
|
81
|
+
throw new ServiceTokenError(`Service principal "${serviceName}" is ${existing.lifecycle}. Resume it with set-service-principal-lifecycle before minting a token.`, 409);
|
|
82
|
+
}
|
|
83
|
+
const policyInput = {};
|
|
84
|
+
if (args.ownerEmail !== undefined) {
|
|
85
|
+
policyInput.ownerEmail = await assertOwnerIsOrgMember(caller.orgId, args.ownerEmail);
|
|
86
|
+
}
|
|
87
|
+
else if (!existing?.ownerEmail) {
|
|
88
|
+
policyInput.ownerEmail = caller.email.toLowerCase();
|
|
89
|
+
}
|
|
90
|
+
if (args.team !== undefined)
|
|
91
|
+
policyInput.team = args.team;
|
|
92
|
+
if (args.riskTier !== undefined)
|
|
93
|
+
policyInput.riskTier = args.riskTier;
|
|
94
|
+
if (args.purpose !== undefined)
|
|
95
|
+
policyInput.purpose = args.purpose;
|
|
96
|
+
if (args.allowedActions !== undefined) {
|
|
97
|
+
policyInput.allowedActions = normalizeAllowedActions(args.allowedActions);
|
|
98
|
+
}
|
|
49
99
|
const appUrl = (getRequestContext()?.requestOrigin || getAppProductionUrl()).replace(/\/+$/, "");
|
|
50
100
|
if (!appUrl && !process.env.A2A_SECRET?.trim()) {
|
|
51
101
|
throw new ServiceTokenError("Could not determine the app URL needed to mint a token. Set APP_URL on the deployment.", 500);
|
|
@@ -53,7 +103,7 @@ export default defineAction({
|
|
|
53
103
|
let minted;
|
|
54
104
|
try {
|
|
55
105
|
minted = await mintOrgServiceToken({
|
|
56
|
-
serviceName
|
|
106
|
+
serviceName,
|
|
57
107
|
orgId: caller.orgId,
|
|
58
108
|
createdBy: caller.email,
|
|
59
109
|
ttlDays: args.ttlDays,
|
|
@@ -67,6 +117,42 @@ export default defineAction({
|
|
|
67
117
|
? new ServiceTokenError(SERVICE_TOKEN_MANAGE_FORBIDDEN_MESSAGE, 403)
|
|
68
118
|
: new ServiceTokenError(CREDENTIAL_MEMBERSHIP_UNAVAILABLE_MESSAGE, 503);
|
|
69
119
|
}
|
|
120
|
+
// Governance is written after the mint so a rejected mint leaves no orphan
|
|
121
|
+
// policy; a failed write revokes the token rather than leaving a live
|
|
122
|
+
// credential that nobody is accountable for.
|
|
123
|
+
let policy;
|
|
124
|
+
try {
|
|
125
|
+
policy = await upsertServicePrincipalPolicy(caller.orgId, minted.serviceName, policyInput);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
console.error("[service-principal] Policy write failed:", error);
|
|
129
|
+
let revoked = false;
|
|
130
|
+
try {
|
|
131
|
+
revoked = await revokeOrgServiceToken(caller.orgId, minted.id);
|
|
132
|
+
}
|
|
133
|
+
catch (revokeError) {
|
|
134
|
+
console.error("[service-principal] Revoke after failure:", revokeError);
|
|
135
|
+
}
|
|
136
|
+
throw new ServiceTokenError(revoked
|
|
137
|
+
? "Could not record the service principal's governance, so the new token was revoked. Try again."
|
|
138
|
+
: `Could not record the service principal's governance AND could not revoke token ${minted.id}. Revoke it with revoke-org-service-token.`, 503);
|
|
139
|
+
}
|
|
140
|
+
// Retirement can finish revoking existing tokens after the initial
|
|
141
|
+
// lifecycle check but before this mint is recorded. The upsert returns the
|
|
142
|
+
// persisted lifecycle; contain this token before ever returning its secret.
|
|
143
|
+
if (policy.lifecycle !== "active") {
|
|
144
|
+
let revoked = false;
|
|
145
|
+
try {
|
|
146
|
+
revoked = await revokeOrgServiceToken(caller.orgId, minted.id);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.error("[service-principal] Revoke after lifecycle change:", error);
|
|
150
|
+
}
|
|
151
|
+
if (!revoked) {
|
|
152
|
+
throw new ServiceTokenError(`Service principal "${serviceName}" became ${policy.lifecycle} while minting, and token ${minted.id} could not be revoked. Revoke it with revoke-org-service-token.`, 503);
|
|
153
|
+
}
|
|
154
|
+
throw new ServiceTokenError(`Service principal "${serviceName}" became ${policy.lifecycle} while minting. The new token was revoked; resume it before minting again.`, 409);
|
|
155
|
+
}
|
|
70
156
|
return {
|
|
71
157
|
// The ONLY place the secret ever appears. Never stored, never logged.
|
|
72
158
|
token: minted.token,
|
|
@@ -75,6 +161,9 @@ export default defineAction({
|
|
|
75
161
|
serviceEmail: minted.serviceEmail,
|
|
76
162
|
orgId: caller.orgId,
|
|
77
163
|
ttlDays: minted.ttlDays,
|
|
164
|
+
ownerEmail: policy.ownerEmail,
|
|
165
|
+
riskTier: policy.riskTier,
|
|
166
|
+
allowedActions: policy.allowedActions,
|
|
78
167
|
note: "Store this token now (e.g. as the PLAN_RECAP_TOKEN GitHub Actions secret). It will not be shown again. Revoke it any time with revoke-org-service-token.",
|
|
79
168
|
};
|
|
80
169
|
},
|
|
@@ -2,6 +2,7 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
2
2
|
includeRevoked?: boolean;
|
|
3
3
|
}, {
|
|
4
4
|
orgId: string;
|
|
5
|
+
canManage: boolean;
|
|
5
6
|
tokens: {
|
|
6
7
|
id: string;
|
|
7
8
|
serviceName: string;
|
|
@@ -12,5 +13,6 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
12
13
|
lastUsedAt: number;
|
|
13
14
|
revokedAt: number;
|
|
14
15
|
}[];
|
|
16
|
+
principals: import("./service-principal-input.js").ServicePrincipalView[];
|
|
15
17
|
}>;
|
|
16
18
|
export default _default;
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* List the
|
|
3
|
-
* created/last-used/revoked timestamps)
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* List the org service tokens — metadata only (name, who minted it,
|
|
3
|
+
* created/last-used/revoked timestamps) — and the governed principals they
|
|
4
|
+
* belong to (state, owner, risk tier, grant). Token values are never stored, so
|
|
5
|
+
* they can never appear here. Any org member may list; minting, revoking and
|
|
6
|
+
* governance changes are owner/admin-gated.
|
|
6
7
|
*/
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
import { defineAction } from "../../action.js";
|
|
10
|
+
import { listServicePrincipalPolicies } from "../../org/service-principal-policy.js";
|
|
9
11
|
import { listOrgServiceTokens } from "../connect-store.js";
|
|
10
|
-
import {
|
|
12
|
+
import { describeServicePrincipal } from "./service-principal-input.js";
|
|
13
|
+
import { requireServiceTokenCaller, ServiceTokenError, } from "./service-token-access.js";
|
|
11
14
|
export default defineAction({
|
|
12
|
-
description: "List your organization's service tokens (CI credentials such as PLAN_RECAP_TOKEN): name, who created them, created/last-used times, and revocation state. Token values are never stored and never shown. Any org member can list.",
|
|
15
|
+
description: "List your organization's service tokens (CI credentials such as PLAN_RECAP_TOKEN): name, who created them, created/last-used times, and revocation state. Also returns `principals`: one row per service name (from tokens and governance records) with state (ungoverned = no owner/grant set, active, suspended, retired), owner, team, risk tier, purpose, allowedActions (null = unrestricted) and lifecycle history. Token values are never stored and never shown. Any org member can list.",
|
|
13
16
|
schema: z.object({
|
|
14
17
|
includeRevoked: z
|
|
15
18
|
.boolean()
|
|
@@ -23,7 +26,19 @@ export default defineAction({
|
|
|
23
26
|
orgId: ctx?.orgId,
|
|
24
27
|
level: "read",
|
|
25
28
|
});
|
|
26
|
-
|
|
29
|
+
let rows;
|
|
30
|
+
let policies;
|
|
31
|
+
try {
|
|
32
|
+
[rows, policies] = await Promise.all([
|
|
33
|
+
listOrgServiceTokens(caller.orgId),
|
|
34
|
+
listServicePrincipalPolicies(caller.orgId),
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// An unreadable policy table must not render every principal "ungoverned".
|
|
39
|
+
console.error("[service-principal] Listing failed:", error);
|
|
40
|
+
throw new ServiceTokenError("Could not read service principal governance. Try again.", 503);
|
|
41
|
+
}
|
|
27
42
|
const tokens = rows
|
|
28
43
|
.filter((row) => args.includeRevoked || row.revokedAt == null)
|
|
29
44
|
.map((row) => ({
|
|
@@ -36,6 +51,19 @@ export default defineAction({
|
|
|
36
51
|
lastUsedAt: row.lastUsedAt,
|
|
37
52
|
revokedAt: row.revokedAt,
|
|
38
53
|
}));
|
|
39
|
-
|
|
54
|
+
const policyByName = new Map(policies.map((p) => [p.serviceName, p]));
|
|
55
|
+
const names = new Set(policyByName.keys());
|
|
56
|
+
for (const row of rows)
|
|
57
|
+
if (row.serviceName)
|
|
58
|
+
names.add(row.serviceName);
|
|
59
|
+
const principals = [...names]
|
|
60
|
+
.sort()
|
|
61
|
+
.map((name) => describeServicePrincipal(caller.orgId, name, policyByName.get(name)));
|
|
62
|
+
return {
|
|
63
|
+
orgId: caller.orgId,
|
|
64
|
+
canManage: caller.role !== "member",
|
|
65
|
+
tokens,
|
|
66
|
+
principals,
|
|
67
|
+
};
|
|
40
68
|
},
|
|
41
69
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Governance input shared by `create-org-service-token` and
|
|
3
|
+
* `set-service-principal-policy`, so a principal is validated the same way
|
|
4
|
+
* whether it is born governed or tightened later.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { type ServicePrincipalLifecycle, type ServicePrincipalPolicy, type ServicePrincipalRiskTier } from "../../org/service-principal-policy.js";
|
|
8
|
+
export declare const MAX_ALLOWED_ACTIONS = 200;
|
|
9
|
+
export declare const riskTierSchema: z.ZodEnum<{
|
|
10
|
+
high: "high";
|
|
11
|
+
low: "low";
|
|
12
|
+
medium: "medium";
|
|
13
|
+
}>;
|
|
14
|
+
export declare const allowedActionsSchema: z.ZodArray<z.ZodString>;
|
|
15
|
+
export declare const ownerEmailSchema: z.ZodString;
|
|
16
|
+
export declare const teamSchema: z.ZodString;
|
|
17
|
+
export declare const purposeSchema: z.ZodString;
|
|
18
|
+
/** Dedupe so the stored grant (and its audited count) has no repeats. */
|
|
19
|
+
export declare function normalizeAllowedActions(allowed: string[] | null | undefined): string[] | null | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* The owner must be a person in this org. A service identity is refused by
|
|
22
|
+
* name so the answer is a clear 400 rather than a membership miss, and an
|
|
23
|
+
* unreadable membership store is a 503, never "not a member".
|
|
24
|
+
*/
|
|
25
|
+
export declare function assertOwnerIsOrgMember(orgId: string, ownerEmail: string): Promise<string>;
|
|
26
|
+
export interface ServicePrincipalView {
|
|
27
|
+
serviceName: string;
|
|
28
|
+
serviceEmail: string;
|
|
29
|
+
state: "ungoverned" | ServicePrincipalLifecycle;
|
|
30
|
+
ownerEmail: string | null;
|
|
31
|
+
team: string | null;
|
|
32
|
+
riskTier: ServicePrincipalRiskTier | null;
|
|
33
|
+
purpose: string | null;
|
|
34
|
+
/** `null` is unrestricted. */
|
|
35
|
+
allowedActions: string[] | null;
|
|
36
|
+
lifecycleReason: string | null;
|
|
37
|
+
lifecycleChangedBy: string | null;
|
|
38
|
+
lifecycleChangedAt: number | null;
|
|
39
|
+
}
|
|
40
|
+
/** No policy row is "ungoverned": a legacy principal that is active and unrestricted. */
|
|
41
|
+
export declare function describeServicePrincipal(orgId: string, serviceName: string, policy: ServicePrincipalPolicy | null | undefined): ServicePrincipalView;
|
|
42
|
+
/**
|
|
43
|
+
* A name with neither a token nor a policy is a typo, not a principal; refusing
|
|
44
|
+
* it keeps governance rows from accumulating for names that can never act.
|
|
45
|
+
*/
|
|
46
|
+
export declare function requireKnownServicePrincipal(orgId: string, serviceName: string): Promise<ServicePrincipalPolicy | null>;
|
|
47
|
+
/** Normalize a user-supplied name; a name with no usable characters is a 400. */
|
|
48
|
+
export declare function parseServiceName(raw: string): string;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Governance input shared by `create-org-service-token` and
|
|
3
|
+
* `set-service-principal-policy`, so a principal is validated the same way
|
|
4
|
+
* whether it is born governed or tightened later.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { isOrgMember } from "../../org/membership.js";
|
|
8
|
+
import { parseServiceIdentityEmail } from "../../org/service-identity.js";
|
|
9
|
+
import { getServicePrincipalPolicy, isServicePrincipalActionPattern, MAX_SERVICE_PRINCIPAL_ACTIONS, SERVICE_PRINCIPAL_RISK_TIERS, } from "../../org/service-principal-policy.js";
|
|
10
|
+
import { CREDENTIAL_MEMBERSHIP_UNAVAILABLE_MESSAGE } from "../../server/credential-membership-unavailable.js";
|
|
11
|
+
import { listOrgServiceTokens, normalizeServiceName, serviceIdentityEmail, } from "../connect-store.js";
|
|
12
|
+
import { ServiceTokenError } from "./service-token-access.js";
|
|
13
|
+
export const MAX_ALLOWED_ACTIONS = MAX_SERVICE_PRINCIPAL_ACTIONS;
|
|
14
|
+
export const riskTierSchema = z
|
|
15
|
+
.enum(SERVICE_PRINCIPAL_RISK_TIERS)
|
|
16
|
+
.describe("Risk tier: low, medium (default) or high");
|
|
17
|
+
export const allowedActionsSchema = z
|
|
18
|
+
.array(z.string().refine(isServicePrincipalActionPattern))
|
|
19
|
+
.max(MAX_ALLOWED_ACTIONS)
|
|
20
|
+
.describe("Action names the principal may call; a trailing * matches a prefix (e.g. 'list-*'). An empty list grants nothing. Use null for unrestricted.");
|
|
21
|
+
export const ownerEmailSchema = z
|
|
22
|
+
.string()
|
|
23
|
+
.trim()
|
|
24
|
+
.email()
|
|
25
|
+
.max(320)
|
|
26
|
+
.describe("Accountable org member (email)");
|
|
27
|
+
export const teamSchema = z.string().trim().min(1).max(120);
|
|
28
|
+
export const purposeSchema = z.string().trim().min(1).max(500);
|
|
29
|
+
/** Dedupe so the stored grant (and its audited count) has no repeats. */
|
|
30
|
+
export function normalizeAllowedActions(allowed) {
|
|
31
|
+
return allowed ? [...new Set(allowed)] : allowed;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The owner must be a person in this org. A service identity is refused by
|
|
35
|
+
* name so the answer is a clear 400 rather than a membership miss, and an
|
|
36
|
+
* unreadable membership store is a 503, never "not a member".
|
|
37
|
+
*/
|
|
38
|
+
export async function assertOwnerIsOrgMember(orgId, ownerEmail) {
|
|
39
|
+
const email = ownerEmail.trim().toLowerCase();
|
|
40
|
+
if (parseServiceIdentityEmail(email)) {
|
|
41
|
+
throw new ServiceTokenError("A service principal cannot own another service principal. Choose an org member.", 400);
|
|
42
|
+
}
|
|
43
|
+
let member;
|
|
44
|
+
try {
|
|
45
|
+
member = await isOrgMember(orgId, email);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error("[service-principal] Owner membership lookup failed:", error);
|
|
49
|
+
throw new ServiceTokenError(CREDENTIAL_MEMBERSHIP_UNAVAILABLE_MESSAGE, 503);
|
|
50
|
+
}
|
|
51
|
+
if (!member) {
|
|
52
|
+
throw new ServiceTokenError(`${email} is not a member of this organization.`, 400);
|
|
53
|
+
}
|
|
54
|
+
return email;
|
|
55
|
+
}
|
|
56
|
+
/** No policy row is "ungoverned": a legacy principal that is active and unrestricted. */
|
|
57
|
+
export function describeServicePrincipal(orgId, serviceName, policy) {
|
|
58
|
+
return {
|
|
59
|
+
serviceName,
|
|
60
|
+
serviceEmail: serviceIdentityEmail(serviceName, orgId),
|
|
61
|
+
state: policy?.lifecycle ?? "ungoverned",
|
|
62
|
+
ownerEmail: policy?.ownerEmail ?? null,
|
|
63
|
+
team: policy?.team ?? null,
|
|
64
|
+
riskTier: policy?.riskTier ?? null,
|
|
65
|
+
purpose: policy?.purpose ?? null,
|
|
66
|
+
allowedActions: policy ? policy.allowedActions : null,
|
|
67
|
+
lifecycleReason: policy?.lifecycleReason ?? null,
|
|
68
|
+
lifecycleChangedBy: policy?.lifecycleChangedBy ?? null,
|
|
69
|
+
lifecycleChangedAt: policy?.lifecycleChangedAt ?? null,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A name with neither a token nor a policy is a typo, not a principal; refusing
|
|
74
|
+
* it keeps governance rows from accumulating for names that can never act.
|
|
75
|
+
*/
|
|
76
|
+
export async function requireKnownServicePrincipal(orgId, serviceName) {
|
|
77
|
+
let policy;
|
|
78
|
+
let tokens;
|
|
79
|
+
try {
|
|
80
|
+
[policy, tokens] = await Promise.all([
|
|
81
|
+
getServicePrincipalPolicy(orgId, serviceName),
|
|
82
|
+
listOrgServiceTokens(orgId),
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error("[service-principal] Principal lookup failed:", error);
|
|
87
|
+
throw new ServiceTokenError("Could not read service principal governance. Try again.", 503);
|
|
88
|
+
}
|
|
89
|
+
if (!policy && !tokens.some((t) => t.serviceName === serviceName)) {
|
|
90
|
+
throw new ServiceTokenError(`No service principal named "${serviceName}" in this organization.`, 404);
|
|
91
|
+
}
|
|
92
|
+
return policy;
|
|
93
|
+
}
|
|
94
|
+
/** Normalize a user-supplied name; a name with no usable characters is a 400. */
|
|
95
|
+
export function parseServiceName(raw) {
|
|
96
|
+
try {
|
|
97
|
+
return normalizeServiceName(raw);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
throw new ServiceTokenError(error instanceof Error ? error.message : "Invalid service name.", 400);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare const _default: import("../../action.js").ActionDefinition<{
|
|
2
|
+
serviceName: string;
|
|
3
|
+
lifecycle: "active" | "retired" | "suspended";
|
|
4
|
+
reason?: string;
|
|
5
|
+
}, {
|
|
6
|
+
orgId: string;
|
|
7
|
+
serviceEmail: string;
|
|
8
|
+
lifecycle: "active" | "retired" | "suspended";
|
|
9
|
+
principal: import("./service-principal-input.js").ServicePrincipalView;
|
|
10
|
+
abortedRuns: number;
|
|
11
|
+
revokedTokens: number;
|
|
12
|
+
contained: boolean;
|
|
13
|
+
containmentErrors: string[];
|
|
14
|
+
}>;
|
|
15
|
+
export default _default;
|