@flowdesk/core 0.1.0 → 0.1.2
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/authority-promotion.d.ts +70 -0
- package/dist/authority-promotion.d.ts.map +1 -0
- package/dist/authority-promotion.js +388 -0
- package/dist/authority-promotion.js.map +1 -0
- package/dist/chat-control-authority.d.ts +83 -0
- package/dist/chat-control-authority.d.ts.map +1 -0
- package/dist/chat-control-authority.js +238 -0
- package/dist/chat-control-authority.js.map +1 -0
- package/dist/chat-hook-authority-probe.d.ts +39 -0
- package/dist/chat-hook-authority-probe.d.ts.map +1 -0
- package/dist/chat-hook-authority-probe.js +153 -0
- package/dist/chat-hook-authority-probe.js.map +1 -0
- package/dist/chat-routing.d.ts.map +1 -1
- package/dist/chat-routing.js +18 -15
- package/dist/chat-routing.js.map +1 -1
- package/dist/connector-gateway.d.ts +34 -0
- package/dist/connector-gateway.d.ts.map +1 -0
- package/dist/connector-gateway.js +147 -0
- package/dist/connector-gateway.js.map +1 -0
- package/dist/connector-profile.d.ts +41 -0
- package/dist/connector-profile.d.ts.map +1 -0
- package/dist/connector-profile.js +125 -0
- package/dist/connector-profile.js.map +1 -0
- package/dist/controlled-conformance-doc-write.d.ts +44 -0
- package/dist/controlled-conformance-doc-write.d.ts.map +1 -0
- package/dist/controlled-conformance-doc-write.js +142 -0
- package/dist/controlled-conformance-doc-write.js.map +1 -0
- package/dist/controlled-redacted-audit-export-write.d.ts +45 -0
- package/dist/controlled-redacted-audit-export-write.d.ts.map +1 -0
- package/dist/controlled-redacted-audit-export-write.js +145 -0
- package/dist/controlled-redacted-audit-export-write.js.map +1 -0
- package/dist/core-completion-safety-contracts.d.ts +35 -0
- package/dist/core-completion-safety-contracts.d.ts.map +1 -0
- package/dist/core-completion-safety-contracts.js +98 -0
- package/dist/core-completion-safety-contracts.js.map +1 -0
- package/dist/dispatch-attempt-manifest.d.ts +59 -0
- package/dist/dispatch-attempt-manifest.d.ts.map +1 -0
- package/dist/dispatch-attempt-manifest.js +294 -0
- package/dist/dispatch-attempt-manifest.js.map +1 -0
- package/dist/dispatch-idempotency.d.ts +89 -0
- package/dist/dispatch-idempotency.d.ts.map +1 -0
- package/dist/dispatch-idempotency.js +275 -0
- package/dist/dispatch-idempotency.js.map +1 -0
- package/dist/external-auth-policy.d.ts +49 -0
- package/dist/external-auth-policy.d.ts.map +1 -0
- package/dist/external-auth-policy.js +166 -0
- package/dist/external-auth-policy.js.map +1 -0
- package/dist/fake-remote-connector-adapter.d.ts +37 -0
- package/dist/fake-remote-connector-adapter.d.ts.map +1 -0
- package/dist/fake-remote-connector-adapter.js +162 -0
- package/dist/fake-remote-connector-adapter.js.map +1 -0
- package/dist/fallback-decision.d.ts +29 -0
- package/dist/fallback-decision.d.ts.map +1 -0
- package/dist/fallback-decision.js +93 -0
- package/dist/fallback-decision.js.map +1 -0
- package/dist/fallback-regate-plan.d.ts +34 -0
- package/dist/fallback-regate-plan.d.ts.map +1 -0
- package/dist/fallback-regate-plan.js +122 -0
- package/dist/fallback-regate-plan.js.map +1 -0
- package/dist/fds1-schema-probe-result.d.ts +37 -0
- package/dist/fds1-schema-probe-result.d.ts.map +1 -0
- package/dist/fds1-schema-probe-result.js +115 -0
- package/dist/fds1-schema-probe-result.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/lane-heartbeat.d.ts +49 -0
- package/dist/lane-heartbeat.d.ts.map +1 -0
- package/dist/lane-heartbeat.js +149 -0
- package/dist/lane-heartbeat.js.map +1 -0
- package/dist/lane-lifecycle-record.d.ts +32 -0
- package/dist/lane-lifecycle-record.d.ts.map +1 -0
- package/dist/lane-lifecycle-record.js +134 -0
- package/dist/lane-lifecycle-record.js.map +1 -0
- package/dist/lane-stall-projection.d.ts +43 -0
- package/dist/lane-stall-projection.d.ts.map +1 -0
- package/dist/lane-stall-projection.js +272 -0
- package/dist/lane-stall-projection.js.map +1 -0
- package/dist/model-availability-cache.d.ts +286 -0
- package/dist/model-availability-cache.d.ts.map +1 -0
- package/dist/model-availability-cache.js +1109 -0
- package/dist/model-availability-cache.js.map +1 -0
- package/dist/operational-intelligence.d.ts +38 -0
- package/dist/operational-intelligence.d.ts.map +1 -0
- package/dist/operational-intelligence.js +107 -0
- package/dist/operational-intelligence.js.map +1 -0
- package/dist/production-approval-source.d.ts +61 -0
- package/dist/production-approval-source.d.ts.map +1 -0
- package/dist/production-approval-source.js +226 -0
- package/dist/production-approval-source.js.map +1 -0
- package/dist/production-enablement.d.ts +92 -1
- package/dist/production-enablement.d.ts.map +1 -1
- package/dist/production-enablement.js +421 -8
- package/dist/production-enablement.js.map +1 -1
- package/dist/production-verification.d.ts +31 -0
- package/dist/production-verification.d.ts.map +1 -0
- package/dist/production-verification.js +126 -0
- package/dist/production-verification.js.map +1 -0
- package/dist/provider-usage-collector.d.ts +7 -0
- package/dist/provider-usage-collector.d.ts.map +1 -1
- package/dist/provider-usage-collector.js +64 -10
- package/dist/provider-usage-collector.js.map +1 -1
- package/dist/release1-contracts.d.ts +8 -2
- package/dist/release1-contracts.d.ts.map +1 -1
- package/dist/release1-contracts.js +2 -1
- package/dist/release1-contracts.js.map +1 -1
- package/dist/remote-write-connector-gate.d.ts +91 -0
- package/dist/remote-write-connector-gate.d.ts.map +1 -0
- package/dist/remote-write-connector-gate.js +291 -0
- package/dist/remote-write-connector-gate.js.map +1 -0
- package/dist/runtime-lane-productization.d.ts +78 -0
- package/dist/runtime-lane-productization.d.ts.map +1 -0
- package/dist/runtime-lane-productization.js +270 -0
- package/dist/runtime-lane-productization.js.map +1 -0
- package/dist/sanitized-auth-capture.d.ts +50 -0
- package/dist/sanitized-auth-capture.d.ts.map +1 -0
- package/dist/sanitized-auth-capture.js +164 -0
- package/dist/sanitized-auth-capture.js.map +1 -0
- package/dist/schema-artifacts.d.ts.map +1 -1
- package/dist/schema-artifacts.js +37 -6
- package/dist/schema-artifacts.js.map +1 -1
- package/dist/schema-registry.d.ts.map +1 -1
- package/dist/schema-registry.js +21 -0
- package/dist/schema-registry.js.map +1 -1
- package/dist/session-evidence.d.ts +117 -0
- package/dist/session-evidence.d.ts.map +1 -1
- package/dist/session-evidence.js +569 -1
- package/dist/session-evidence.js.map +1 -1
- package/dist/state-paths.d.ts +1 -1
- package/dist/state-paths.d.ts.map +1 -1
- package/dist/state-paths.js +56 -6
- package/dist/state-paths.js.map +1 -1
- package/dist/status.d.ts +7 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +89 -1
- package/dist/status.js.map +1 -1
- package/dist/validators.d.ts +1 -0
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +30 -7
- package/dist/validators.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { FlowDeskExternalAuthProviderPolicyResultV1 } from "./external-auth-policy.js";
|
|
2
|
+
import type { FlowDeskConfiguredVerificationResultV1 } from "./production-verification.js";
|
|
3
|
+
import type { FlowDeskSanitizedAuthCaptureResultV1 } from "./sanitized-auth-capture.js";
|
|
1
4
|
import type { FlowDeskSessionEvidenceReloadResultV1 } from "./session-evidence.js";
|
|
2
5
|
import { type ValidationResult } from "./validators.js";
|
|
3
6
|
export declare const FLOWDESK_PRODUCTION_ENABLEMENT_STATES: readonly ["disabled", "blocked", "configured", "approved", "dispatch_capable"];
|
|
4
7
|
export type FlowDeskProductionEnablementStateV1 = (typeof FLOWDESK_PRODUCTION_ENABLEMENT_STATES)[number];
|
|
5
|
-
export declare const FLOWDESK_PRODUCTION_ENABLEMENT_BLOCKER_LABELS: readonly ["session_evidence_reload_failed", "session_evidence_blocked_records", "usage_authority_missing", "runtime_echo_missing", "telemetry_correlation_missing", "pre_dispatch_audit_missing", "configured_verification_missing", "external_auth_policy_missing", "provider_policy_missing", "approval_missing", "approval_denied", "approval_mismatched", "approval_required_refs_missing", "lane_conformance_missing"];
|
|
8
|
+
export declare const FLOWDESK_PRODUCTION_ENABLEMENT_BLOCKER_LABELS: readonly ["session_evidence_reload_failed", "session_evidence_blocked_records", "usage_authority_missing", "runtime_echo_missing", "telemetry_correlation_missing", "pre_dispatch_audit_missing", "configured_verification_missing", "configured_verification_result_missing", "configured_verification_invalid", "configured_verification_failed", "sanitized_auth_capture_result_missing", "sanitized_auth_capture_invalid", "sanitized_auth_capture_failed", "external_auth_policy_missing", "provider_policy_missing", "external_auth_provider_policy_result_missing", "external_auth_provider_policy_invalid", "external_auth_provider_policy_failed", "approval_missing", "approval_denied", "approval_mismatched", "approval_required_refs_missing", "lane_conformance_missing"];
|
|
6
9
|
export type FlowDeskProductionEnablementBlockerLabelV1 = (typeof FLOWDESK_PRODUCTION_ENABLEMENT_BLOCKER_LABELS)[number];
|
|
7
10
|
export declare const FLOWDESK_PRODUCTION_UNCERTAINTY_LABELS: readonly ["opencode_subtask_lifecycle_unproven", "injected_sdk_runtime_echo_partial", "external_auth_plugin_introspection_partial", "hard_chat_cancel_or_no_reply_unproven", "flowdesk_created_telemetry_correlation"];
|
|
8
11
|
export type FlowDeskProductionUncertaintyLabelV1 = (typeof FLOWDESK_PRODUCTION_UNCERTAINTY_LABELS)[number];
|
|
@@ -32,8 +35,12 @@ export interface FlowDeskProductionEnablementInputV1 {
|
|
|
32
35
|
evidenceReload: FlowDeskSessionEvidenceReloadResultV1;
|
|
33
36
|
preDispatchAuditRef?: string;
|
|
34
37
|
configuredVerificationRef?: string;
|
|
38
|
+
configuredVerificationResult?: FlowDeskConfiguredVerificationResultV1;
|
|
39
|
+
sanitizedAuthCaptureRef?: string;
|
|
40
|
+
sanitizedAuthCaptureResult?: FlowDeskSanitizedAuthCaptureResultV1;
|
|
35
41
|
externalAuthPolicyRef?: string;
|
|
36
42
|
providerPolicyRef?: string;
|
|
43
|
+
externalAuthProviderPolicyResult?: FlowDeskExternalAuthProviderPolicyResultV1;
|
|
37
44
|
laneConformanceRefs?: string[];
|
|
38
45
|
allowIncompleteConformance?: boolean;
|
|
39
46
|
approvalDecision?: FlowDeskProductionApprovalDecisionV1;
|
|
@@ -50,8 +57,92 @@ export interface FlowDeskProductionEnablementEvaluationV1 extends ValidationResu
|
|
|
50
57
|
dispatch_authority_enabled: false;
|
|
51
58
|
default_release1_non_dispatch_preserved: true;
|
|
52
59
|
safe_next_actions: string[];
|
|
60
|
+
configured_verification_result?: FlowDeskConfiguredVerificationResultV1["result"];
|
|
61
|
+
configured_verification_ref?: string;
|
|
62
|
+
sanitized_auth_capture_result?: FlowDeskSanitizedAuthCaptureResultV1["result"];
|
|
63
|
+
sanitized_auth_capture_ref?: string;
|
|
64
|
+
external_auth_provider_policy_result?: FlowDeskExternalAuthProviderPolicyResultV1["result"];
|
|
65
|
+
external_auth_policy_ref?: string;
|
|
66
|
+
provider_policy_ref?: string;
|
|
67
|
+
approval_decision?: FlowDeskProductionApprovalDecisionV1["decision"];
|
|
68
|
+
approval_ref?: string;
|
|
69
|
+
}
|
|
70
|
+
export declare const FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_STATES: readonly ["blocked", "configured", "default_candidate"];
|
|
71
|
+
export type FlowDeskDefaultManagedDispatchPromotionStateV1 = (typeof FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_STATES)[number];
|
|
72
|
+
export declare const FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_BLOCKER_LABELS: readonly ["production_enablement_not_dispatch_capable", "production_enablement_errors_present", "durable_precall_missing", "adapter_unavailable", "sdk_client_unavailable", "default_release_enablement_missing", "promotion_uncertainty_present"];
|
|
73
|
+
export type FlowDeskDefaultManagedDispatchPromotionBlockerLabelV1 = (typeof FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_BLOCKER_LABELS)[number];
|
|
74
|
+
export declare const FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_STATES: readonly ["blocked", "authorized"];
|
|
75
|
+
export type FlowDeskDefaultManagedDispatchAuthorizationStateV1 = (typeof FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_STATES)[number];
|
|
76
|
+
export declare const FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_BLOCKER_LABELS: readonly ["readiness_not_candidate", "default_enablement_not_requested", "kill_switch_active", "authorization_expired", "authorization_ref_invalid"];
|
|
77
|
+
export type FlowDeskDefaultManagedDispatchAuthorizationBlockerLabelV1 = (typeof FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_BLOCKER_LABELS)[number];
|
|
78
|
+
export interface FlowDeskDefaultManagedDispatchPromotionReadinessInputV1 {
|
|
79
|
+
productionEnablement: FlowDeskProductionEnablementEvaluationV1;
|
|
80
|
+
durablePrecallRef?: string;
|
|
81
|
+
adapterProfileRef?: string;
|
|
82
|
+
sdkClientRef?: string;
|
|
83
|
+
defaultReleaseEnablementRef?: string;
|
|
84
|
+
allowUncertainty?: boolean;
|
|
85
|
+
}
|
|
86
|
+
export interface FlowDeskDefaultManagedDispatchPromotionReadinessV1 extends ValidationResult {
|
|
87
|
+
schema_version: "flowdesk.default_managed_dispatch_promotion_readiness.v1";
|
|
88
|
+
workflow_id: string;
|
|
89
|
+
state: FlowDeskDefaultManagedDispatchPromotionStateV1;
|
|
90
|
+
blocked_labels: FlowDeskDefaultManagedDispatchPromotionBlockerLabelV1[];
|
|
91
|
+
evidence_refs: string[];
|
|
92
|
+
production_enablement_state: FlowDeskProductionEnablementStateV1;
|
|
93
|
+
managed_dispatch_ready: boolean;
|
|
94
|
+
durable_precall_ready: boolean;
|
|
95
|
+
adapter_available: boolean;
|
|
96
|
+
sdk_client_available: boolean;
|
|
97
|
+
doctor_status_ref: string;
|
|
98
|
+
default_dispatch_candidate: boolean;
|
|
99
|
+
dispatch_authority_enabled: false;
|
|
100
|
+
providerCall: false;
|
|
101
|
+
actualLaneLaunch: false;
|
|
102
|
+
runtimeExecution: false;
|
|
103
|
+
safe_next_actions: string[];
|
|
104
|
+
release_enablement_ref?: string;
|
|
105
|
+
}
|
|
106
|
+
export interface FlowDeskDefaultManagedDispatchAuthorizationInputV1 {
|
|
107
|
+
authorizationId: string;
|
|
108
|
+
readiness: FlowDeskDefaultManagedDispatchPromotionReadinessV1;
|
|
109
|
+
actorRef: string;
|
|
110
|
+
profileRef: string;
|
|
111
|
+
releaseGateRef: string;
|
|
112
|
+
rollbackRef: string;
|
|
113
|
+
createdAt: string;
|
|
114
|
+
expiresAt: string;
|
|
115
|
+
defaultEnablementRequested: boolean;
|
|
116
|
+
killSwitchState: "inactive" | "active";
|
|
117
|
+
now?: number;
|
|
118
|
+
}
|
|
119
|
+
export interface FlowDeskDefaultManagedDispatchAuthorizationV1 extends ValidationResult {
|
|
120
|
+
schema_version: "flowdesk.default_managed_dispatch_authorization.v1";
|
|
121
|
+
authorization_id: string;
|
|
122
|
+
workflow_id: string;
|
|
123
|
+
state: FlowDeskDefaultManagedDispatchAuthorizationStateV1;
|
|
124
|
+
blocked_labels: FlowDeskDefaultManagedDispatchAuthorizationBlockerLabelV1[];
|
|
125
|
+
readiness_ref: string;
|
|
126
|
+
actor_ref: string;
|
|
127
|
+
profile_ref: string;
|
|
128
|
+
release_gate_ref: string;
|
|
129
|
+
rollback_ref: string;
|
|
130
|
+
created_at: string;
|
|
131
|
+
expires_at: string;
|
|
132
|
+
default_enablement_requested: boolean;
|
|
133
|
+
kill_switch_state: "inactive" | "active";
|
|
134
|
+
default_managed_dispatch_authority_enabled: boolean;
|
|
135
|
+
dispatch_authority_enabled: false;
|
|
136
|
+
providerCall: false;
|
|
137
|
+
actualLaneLaunch: false;
|
|
138
|
+
runtimeExecution: false;
|
|
139
|
+
safe_next_actions: string[];
|
|
53
140
|
}
|
|
54
141
|
export declare function createFlowDeskProductionApprovalDecisionV1(input: FlowDeskProductionApprovalDecisionInputV1): FlowDeskProductionApprovalDecisionV1;
|
|
55
142
|
export declare function validateFlowDeskProductionApprovalDecisionV1(value: unknown, expectedWorkflowId?: string): ValidationResult;
|
|
143
|
+
export declare function evaluateFlowDeskDefaultManagedDispatchPromotionReadinessV1(input: FlowDeskDefaultManagedDispatchPromotionReadinessInputV1): FlowDeskDefaultManagedDispatchPromotionReadinessV1;
|
|
144
|
+
export declare function validateFlowDeskDefaultManagedDispatchPromotionReadinessV1(value: unknown, expectedWorkflowId?: string): ValidationResult;
|
|
145
|
+
export declare function authorizeFlowDeskDefaultManagedDispatchV1(input: FlowDeskDefaultManagedDispatchAuthorizationInputV1): FlowDeskDefaultManagedDispatchAuthorizationV1;
|
|
146
|
+
export declare function validateFlowDeskDefaultManagedDispatchAuthorizationV1(value: unknown, expectedWorkflowId?: string): ValidationResult;
|
|
56
147
|
export declare function evaluateFlowDeskProductionEnablementV1(input: FlowDeskProductionEnablementInputV1): FlowDeskProductionEnablementEvaluationV1;
|
|
57
148
|
//# sourceMappingURL=production-enablement.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"production-enablement.d.ts","sourceRoot":"","sources":["../src/production-enablement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,uBAAuB,CAAC;AAEnF,OAAO,EAEN,KAAK,gBAAgB,EAKrB,MAAM,iBAAiB,CAAC;AAEzB,eAAO,MAAM,qCAAqC,gFAMxC,CAAC;AACX,MAAM,MAAM,mCAAmC,GAC9C,CAAC,OAAO,qCAAqC,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,6CAA6C,
|
|
1
|
+
{"version":3,"file":"production-enablement.d.ts","sourceRoot":"","sources":["../src/production-enablement.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { validateFlowDeskExternalAuthProviderPolicyResultV1 } from "./external-auth-policy.js";
|
|
2
|
+
import { validateFlowDeskConfiguredVerificationResultV1 } from "./production-verification.js";
|
|
3
|
+
import { validateFlowDeskSanitizedAuthCaptureResultV1 } from "./sanitized-auth-capture.js";
|
|
1
4
|
import { invalid, valid, validateNoForbiddenRawPayloads, validateOpaqueId, validateOpaqueRef, } from "./validators.js";
|
|
2
5
|
export const FLOWDESK_PRODUCTION_ENABLEMENT_STATES = [
|
|
3
6
|
"disabled",
|
|
@@ -14,8 +17,17 @@ export const FLOWDESK_PRODUCTION_ENABLEMENT_BLOCKER_LABELS = [
|
|
|
14
17
|
"telemetry_correlation_missing",
|
|
15
18
|
"pre_dispatch_audit_missing",
|
|
16
19
|
"configured_verification_missing",
|
|
20
|
+
"configured_verification_result_missing",
|
|
21
|
+
"configured_verification_invalid",
|
|
22
|
+
"configured_verification_failed",
|
|
23
|
+
"sanitized_auth_capture_result_missing",
|
|
24
|
+
"sanitized_auth_capture_invalid",
|
|
25
|
+
"sanitized_auth_capture_failed",
|
|
17
26
|
"external_auth_policy_missing",
|
|
18
27
|
"provider_policy_missing",
|
|
28
|
+
"external_auth_provider_policy_result_missing",
|
|
29
|
+
"external_auth_provider_policy_invalid",
|
|
30
|
+
"external_auth_provider_policy_failed",
|
|
19
31
|
"approval_missing",
|
|
20
32
|
"approval_denied",
|
|
21
33
|
"approval_mismatched",
|
|
@@ -29,6 +41,31 @@ export const FLOWDESK_PRODUCTION_UNCERTAINTY_LABELS = [
|
|
|
29
41
|
"hard_chat_cancel_or_no_reply_unproven",
|
|
30
42
|
"flowdesk_created_telemetry_correlation",
|
|
31
43
|
];
|
|
44
|
+
export const FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_STATES = [
|
|
45
|
+
"blocked",
|
|
46
|
+
"configured",
|
|
47
|
+
"default_candidate",
|
|
48
|
+
];
|
|
49
|
+
export const FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_BLOCKER_LABELS = [
|
|
50
|
+
"production_enablement_not_dispatch_capable",
|
|
51
|
+
"production_enablement_errors_present",
|
|
52
|
+
"durable_precall_missing",
|
|
53
|
+
"adapter_unavailable",
|
|
54
|
+
"sdk_client_unavailable",
|
|
55
|
+
"default_release_enablement_missing",
|
|
56
|
+
"promotion_uncertainty_present",
|
|
57
|
+
];
|
|
58
|
+
export const FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_STATES = [
|
|
59
|
+
"blocked",
|
|
60
|
+
"authorized",
|
|
61
|
+
];
|
|
62
|
+
export const FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_BLOCKER_LABELS = [
|
|
63
|
+
"readiness_not_candidate",
|
|
64
|
+
"default_enablement_not_requested",
|
|
65
|
+
"kill_switch_active",
|
|
66
|
+
"authorization_expired",
|
|
67
|
+
"authorization_ref_invalid",
|
|
68
|
+
];
|
|
32
69
|
const REQUIRED_SESSION_EVIDENCE_CLASSES = [
|
|
33
70
|
"usage_authority",
|
|
34
71
|
"runtime_echo",
|
|
@@ -138,6 +175,286 @@ function missingRequiredApprovalRefs(approval, evidenceRefs) {
|
|
|
138
175
|
const available = new Set(evidenceRefs);
|
|
139
176
|
return approval.required_evidence_refs.filter((ref) => !available.has(ref));
|
|
140
177
|
}
|
|
178
|
+
function optionalOpaqueRef(value, label) {
|
|
179
|
+
return value === undefined ? valid() : validateOpaqueRef(value, label);
|
|
180
|
+
}
|
|
181
|
+
function validDate(value) {
|
|
182
|
+
return Number.isFinite(Date.parse(value));
|
|
183
|
+
}
|
|
184
|
+
export function evaluateFlowDeskDefaultManagedDispatchPromotionReadinessV1(input) {
|
|
185
|
+
const errors = [];
|
|
186
|
+
const blockedLabels = [];
|
|
187
|
+
const production = input.productionEnablement;
|
|
188
|
+
errors.push(...validateOpaqueId(production.workflow_id, "workflow_id").errors);
|
|
189
|
+
if (!production.ok || production.errors.length > 0)
|
|
190
|
+
blockedLabels.push("production_enablement_errors_present");
|
|
191
|
+
if (production.state !== "dispatch_capable" || !production.managed_dispatch_ready)
|
|
192
|
+
blockedLabels.push("production_enablement_not_dispatch_capable");
|
|
193
|
+
if (production.uncertainty_labels.length > 0 &&
|
|
194
|
+
input.allowUncertainty !== true)
|
|
195
|
+
blockedLabels.push("promotion_uncertainty_present");
|
|
196
|
+
const durablePrecallResult = optionalOpaqueRef(input.durablePrecallRef, "durable_precall_ref");
|
|
197
|
+
const adapterProfileResult = optionalOpaqueRef(input.adapterProfileRef, "adapter_profile_ref");
|
|
198
|
+
const sdkClientResult = optionalOpaqueRef(input.sdkClientRef, "sdk_client_ref");
|
|
199
|
+
const defaultReleaseResult = optionalOpaqueRef(input.defaultReleaseEnablementRef, "default_release_enablement_ref");
|
|
200
|
+
errors.push(...durablePrecallResult.errors, ...adapterProfileResult.errors, ...sdkClientResult.errors, ...defaultReleaseResult.errors);
|
|
201
|
+
if (!durablePrecallResult.ok || input.durablePrecallRef === undefined)
|
|
202
|
+
blockedLabels.push("durable_precall_missing");
|
|
203
|
+
if (!adapterProfileResult.ok || input.adapterProfileRef === undefined)
|
|
204
|
+
blockedLabels.push("adapter_unavailable");
|
|
205
|
+
if (!sdkClientResult.ok || input.sdkClientRef === undefined)
|
|
206
|
+
blockedLabels.push("sdk_client_unavailable");
|
|
207
|
+
if (!defaultReleaseResult.ok || input.defaultReleaseEnablementRef === undefined)
|
|
208
|
+
blockedLabels.push("default_release_enablement_missing");
|
|
209
|
+
const uniqueBlockers = unique(blockedLabels);
|
|
210
|
+
const candidate = errors.length === 0 && uniqueBlockers.length === 0;
|
|
211
|
+
const state = candidate
|
|
212
|
+
? "default_candidate"
|
|
213
|
+
: production.state === "dispatch_capable" && production.ok
|
|
214
|
+
? "configured"
|
|
215
|
+
: "blocked";
|
|
216
|
+
const evidenceRefs = unique([
|
|
217
|
+
...production.evidence_refs,
|
|
218
|
+
input.durablePrecallRef,
|
|
219
|
+
input.adapterProfileRef,
|
|
220
|
+
input.sdkClientRef,
|
|
221
|
+
input.defaultReleaseEnablementRef,
|
|
222
|
+
].filter((ref) => typeof ref === "string"));
|
|
223
|
+
return {
|
|
224
|
+
schema_version: "flowdesk.default_managed_dispatch_promotion_readiness.v1",
|
|
225
|
+
workflow_id: production.workflow_id,
|
|
226
|
+
ok: errors.length === 0,
|
|
227
|
+
errors,
|
|
228
|
+
state,
|
|
229
|
+
blocked_labels: uniqueBlockers,
|
|
230
|
+
evidence_refs: evidenceRefs,
|
|
231
|
+
production_enablement_state: production.state,
|
|
232
|
+
managed_dispatch_ready: production.managed_dispatch_ready,
|
|
233
|
+
durable_precall_ready: input.durablePrecallRef !== undefined && durablePrecallResult.ok,
|
|
234
|
+
adapter_available: input.adapterProfileRef !== undefined && adapterProfileResult.ok,
|
|
235
|
+
sdk_client_available: input.sdkClientRef !== undefined && sdkClientResult.ok,
|
|
236
|
+
doctor_status_ref: `default-managed-dispatch-${state}`,
|
|
237
|
+
default_dispatch_candidate: candidate,
|
|
238
|
+
dispatch_authority_enabled: false,
|
|
239
|
+
providerCall: false,
|
|
240
|
+
actualLaneLaunch: false,
|
|
241
|
+
runtimeExecution: false,
|
|
242
|
+
safe_next_actions: candidate
|
|
243
|
+
? ["/flowdesk-status"]
|
|
244
|
+
: ["/flowdesk-doctor", "/flowdesk-status"],
|
|
245
|
+
...(input.defaultReleaseEnablementRef === undefined
|
|
246
|
+
? {}
|
|
247
|
+
: { release_enablement_ref: input.defaultReleaseEnablementRef }),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
export function validateFlowDeskDefaultManagedDispatchPromotionReadinessV1(value, expectedWorkflowId) {
|
|
251
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
252
|
+
return invalid("default managed dispatch promotion readiness must be an object");
|
|
253
|
+
const record = value;
|
|
254
|
+
const errors = [];
|
|
255
|
+
const allowed = new Set([
|
|
256
|
+
"schema_version",
|
|
257
|
+
"workflow_id",
|
|
258
|
+
"ok",
|
|
259
|
+
"errors",
|
|
260
|
+
"state",
|
|
261
|
+
"blocked_labels",
|
|
262
|
+
"evidence_refs",
|
|
263
|
+
"production_enablement_state",
|
|
264
|
+
"managed_dispatch_ready",
|
|
265
|
+
"durable_precall_ready",
|
|
266
|
+
"adapter_available",
|
|
267
|
+
"sdk_client_available",
|
|
268
|
+
"doctor_status_ref",
|
|
269
|
+
"default_dispatch_candidate",
|
|
270
|
+
"dispatch_authority_enabled",
|
|
271
|
+
"providerCall",
|
|
272
|
+
"actualLaneLaunch",
|
|
273
|
+
"runtimeExecution",
|
|
274
|
+
"safe_next_actions",
|
|
275
|
+
"release_enablement_ref",
|
|
276
|
+
]);
|
|
277
|
+
for (const key of Object.keys(record))
|
|
278
|
+
if (!allowed.has(key))
|
|
279
|
+
errors.push(`unknown properties: ${key}`);
|
|
280
|
+
if (record.schema_version !==
|
|
281
|
+
"flowdesk.default_managed_dispatch_promotion_readiness.v1")
|
|
282
|
+
errors.push("promotion readiness schema_version is invalid");
|
|
283
|
+
errors.push(...validateOpaqueId(record.workflow_id, "workflow_id").errors);
|
|
284
|
+
if (expectedWorkflowId !== undefined && record.workflow_id !== expectedWorkflowId)
|
|
285
|
+
errors.push("promotion readiness workflow_id mismatch");
|
|
286
|
+
if (typeof record.ok !== "boolean")
|
|
287
|
+
errors.push("ok must be boolean");
|
|
288
|
+
if (!Array.isArray(record.errors))
|
|
289
|
+
errors.push("errors must be an array");
|
|
290
|
+
if (!FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_STATES.includes(String(record.state)))
|
|
291
|
+
errors.push("promotion readiness state is invalid");
|
|
292
|
+
if (!Array.isArray(record.blocked_labels))
|
|
293
|
+
errors.push("blocked_labels must be an array");
|
|
294
|
+
else
|
|
295
|
+
for (const label of record.blocked_labels)
|
|
296
|
+
if (!FLOWDESK_DEFAULT_MANAGED_DISPATCH_PROMOTION_BLOCKER_LABELS.includes(label))
|
|
297
|
+
errors.push(`blocked_label is invalid: ${label}`);
|
|
298
|
+
if (!Array.isArray(record.evidence_refs))
|
|
299
|
+
errors.push("evidence_refs must be an array");
|
|
300
|
+
else
|
|
301
|
+
for (const [index, ref] of record.evidence_refs.entries())
|
|
302
|
+
errors.push(...validateOpaqueRef(ref, `evidence_refs[${index}]`).errors);
|
|
303
|
+
if (!FLOWDESK_PRODUCTION_ENABLEMENT_STATES.includes(String(record.production_enablement_state)))
|
|
304
|
+
errors.push("production_enablement_state is invalid");
|
|
305
|
+
for (const key of [
|
|
306
|
+
"managed_dispatch_ready",
|
|
307
|
+
"durable_precall_ready",
|
|
308
|
+
"adapter_available",
|
|
309
|
+
"sdk_client_available",
|
|
310
|
+
"default_dispatch_candidate",
|
|
311
|
+
])
|
|
312
|
+
if (typeof record[key] !== "boolean")
|
|
313
|
+
errors.push(`${key} must be boolean`);
|
|
314
|
+
errors.push(...validateOpaqueRef(record.doctor_status_ref, "doctor_status_ref").errors);
|
|
315
|
+
if (record.dispatch_authority_enabled !== false)
|
|
316
|
+
errors.push("promotion readiness cannot enable dispatch authority");
|
|
317
|
+
if (record.providerCall !== false)
|
|
318
|
+
errors.push("promotion readiness cannot make provider calls");
|
|
319
|
+
if (record.actualLaneLaunch !== false)
|
|
320
|
+
errors.push("promotion readiness cannot launch lanes");
|
|
321
|
+
if (record.runtimeExecution !== false)
|
|
322
|
+
errors.push("promotion readiness cannot execute runtime");
|
|
323
|
+
if (!Array.isArray(record.safe_next_actions))
|
|
324
|
+
errors.push("safe_next_actions must be an array");
|
|
325
|
+
if (record.release_enablement_ref !== undefined)
|
|
326
|
+
errors.push(...validateOpaqueRef(record.release_enablement_ref, "release_enablement_ref")
|
|
327
|
+
.errors);
|
|
328
|
+
errors.push(...validateNoForbiddenRawPayloads(record, "default_managed_dispatch_promotion_readiness")
|
|
329
|
+
.errors);
|
|
330
|
+
return errors.length === 0 ? valid() : invalid(...errors);
|
|
331
|
+
}
|
|
332
|
+
export function authorizeFlowDeskDefaultManagedDispatchV1(input) {
|
|
333
|
+
const errors = [];
|
|
334
|
+
const blockedLabels = [];
|
|
335
|
+
const readinessValidation = validateFlowDeskDefaultManagedDispatchPromotionReadinessV1(input.readiness);
|
|
336
|
+
errors.push(...validateOpaqueId(input.authorizationId, "authorization_id").errors, ...readinessValidation.errors, ...validateOpaqueRef(input.actorRef, "actor_ref").errors, ...validateOpaqueRef(input.profileRef, "profile_ref").errors, ...validateOpaqueRef(input.releaseGateRef, "release_gate_ref").errors, ...validateOpaqueRef(input.rollbackRef, "rollback_ref").errors);
|
|
337
|
+
if (!readinessValidation.ok || !input.readiness.default_dispatch_candidate)
|
|
338
|
+
blockedLabels.push("readiness_not_candidate");
|
|
339
|
+
if (!input.defaultEnablementRequested)
|
|
340
|
+
blockedLabels.push("default_enablement_not_requested");
|
|
341
|
+
if (input.killSwitchState === "active")
|
|
342
|
+
blockedLabels.push("kill_switch_active");
|
|
343
|
+
else if (input.killSwitchState !== "inactive") {
|
|
344
|
+
blockedLabels.push("authorization_ref_invalid");
|
|
345
|
+
errors.push("kill_switch_state is invalid");
|
|
346
|
+
}
|
|
347
|
+
if (!validDate(input.createdAt) || !validDate(input.expiresAt)) {
|
|
348
|
+
blockedLabels.push("authorization_ref_invalid");
|
|
349
|
+
errors.push("authorization timestamps must be parseable");
|
|
350
|
+
}
|
|
351
|
+
else if (Date.parse(input.expiresAt) <= (input.now ?? Date.now()))
|
|
352
|
+
blockedLabels.push("authorization_expired");
|
|
353
|
+
const uniqueBlockers = unique(blockedLabels);
|
|
354
|
+
const authorityEnabled = errors.length === 0 && uniqueBlockers.length === 0;
|
|
355
|
+
return {
|
|
356
|
+
schema_version: "flowdesk.default_managed_dispatch_authorization.v1",
|
|
357
|
+
authorization_id: input.authorizationId,
|
|
358
|
+
workflow_id: input.readiness.workflow_id,
|
|
359
|
+
ok: errors.length === 0,
|
|
360
|
+
errors,
|
|
361
|
+
state: authorityEnabled ? "authorized" : "blocked",
|
|
362
|
+
blocked_labels: uniqueBlockers,
|
|
363
|
+
readiness_ref: input.readiness.doctor_status_ref,
|
|
364
|
+
actor_ref: input.actorRef,
|
|
365
|
+
profile_ref: input.profileRef,
|
|
366
|
+
release_gate_ref: input.releaseGateRef,
|
|
367
|
+
rollback_ref: input.rollbackRef,
|
|
368
|
+
created_at: input.createdAt,
|
|
369
|
+
expires_at: input.expiresAt,
|
|
370
|
+
default_enablement_requested: input.defaultEnablementRequested,
|
|
371
|
+
kill_switch_state: input.killSwitchState,
|
|
372
|
+
default_managed_dispatch_authority_enabled: authorityEnabled,
|
|
373
|
+
dispatch_authority_enabled: false,
|
|
374
|
+
providerCall: false,
|
|
375
|
+
actualLaneLaunch: false,
|
|
376
|
+
runtimeExecution: false,
|
|
377
|
+
safe_next_actions: authorityEnabled
|
|
378
|
+
? ["/flowdesk-status"]
|
|
379
|
+
: ["/flowdesk-doctor", "/flowdesk-status"],
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
export function validateFlowDeskDefaultManagedDispatchAuthorizationV1(value, expectedWorkflowId) {
|
|
383
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
384
|
+
return invalid("default managed dispatch authorization must be an object");
|
|
385
|
+
const record = value;
|
|
386
|
+
const errors = [];
|
|
387
|
+
const allowed = new Set([
|
|
388
|
+
"schema_version",
|
|
389
|
+
"authorization_id",
|
|
390
|
+
"workflow_id",
|
|
391
|
+
"ok",
|
|
392
|
+
"errors",
|
|
393
|
+
"state",
|
|
394
|
+
"blocked_labels",
|
|
395
|
+
"readiness_ref",
|
|
396
|
+
"actor_ref",
|
|
397
|
+
"profile_ref",
|
|
398
|
+
"release_gate_ref",
|
|
399
|
+
"rollback_ref",
|
|
400
|
+
"created_at",
|
|
401
|
+
"expires_at",
|
|
402
|
+
"default_enablement_requested",
|
|
403
|
+
"kill_switch_state",
|
|
404
|
+
"default_managed_dispatch_authority_enabled",
|
|
405
|
+
"dispatch_authority_enabled",
|
|
406
|
+
"providerCall",
|
|
407
|
+
"actualLaneLaunch",
|
|
408
|
+
"runtimeExecution",
|
|
409
|
+
"safe_next_actions",
|
|
410
|
+
]);
|
|
411
|
+
for (const key of Object.keys(record))
|
|
412
|
+
if (!allowed.has(key))
|
|
413
|
+
errors.push(`unknown properties: ${key}`);
|
|
414
|
+
if (record.schema_version !== "flowdesk.default_managed_dispatch_authorization.v1")
|
|
415
|
+
errors.push("default managed dispatch authorization schema_version is invalid");
|
|
416
|
+
errors.push(...validateOpaqueId(record.authorization_id, "authorization_id").errors, ...validateOpaqueId(record.workflow_id, "workflow_id").errors, ...validateOpaqueRef(record.readiness_ref, "readiness_ref").errors, ...validateOpaqueRef(record.actor_ref, "actor_ref").errors, ...validateOpaqueRef(record.profile_ref, "profile_ref").errors, ...validateOpaqueRef(record.release_gate_ref, "release_gate_ref").errors, ...validateOpaqueRef(record.rollback_ref, "rollback_ref").errors);
|
|
417
|
+
if (expectedWorkflowId !== undefined && record.workflow_id !== expectedWorkflowId)
|
|
418
|
+
errors.push("default managed dispatch authorization workflow_id mismatch");
|
|
419
|
+
if (typeof record.ok !== "boolean")
|
|
420
|
+
errors.push("ok must be boolean");
|
|
421
|
+
if (!Array.isArray(record.errors))
|
|
422
|
+
errors.push("errors must be an array");
|
|
423
|
+
if (!FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_STATES.includes(String(record.state)))
|
|
424
|
+
errors.push("authorization state is invalid");
|
|
425
|
+
if (!Array.isArray(record.blocked_labels))
|
|
426
|
+
errors.push("blocked_labels must be an array");
|
|
427
|
+
else
|
|
428
|
+
for (const label of record.blocked_labels)
|
|
429
|
+
if (!FLOWDESK_DEFAULT_MANAGED_DISPATCH_AUTHORIZATION_BLOCKER_LABELS.includes(label))
|
|
430
|
+
errors.push(`authorization blocked_label is invalid: ${label}`);
|
|
431
|
+
if (typeof record.created_at !== "string" || !validDate(record.created_at))
|
|
432
|
+
errors.push("created_at must be parseable");
|
|
433
|
+
if (typeof record.expires_at !== "string" || !validDate(record.expires_at))
|
|
434
|
+
errors.push("expires_at must be parseable");
|
|
435
|
+
if (typeof record.default_enablement_requested !== "boolean")
|
|
436
|
+
errors.push("default_enablement_requested must be boolean");
|
|
437
|
+
if (record.kill_switch_state !== "inactive" && record.kill_switch_state !== "active")
|
|
438
|
+
errors.push("kill_switch_state is invalid");
|
|
439
|
+
if (typeof record.default_managed_dispatch_authority_enabled !== "boolean")
|
|
440
|
+
errors.push("default_managed_dispatch_authority_enabled must be boolean");
|
|
441
|
+
if (record.state !== "authorized" &&
|
|
442
|
+
record.default_managed_dispatch_authority_enabled === true)
|
|
443
|
+
errors.push("blocked authorization cannot enable default managed dispatch");
|
|
444
|
+
if (record.dispatch_authority_enabled !== false)
|
|
445
|
+
errors.push("default authorization cannot set generic dispatch authority");
|
|
446
|
+
if (record.providerCall !== false)
|
|
447
|
+
errors.push("default authorization cannot make provider calls");
|
|
448
|
+
if (record.actualLaneLaunch !== false)
|
|
449
|
+
errors.push("default authorization cannot launch lanes");
|
|
450
|
+
if (record.runtimeExecution !== false)
|
|
451
|
+
errors.push("default authorization cannot execute runtime");
|
|
452
|
+
if (!Array.isArray(record.safe_next_actions))
|
|
453
|
+
errors.push("safe_next_actions must be an array");
|
|
454
|
+
errors.push(...validateNoForbiddenRawPayloads(record, "default_managed_dispatch_authorization")
|
|
455
|
+
.errors);
|
|
456
|
+
return errors.length === 0 ? valid() : invalid(...errors);
|
|
457
|
+
}
|
|
141
458
|
export function evaluateFlowDeskProductionEnablementV1(input) {
|
|
142
459
|
const errors = [];
|
|
143
460
|
errors.push(...validateOpaqueId(input.workflowId, "workflow_id").errors);
|
|
@@ -174,6 +491,11 @@ export function evaluateFlowDeskProductionEnablementV1(input) {
|
|
|
174
491
|
input.externalAuthPolicyRef,
|
|
175
492
|
"external_auth_policy_ref",
|
|
176
493
|
],
|
|
494
|
+
[
|
|
495
|
+
"sanitized_auth_capture_result_missing",
|
|
496
|
+
input.sanitizedAuthCaptureRef,
|
|
497
|
+
"sanitized_auth_capture_ref",
|
|
498
|
+
],
|
|
177
499
|
["provider_policy_missing", input.providerPolicyRef, "provider_policy_ref"],
|
|
178
500
|
];
|
|
179
501
|
for (const [blocker, ref, label] of requiredRefs) {
|
|
@@ -183,6 +505,64 @@ export function evaluateFlowDeskProductionEnablementV1(input) {
|
|
|
183
505
|
errors.push(...refResult.errors);
|
|
184
506
|
}
|
|
185
507
|
}
|
|
508
|
+
const configuredVerificationResult = input.configuredVerificationResult;
|
|
509
|
+
let validConfiguredVerificationResult;
|
|
510
|
+
if (configuredVerificationResult !== undefined) {
|
|
511
|
+
const verificationResult = validateFlowDeskConfiguredVerificationResultV1(configuredVerificationResult, input.workflowId, input.configuredVerificationRef);
|
|
512
|
+
errors.push(...verificationResult.errors);
|
|
513
|
+
if (!verificationResult.ok)
|
|
514
|
+
blockerLabels.push("configured_verification_invalid");
|
|
515
|
+
else if (input.configuredVerificationRef !== undefined)
|
|
516
|
+
validConfiguredVerificationResult = configuredVerificationResult;
|
|
517
|
+
if (verificationResult.ok && configuredVerificationResult.result !== "passed")
|
|
518
|
+
blockerLabels.push("configured_verification_failed");
|
|
519
|
+
}
|
|
520
|
+
if (input.configuredVerificationRef !== undefined) {
|
|
521
|
+
if (validConfiguredVerificationResult === undefined) {
|
|
522
|
+
blockerLabels.push("configured_verification_result_missing");
|
|
523
|
+
if (configuredVerificationResult === undefined)
|
|
524
|
+
errors.push("configured verification result is required");
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
const sanitizedAuthCaptureResult = input.sanitizedAuthCaptureResult;
|
|
528
|
+
let validSanitizedAuthCaptureResult;
|
|
529
|
+
if (sanitizedAuthCaptureResult !== undefined) {
|
|
530
|
+
const captureResult = validateFlowDeskSanitizedAuthCaptureResultV1(sanitizedAuthCaptureResult, input.workflowId, input.sanitizedAuthCaptureRef);
|
|
531
|
+
errors.push(...captureResult.errors);
|
|
532
|
+
if (!captureResult.ok)
|
|
533
|
+
blockerLabels.push("sanitized_auth_capture_invalid");
|
|
534
|
+
else if (input.sanitizedAuthCaptureRef !== undefined)
|
|
535
|
+
validSanitizedAuthCaptureResult = sanitizedAuthCaptureResult;
|
|
536
|
+
if (captureResult.ok && sanitizedAuthCaptureResult.result !== "passed")
|
|
537
|
+
blockerLabels.push("sanitized_auth_capture_failed");
|
|
538
|
+
}
|
|
539
|
+
if (input.sanitizedAuthCaptureRef !== undefined) {
|
|
540
|
+
if (validSanitizedAuthCaptureResult === undefined) {
|
|
541
|
+
blockerLabels.push("sanitized_auth_capture_result_missing");
|
|
542
|
+
if (sanitizedAuthCaptureResult === undefined)
|
|
543
|
+
errors.push("sanitized auth capture result is required");
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const externalAuthProviderPolicyResult = input.externalAuthProviderPolicyResult;
|
|
547
|
+
let validExternalAuthProviderPolicyResult;
|
|
548
|
+
if (externalAuthProviderPolicyResult !== undefined) {
|
|
549
|
+
const policyResult = validateFlowDeskExternalAuthProviderPolicyResultV1(externalAuthProviderPolicyResult, input.workflowId, input.externalAuthPolicyRef, input.providerPolicyRef);
|
|
550
|
+
errors.push(...policyResult.errors);
|
|
551
|
+
if (!policyResult.ok)
|
|
552
|
+
blockerLabels.push("external_auth_provider_policy_invalid");
|
|
553
|
+
else if (input.externalAuthPolicyRef !== undefined &&
|
|
554
|
+
input.providerPolicyRef !== undefined)
|
|
555
|
+
validExternalAuthProviderPolicyResult = externalAuthProviderPolicyResult;
|
|
556
|
+
if (policyResult.ok && externalAuthProviderPolicyResult.result !== "passed")
|
|
557
|
+
blockerLabels.push("external_auth_provider_policy_failed");
|
|
558
|
+
}
|
|
559
|
+
if (input.externalAuthPolicyRef !== undefined &&
|
|
560
|
+
input.providerPolicyRef !== undefined &&
|
|
561
|
+
validExternalAuthProviderPolicyResult === undefined) {
|
|
562
|
+
blockerLabels.push("external_auth_provider_policy_result_missing");
|
|
563
|
+
if (externalAuthProviderPolicyResult === undefined)
|
|
564
|
+
errors.push("external auth provider policy result is required");
|
|
565
|
+
}
|
|
186
566
|
const laneConformanceRefs = input.laneConformanceRefs ?? [];
|
|
187
567
|
if (laneConformanceRefs.length === 0) {
|
|
188
568
|
if (input.allowIncompleteConformance === true)
|
|
@@ -202,11 +582,16 @@ export function evaluateFlowDeskProductionEnablementV1(input) {
|
|
|
202
582
|
...evidenceRefsFromReload(input.evidenceReload),
|
|
203
583
|
input.preDispatchAuditRef,
|
|
204
584
|
input.configuredVerificationRef,
|
|
585
|
+
...(validConfiguredVerificationResult?.evidence_refs ?? []),
|
|
586
|
+
input.sanitizedAuthCaptureRef,
|
|
587
|
+
...(validSanitizedAuthCaptureResult?.evidence_refs ?? []),
|
|
205
588
|
input.externalAuthPolicyRef,
|
|
206
589
|
input.providerPolicyRef,
|
|
590
|
+
...(validExternalAuthProviderPolicyResult?.evidence_refs ?? []),
|
|
207
591
|
...laneConformanceRefs,
|
|
208
592
|
].filter((ref) => typeof ref === "string"));
|
|
209
593
|
const approval = input.approvalDecision;
|
|
594
|
+
let validApprovalDecision;
|
|
210
595
|
if (approval === undefined) {
|
|
211
596
|
if (blockerLabels.length === 0)
|
|
212
597
|
blockerLabels.push("approval_missing");
|
|
@@ -216,14 +601,17 @@ export function evaluateFlowDeskProductionEnablementV1(input) {
|
|
|
216
601
|
errors.push(...approvalResult.errors);
|
|
217
602
|
if (!approvalResult.ok)
|
|
218
603
|
blockerLabels.push("approval_mismatched");
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
604
|
+
else {
|
|
605
|
+
validApprovalDecision = approval;
|
|
606
|
+
if (approval.decision !== "approve")
|
|
607
|
+
blockerLabels.push("approval_denied");
|
|
608
|
+
if (approval.missing_evidence_labels.length > 0)
|
|
609
|
+
blockerLabels.push(...approval.missing_evidence_labels);
|
|
610
|
+
const missingRefs = missingRequiredApprovalRefs(approval, evidenceRefs);
|
|
611
|
+
if (missingRefs.length > 0)
|
|
612
|
+
blockerLabels.push("approval_required_refs_missing");
|
|
613
|
+
uncertaintyLabels.push(...approval.uncertainty_labels);
|
|
614
|
+
}
|
|
227
615
|
}
|
|
228
616
|
const uniqueBlockers = unique(blockerLabels);
|
|
229
617
|
const uniqueUncertainties = unique(uncertaintyLabels);
|
|
@@ -251,6 +639,31 @@ export function evaluateFlowDeskProductionEnablementV1(input) {
|
|
|
251
639
|
managed_dispatch_ready: errors.length === 0 && state === "dispatch_capable",
|
|
252
640
|
dispatch_authority_enabled: false,
|
|
253
641
|
default_release1_non_dispatch_preserved: true,
|
|
642
|
+
...(validConfiguredVerificationResult === undefined
|
|
643
|
+
? {}
|
|
644
|
+
: {
|
|
645
|
+
configured_verification_result: validConfiguredVerificationResult.result,
|
|
646
|
+
configured_verification_ref: validConfiguredVerificationResult.verification_ref,
|
|
647
|
+
}),
|
|
648
|
+
...(validExternalAuthProviderPolicyResult === undefined
|
|
649
|
+
? {}
|
|
650
|
+
: {
|
|
651
|
+
external_auth_provider_policy_result: validExternalAuthProviderPolicyResult.result,
|
|
652
|
+
external_auth_policy_ref: validExternalAuthProviderPolicyResult.external_auth_policy_ref,
|
|
653
|
+
provider_policy_ref: validExternalAuthProviderPolicyResult.provider_policy_ref,
|
|
654
|
+
}),
|
|
655
|
+
...(validSanitizedAuthCaptureResult === undefined
|
|
656
|
+
? {}
|
|
657
|
+
: {
|
|
658
|
+
sanitized_auth_capture_result: validSanitizedAuthCaptureResult.result,
|
|
659
|
+
sanitized_auth_capture_ref: validSanitizedAuthCaptureResult.sanitized_auth_capture_ref,
|
|
660
|
+
}),
|
|
661
|
+
...(validApprovalDecision === undefined
|
|
662
|
+
? {}
|
|
663
|
+
: {
|
|
664
|
+
approval_decision: validApprovalDecision.decision,
|
|
665
|
+
approval_ref: validApprovalDecision.approval_id,
|
|
666
|
+
}),
|
|
254
667
|
safe_next_actions: state === "dispatch_capable"
|
|
255
668
|
? ["/flowdesk-status"]
|
|
256
669
|
: ["/flowdesk-doctor", "/flowdesk-status"],
|