@wildo-ai/saas-backend-lib 1.1.12 → 1.1.13
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/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +2 -0
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts +4 -0
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js +20 -5
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts +3 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js +10 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts +22 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js +25 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts +38 -3
- package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js +68 -5
- package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts +2 -2
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +6 -3
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +83 -0
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +217 -14
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts +32 -0
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js +36 -0
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts +38 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js +83 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts +36 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js +51 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts +46 -0
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js +68 -0
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts +27 -0
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js +42 -3
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts +26 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js +10 -0
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts +10 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js +60 -28
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts +90 -0
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js +373 -0
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js.map +1 -0
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts +29 -2
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.js +40 -3
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js +34 -6
- package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts +30 -6
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js +67 -22
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js +18 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts +66 -1
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js +161 -14
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts +47 -0
- package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.js.map +1 -1
- package/dist/esm/external-providers/services/content-safety.backend.service.d.ts +27 -2
- package/dist/esm/external-providers/services/content-safety.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/content-safety.backend.service.js +46 -1
- package/dist/esm/external-providers/services/content-safety.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/embeddings.backend.service.js +2 -0
- package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +11 -0
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +23 -0
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts +19 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts.map +1 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.js +41 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.js.map +1 -1
- package/dist/esm/files/utils/file-parent-read-context.backend.d.ts +27 -2
- package/dist/esm/files/utils/file-parent-read-context.backend.d.ts.map +1 -1
- package/dist/esm/files/utils/file-parent-read-context.backend.js +23 -4
- package/dist/esm/files/utils/file-parent-read-context.backend.js.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts +26 -0
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js +100 -8
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts +3 -1
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js +8 -2
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js.map +1 -1
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +43 -0
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +37 -0
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts +7 -0
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js +8 -3
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts +31 -6
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.js +78 -30
- package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js +4 -0
- package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +28 -2
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +132 -22
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js +12 -8
- package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +5 -0
- package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/flows-actors-registry.service.js +18 -2
- package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +33 -0
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +58 -0
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts +12 -1
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js +23 -4
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts +12 -1
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js +55 -17
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts +22 -1
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js +52 -9
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts +79 -0
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts.map +1 -0
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js +211 -0
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js.map +1 -0
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts +2 -2
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js +9 -1
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/inject/models/container.d.ts.map +1 -1
- package/dist/esm/inject/models/container.js +6 -0
- package/dist/esm/inject/models/container.js.map +1 -1
- package/dist/esm/inject/models/service-types.d.ts +5 -0
- package/dist/esm/inject/models/service-types.d.ts.map +1 -1
- package/dist/esm/inject/models/service-types.js +3 -0
- package/dist/esm/inject/models/service-types.js.map +1 -1
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +5 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts +34 -1
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.js +49 -0
- package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +6 -1
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +15 -4
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js +3 -1
- package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/runtime/services/http-server.backend.service.d.ts +3 -1
- package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
- package/dist/esm/runtime/services/http-server.backend.service.js +11 -3
- package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts +22 -0
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts.map +1 -1
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js +54 -0
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts +51 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js +87 -15
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js +5 -2
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +65 -24
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +64 -1
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +84 -2
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +14 -0
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +13 -5
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js +6 -2
- package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts +7 -0
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js +65 -20
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js +11 -4
- package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -1
- package/dist/esm/users/services/user-self-custom-implementations.backend.js +4 -2
- package/dist/esm/users/services/user-self-custom-implementations.backend.js.map +1 -1
- package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js +16 -0
- package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +10 -10
|
@@ -17,9 +17,20 @@
|
|
|
17
17
|
* Fail closed at use, warn at boot: the report never throws and never stops startup. The remedy (select a classifier for
|
|
18
18
|
* this environment, or remove the declaration) is an edit to configuration, and a refused boot would also take down
|
|
19
19
|
* everything the application serves that does not need a classifier.
|
|
20
|
+
*
|
|
21
|
+
* ## An environment may declare that its agents run unguarded
|
|
22
|
+
*
|
|
23
|
+
* `agentContentGuardrails: { withoutClassifier: RUN_UNGUARDED, reason }` in `wildo.infra.<env>.config.ts` (see
|
|
24
|
+
* `EnvironmentAgentContentGuardrailsSchema` in `@wildo-ai/saas-models`). Where it is declared and NO selected classifier
|
|
25
|
+
* offers a guardrail, the predicate below still reports the gap, and marks it `runsUnguarded`: the agent's turn then runs
|
|
26
|
+
* without that guardrail, and the boot report names the agent as UNGUARDED (with the environment's reason) instead of as
|
|
27
|
+
* refusing. "No classifier" means none is PRESENT for the guardrail (`ContentSafetyBackendService.classifierPresentFor`):
|
|
28
|
+
* none declared, the selected one does not offer it, or its credentials are not authored in this environment. A
|
|
29
|
+
* classifier that is there and cannot be used (declared and not loaded, a category it does not assess) is never waived,
|
|
30
|
+
* and one that fails at call time (a key set and refused, an outage) still withholds: those are failures.
|
|
20
31
|
*/
|
|
21
|
-
import { ContentSafety_HarmCategory } from '@wildo-ai/external-connectors-models';
|
|
22
|
-
import { FlowsActors_Agent_Status, isLLMAgentConfiguration, outputModerationCategories } from '@wildo-ai/saas-models';
|
|
32
|
+
import { ContentSafety_HarmCategory, ContentSafetyProvider_OperationKey } from '@wildo-ai/external-connectors-models';
|
|
33
|
+
import { AgentContentGuardrailsWithoutClassifier, EnvironmentAgentContentGuardrailsReadingKind, FlowsActors_Agent_Status, isLLMAgentConfiguration, outputModerationCategories, } from '@wildo-ai/saas-models';
|
|
23
34
|
import { describeCaughtError, projectCaughtErrorLogFields } from '../../errors/utils/error-log-level-classification.backend.utils.js';
|
|
24
35
|
/** The content guardrails that need a classifier, named by their key in `contentGuardrails`. */
|
|
25
36
|
export var ClassifierBackedContentGuardrail;
|
|
@@ -55,6 +66,37 @@ export function contentGuardrailClassifierGapOf(contentSafety, guardrail, holder
|
|
|
55
66
|
if (!contentSafety) {
|
|
56
67
|
return { gap: ContentGuardrailClassifierGap.NO_CONTENT_SAFETY_SERVICE, reason: `${holder} binds no content-safety service` };
|
|
57
68
|
}
|
|
69
|
+
const unavailability = classifierGapOfBoundService(contentSafety, guardrail, holder);
|
|
70
|
+
if (unavailability === undefined)
|
|
71
|
+
return undefined;
|
|
72
|
+
const runsUnguarded = environmentRunsGuardrailUnguarded(contentSafety, guardrail);
|
|
73
|
+
return runsUnguarded === undefined ? unavailability : { ...unavailability, runsUnguarded };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The environment's waiver for `guardrail`, when it declared one and no selected classifier offers the guardrail. The ONE
|
|
77
|
+
* place the waiver is decided, so the turn, the boot report and the inbound-delivery screening cannot disagree.
|
|
78
|
+
*/
|
|
79
|
+
function environmentRunsGuardrailUnguarded(contentSafety, guardrail) {
|
|
80
|
+
// A content-safety service that does not expose the declaration (a partial stand-in) waives nothing: fail closed.
|
|
81
|
+
if (typeof contentSafety.agentGuardrailsWithoutClassifier !== 'function' || typeof contentSafety.classifierPresentFor !== 'function')
|
|
82
|
+
return undefined;
|
|
83
|
+
const reading = contentSafety.agentGuardrailsWithoutClassifier();
|
|
84
|
+
if (reading.kind === EnvironmentAgentContentGuardrailsReadingKind.UNREADABLE)
|
|
85
|
+
return undefined;
|
|
86
|
+
const declaration = reading.declaration;
|
|
87
|
+
if (declaration.withoutClassifier !== AgentContentGuardrailsWithoutClassifier.RUN_UNGUARDED)
|
|
88
|
+
return undefined;
|
|
89
|
+
// Per GUARDRAIL, never per category: a classifier that moderates some of the agent's categories and not others is a
|
|
90
|
+
// mismatch the operator fixes (narrow the policy, or select one that assesses them), so the agent is refused. Waiving
|
|
91
|
+
// there would switch off the categories it CAN judge too. Absent here means: none declared, the selected one does not
|
|
92
|
+
// offer the guardrail, or its credentials are not authored in this environment (`classifierPresentFor`).
|
|
93
|
+
const offered = contentSafety.classifierPresentFor(guardrail.kind === ClassifierBackedContentGuardrail.PROMPT_INJECTION
|
|
94
|
+
? ContentSafetyProvider_OperationKey.SCREEN_PROMPT_INJECTION
|
|
95
|
+
: ContentSafetyProvider_OperationKey.MODERATE_OUTPUT);
|
|
96
|
+
return offered ? undefined : { declaredReason: declaration.reason };
|
|
97
|
+
}
|
|
98
|
+
/** {@link contentGuardrailClassifierGapOf} for a process that binds the service. */
|
|
99
|
+
function classifierGapOfBoundService(contentSafety, guardrail, holder) {
|
|
58
100
|
if (!contentSafety.recordsScreenings()) {
|
|
59
101
|
// R7: every screening and judgement leaves a provider-call record; a process that cannot write one does neither.
|
|
60
102
|
const act = guardrail.kind === ClassifierBackedContentGuardrail.PROMPT_INJECTION ? 'a screening' : 'a judgement';
|
|
@@ -134,15 +176,28 @@ export function reportUnservableAgentContentGuardrails(input) {
|
|
|
134
176
|
&& (agent.contentGuardrails?.promptInjection !== undefined || agent.contentGuardrails?.outputModeration !== undefined));
|
|
135
177
|
// Resolved only when an agent needs it: an application with no guarded agent asks the container nothing.
|
|
136
178
|
const contentSafety = guarded.length > 0 ? input.resolveContentSafety() : undefined;
|
|
179
|
+
reportUnreadableGuardrailDeclaration(contentSafety, input.logger);
|
|
137
180
|
for (const agent of guarded) {
|
|
138
181
|
const unservable = unservableAgentContentGuardrails(agent, contentSafety);
|
|
139
182
|
if (unservable.length === 0)
|
|
140
183
|
continue;
|
|
141
184
|
findings.push(...unservable);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
185
|
+
const refused = unservable.filter((entry) => entry.runsUnguarded === undefined);
|
|
186
|
+
const unguarded = unservable.filter((entry) => entry.runsUnguarded !== undefined);
|
|
187
|
+
if (refused.length > 0) {
|
|
188
|
+
input.logger.warn(describeUnservableAgent(agent.ref, refused), {
|
|
189
|
+
agentRef: agent.ref,
|
|
190
|
+
guardrails: refused.map(({ guardrail, gap, reason }) => ({ guardrail, gap, reason })),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (unguarded.length > 0) {
|
|
194
|
+
input.logger.warn(describeUnguardedAgent(agent.ref, unguarded), {
|
|
195
|
+
agentRef: agent.ref,
|
|
196
|
+
runsUnguarded: true,
|
|
197
|
+
declaredReason: unguarded[0].runsUnguarded.declaredReason,
|
|
198
|
+
guardrails: unguarded.map(({ guardrail, gap, reason }) => ({ guardrail, gap, reason })),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
146
201
|
}
|
|
147
202
|
if (findings.length === 0) {
|
|
148
203
|
input.logger.debug('Every agent declaring a classifier-backed content guardrail can be served in this environment');
|
|
@@ -173,6 +228,36 @@ function describeUnservableAgent(agentRef, unservable) {
|
|
|
173
228
|
return `Agent '${agentRef}' declares ${declared}, and no classifier can serve ${unservable.length === 1 ? 'it' : 'them'} in this environment, `
|
|
174
229
|
+ `so the agent REFUSES EVERY TURN here (it does not run unguarded). ${reasons.join(' ')}`;
|
|
175
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* The WARN line for an agent this environment runs unguarded: what it declares, that it runs WITHOUT it here, and the
|
|
233
|
+
* environment's own reason. A WARN on every boot, on purpose: running an agent that declares a guardrail without it is a
|
|
234
|
+
* decision someone must keep seeing until a classifier is selected or the declaration is removed.
|
|
235
|
+
*/
|
|
236
|
+
function describeUnguardedAgent(agentRef, unguarded) {
|
|
237
|
+
const declared = unguarded.map((entry) => `contentGuardrails.${entry.guardrail}`).join(' and ');
|
|
238
|
+
return `Agent '${agentRef}' declares ${declared}, no classifier serves ${unguarded.length === 1 ? 'it' : 'them'} in this environment, `
|
|
239
|
+
+ 'and the environment declares agentContentGuardrails.withoutClassifier = run_unguarded, so the agent RUNS UNGUARDED here '
|
|
240
|
+
+ `(its ${unguarded.map((entry) => GUARDRAIL_EFFECT[entry.guardrail]).join(' and ')}). The environment's reason: `
|
|
241
|
+
+ `"${unguarded[0].runsUnguarded.declaredReason}". Select a provider for AI_CONTENT_SAFETY here to enforce it.`;
|
|
242
|
+
}
|
|
243
|
+
/** What running without each guardrail means, in a reader's words. TOTAL over the enum. */
|
|
244
|
+
const GUARDRAIL_EFFECT = {
|
|
245
|
+
[ClassifierBackedContentGuardrail.PROMPT_INJECTION]: 'tool results and inbound deliveries reach its model unscreened',
|
|
246
|
+
[ClassifierBackedContentGuardrail.OUTPUT_MODERATION]: 'replies, reasoning and tool inputs leave it unmoderated',
|
|
247
|
+
};
|
|
248
|
+
/**
|
|
249
|
+
* One WARN when the environment's declaration (`WILDO_AGENT_CONTENT_GUARDRAILS`) does not parse. The runtime then reads
|
|
250
|
+
* it as REFUSE, which is safe, but an operator who declared RUN_UNGUARDED would otherwise see agents refusing with no
|
|
251
|
+
* word about why their declaration was ignored.
|
|
252
|
+
*/
|
|
253
|
+
function reportUnreadableGuardrailDeclaration(contentSafety, logger) {
|
|
254
|
+
const reading = typeof contentSafety?.agentGuardrailsWithoutClassifier === 'function' ? contentSafety.agentGuardrailsWithoutClassifier() : undefined;
|
|
255
|
+
if (reading?.kind !== EnvironmentAgentContentGuardrailsReadingKind.UNREADABLE)
|
|
256
|
+
return;
|
|
257
|
+
logger.warn(`The environment's agentContentGuardrails declaration could not be read (${reading.problem}), so agents whose guardrails `
|
|
258
|
+
+ 'no classifier serves REFUSE their turns here. Correct `agentContentGuardrails` in this environment\'s wildo.infra.<env>.config.ts '
|
|
259
|
+
+ 'and run `wildo config sync`.');
|
|
260
|
+
}
|
|
176
261
|
/**
|
|
177
262
|
* The organization agent policies that switch prompt-injection screening on: `promptInjectionScreening` set. A raw filter
|
|
178
263
|
* both adapters translate (`IS NOT NULL` on PostgreSQL's text column).
|
|
@@ -226,10 +311,17 @@ export async function reportOrganizationAgentPoliciesNoClassifierServes(input) {
|
|
|
226
311
|
&& !(screeningGap && policy.promptInjectionScreening != null)).length;
|
|
227
312
|
}
|
|
228
313
|
if (unservable > 0) {
|
|
314
|
+
// Under an environment that declares run_unguarded, a guardrail no classifier offers is not refused: the turn runs
|
|
315
|
+
// without it (the predicate's `runsUnguarded`). Said as such, or the operator reads a refusal that is not happening.
|
|
316
|
+
// A category the provider does not assess is never waived (the waiver is per guardrail), so those rows refuse.
|
|
317
|
+
const waiver = [screeningGap, moderationGap].find((gap) => gap?.runsUnguarded !== undefined)?.runsUnguarded;
|
|
318
|
+
const refusing = unassessedCategories.length > 0 || [screeningGap, moderationGap].some((gap) => gap !== undefined && gap.runsUnguarded === undefined);
|
|
229
319
|
input.logger.warn(`${unservable} organization agent ${unservable === 1 ? 'policy switches' : 'policies switch'} on prompt-injection screening or output `
|
|
230
320
|
+ 'moderation that no classifier can serve in this environment, so every agent turn acting for '
|
|
231
|
-
+ `${unservable === 1 ? 'that organization' : 'those organizations'}
|
|
232
|
-
|
|
321
|
+
+ `${unservable === 1 ? 'that organization' : 'those organizations'} ${waiver !== undefined && !refusing
|
|
322
|
+
? `RUNS UNGUARDED: the environment declares agentContentGuardrails.withoutClassifier = run_unguarded ("${waiver.declaredReason}")`
|
|
323
|
+
: 'is REFUSED'}. ${(screeningGap ?? moderationGap)?.reason ?? 'A harm category a policy names is not assessed by the selected provider'}. `
|
|
324
|
+
+ 'Make a provider serve AI_CONTENT_SAFETY here (or fix what the reason names); the organization\'s administrator can relax the policy.', { unservableOrganizationAgentPolicyCount: unservable, ...(waiver !== undefined && !refusing ? { runsUnguarded: true } : {}) });
|
|
233
325
|
}
|
|
234
326
|
return unservable;
|
|
235
327
|
}
|
package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classifier-availability.backend.utils.js","sourceRoot":"","sources":["../../../../src/flows-actors/content-guardrails/classifier-availability.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * #2292 — whether a classifier can serve an agent's classifier-backed content guardrails in THIS process, and the boot\n * report that says so before any turn does.\n *\n * Two guardrails need a classifier (a provider for `EngineCapability.AI_CONTENT_SAFETY`): prompt-injection screening\n * (`contentGuardrails.promptInjection`) and output moderation (`contentGuardrails.outputModeration`). Where none can\n * serve them, an agent declaring either refuses every invocation (`AgentsBackendService.toolResultScreenOf` and\n * `outputModerationGuardOf`), and an organization's agent policy asking for either is refused when it is written\n * (`classifierRefusalOf`). That is correct and stays: running unscreened or unmoderated is what the declaration exists\n * to prevent.\n *\n * What was missing is the signal. An application that selects a classifier in one environment and not in another booted\n * the other one without a word, and its guarded agents' first failed turn was the only report. So the ONE predicate the\n * runtime refuses on lives here, and startup runs it over every registered agent ({@link reportUnservableAgentContentGuardrails}):\n * the boot and the turn cannot disagree about which agents refuse, because they ask the same function.\n *\n * Fail closed at use, warn at boot: the report never throws and never stops startup. The remedy (select a classifier for\n * this environment, or remove the declaration) is an edit to configuration, and a refused boot would also take down\n * everything the application serves that does not need a classifier.\n */\nimport { ContentSafety_HarmCategory } from '@wildo-ai/external-connectors-models';\nimport { FlowsActors_Agent_Status, isLLMAgentConfiguration, outputModerationCategories, type FlowsActors_Agent } from '@wildo-ai/saas-models';\nimport { type ContentSafetyBackendService } from '~wildo-backend-lib/external-providers/services/content-safety.backend.service';\nimport { describeCaughtError, projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\n\n/** The content guardrails that need a classifier, named by their key in `contentGuardrails`. */\nexport enum ClassifierBackedContentGuardrail {\n /** `contentGuardrails.promptInjection`: what somebody else wrote is screened before the model reads it. */\n PROMPT_INJECTION = 'promptInjection',\n /** `contentGuardrails.outputModeration`: what the model writes is judged before anyone reads it. */\n OUTPUT_MODERATION = 'outputModeration',\n}\n\n/**\n * Why no classifier can serve a guardrail here. Kept apart because each has its own remedy: two are about how the\n * process was assembled, two about the environment's provider configuration.\n */\nexport enum ContentGuardrailClassifierGap {\n /** The container binds no `ContentSafetyService`. The engine's default container binds it; a custom one may not. */\n NO_CONTENT_SAFETY_SERVICE = 'no_content_safety_service',\n /** No provider-call recorder is bound, so a screening or judgement could not be shown to have happened (#2292 R7). */\n NO_PROVIDER_CALL_RECORDER = 'no_provider_call_recorder',\n /** No provider serves `AI_CONTENT_SAFETY` in this runtime: the capability is off, or no provider in scope serves it. */\n NO_PROVIDER_SELECTED = 'no_provider_selected',\n /** A provider serves it and cannot be used: no such operation, an unassessed category, its API key or host slot not set, … */\n SELECTED_PROVIDER_CANNOT_SERVE = 'selected_provider_cannot_serve',\n}\n\n/** One guardrail no classifier can serve, with the sentence the runtime refuses with. */\nexport interface ContentGuardrailClassifierUnavailability {\n readonly gap: ContentGuardrailClassifierGap;\n /** The reason, in the runtime's words: it is the clause after \"cannot be screened:\" in the refusal. */\n readonly reason: string;\n}\n\n/**\n * Why `contentSafety` cannot serve `guardrail`, or `undefined` when it can. The ONE predicate: the runtime refuses an\n * invocation on it, an organization's agent policy is refused on it, and the boot report runs it over every agent.\n *\n * `holder` names what is missing the service or the recorder in the reason (\"this process\" at run time and at boot, \"this\n * application\" where an administrator reads it).\n */\nexport function contentGuardrailClassifierGapOf(\n contentSafety: ContentSafetyBackendService | undefined,\n guardrail: { readonly kind: ClassifierBackedContentGuardrail.PROMPT_INJECTION } | {\n readonly kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION;\n readonly categories: readonly ContentSafety_HarmCategory[];\n },\n holder = 'this process',\n): ContentGuardrailClassifierUnavailability | undefined {\n if (!contentSafety) {\n return { gap: ContentGuardrailClassifierGap.NO_CONTENT_SAFETY_SERVICE, reason: `${holder} binds no content-safety service` };\n }\n if (!contentSafety.recordsScreenings()) {\n // R7: every screening and judgement leaves a provider-call record; a process that cannot write one does neither.\n const act = guardrail.kind === ClassifierBackedContentGuardrail.PROMPT_INJECTION ? 'a screening' : 'a judgement';\n return { gap: ContentGuardrailClassifierGap.NO_PROVIDER_CALL_RECORDER, reason: `${holder} records no provider calls, so ${act} could not be recorded` };\n }\n try {\n const binding = guardrail.kind === ClassifierBackedContentGuardrail.PROMPT_INJECTION\n ? contentSafety.resolvePromptInjectionBinding()\n : contentSafety.resolveOutputModerationBinding(guardrail.categories);\n if (!binding.configured) return { gap: ContentGuardrailClassifierGap.NO_PROVIDER_SELECTED, reason: 'no provider is selected for AI_CONTENT_SAFETY' };\n } catch (error) {\n // A selected provider that cannot serve throws a named CONFIGURATION error: an operator's mistake, never an absence.\n // Its own sentence, without the closing period: every caller writes the reason as a clause (\"…: <reason>. It is not run.\").\n return { gap: ContentGuardrailClassifierGap.SELECTED_PROVIDER_CANNOT_SERVE, reason: describeCaughtError(error).replace(/[.\\s]+$/u, '') };\n }\n return undefined;\n}\n\n/** One guardrail an agent declares that no classifier can serve here. */\nexport interface UnservableAgentContentGuardrail extends ContentGuardrailClassifierUnavailability {\n readonly agentRef: string;\n readonly guardrail: ClassifierBackedContentGuardrail;\n /** What the operator does about it. */\n readonly remedy: string;\n}\n\n/** What to do about a gap, said once so the boot report and anything else that names it agree. */\nexport function contentGuardrailClassifierGapRemedy(gap: ContentGuardrailClassifierGap, guardrail: ClassifierBackedContentGuardrail): string {\n const orRemove = `or remove \\`contentGuardrails.${guardrail}\\` from the agent`;\n switch (gap) {\n case ContentGuardrailClassifierGap.NO_CONTENT_SAFETY_SERVICE:\n return `Bind SAAS_SERVICE_TYPES.ContentSafetyService in this runtime's container (the engine's default container does), ${orRemove}.`;\n case ContentGuardrailClassifierGap.NO_PROVIDER_CALL_RECORDER:\n return `Bind SAAS_SERVICE_TYPES.ProviderCallRecorder in this runtime's container (the engine's default container does), ${orRemove}.`;\n case ContentGuardrailClassifierGap.NO_PROVIDER_SELECTED:\n // A selection only REORDERS the providers that serve: what makes one serve is the capability being enabled and the\n // provider being in this runtime's scope with that capability.\n return 'Enable EngineCapability.AI_CONTENT_SAFETY and give this runtime\\'s provider scope a provider that serves it (its scope entry lists '\n + `AI_CONTENT_SAFETY); \\`providerSelection\\` in \\`wildo.infra.<env>.config.ts\\` only chooses among the providers that already serve, ${orRemove}.`;\n case ContentGuardrailClassifierGap.SELECTED_PROVIDER_CANNOT_SERVE:\n return `Fix what the reason names in this environment's provider configuration or secrets (an unset API key or host slot is one), `\n + `make a provider that can serve it the one asked first, ${orRemove}.`;\n default: {\n const unknownGap: never = gap;\n return `Unknown gap ${String(unknownGap)}.`;\n }\n }\n}\n\n/**\n * Every classifier-backed guardrail `agent` DECLARES that `contentSafety` cannot serve, empty when it can serve them all\n * (or the agent declares none). The agent's own declaration only: an organization's policy can switch a guardrail on for\n * the turns acting for it, and is read per turn, never at boot (see {@link reportUnservableAgentContentGuardrails}).\n */\nexport function unservableAgentContentGuardrails(\n agent: Pick<FlowsActors_Agent, 'ref' | 'contentGuardrails'>,\n contentSafety: ContentSafetyBackendService | undefined,\n): UnservableAgentContentGuardrail[] {\n const unservable: UnservableAgentContentGuardrail[] = [];\n const add = (guardrail: ClassifierBackedContentGuardrail, unavailability: ContentGuardrailClassifierUnavailability | undefined): void => {\n if (unavailability) unservable.push({ agentRef: agent.ref, guardrail, ...unavailability, remedy: contentGuardrailClassifierGapRemedy(unavailability.gap, guardrail) });\n };\n if (agent.contentGuardrails?.promptInjection) {\n add(ClassifierBackedContentGuardrail.PROMPT_INJECTION,\n contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.PROMPT_INJECTION }));\n }\n const moderation = agent.contentGuardrails?.outputModeration?.blockAtOrAbove;\n if (moderation) {\n add(ClassifierBackedContentGuardrail.OUTPUT_MODERATION,\n contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION, categories: outputModerationCategories(moderation) }));\n }\n return unservable;\n}\n\n/**\n * The boot report: one WARN per agent that declares a classifier-backed guardrail no classifier can serve in this\n * process, naming the agent, the guardrail, why, and what to do. Returns the findings; NEVER throws, because a\n * diagnostic must never be why startup fails (the remedy is a configuration edit, and the rest of the application runs\n * without a classifier).\n *\n * Reads the registered ACTIVE language-model agents: an inactive agent is never invoked, and only a language-model agent\n * runs guardrails (registration refuses one on any other). Organization agent policies are per-tenant rows and are not\n * read here; a policy asking for a guardrail was refused when written unless a classifier could serve it then, and an\n * agent it switches on refuses its turns exactly as a declaring agent does.\n */\nexport function reportUnservableAgentContentGuardrails(input: {\n /** The registered agents. A function, so a registry that cannot be read is reported here rather than thrown at startup. */\n readonly readAgents: () => readonly FlowsActors_Agent[];\n /** The process's content-safety service, `undefined` when none is bound. A function for the same reason. */\n readonly resolveContentSafety: () => ContentSafetyBackendService | undefined;\n readonly logger: Pick<LoggerService, 'warn' | 'debug'>;\n}): UnservableAgentContentGuardrail[] {\n try {\n const findings: UnservableAgentContentGuardrail[] = [];\n const guarded = input.readAgents().filter((agent) => agent.status === FlowsActors_Agent_Status.ACTIVE && isLLMAgentConfiguration(agent.config)\n && (agent.contentGuardrails?.promptInjection !== undefined || agent.contentGuardrails?.outputModeration !== undefined));\n // Resolved only when an agent needs it: an application with no guarded agent asks the container nothing.\n const contentSafety = guarded.length > 0 ? input.resolveContentSafety() : undefined;\n for (const agent of guarded) {\n const unservable = unservableAgentContentGuardrails(agent, contentSafety);\n if (unservable.length === 0) continue;\n findings.push(...unservable);\n input.logger.warn(describeUnservableAgent(agent.ref, unservable), {\n agentRef: agent.ref,\n guardrails: unservable.map(({ guardrail, gap, reason }) => ({ guardrail, gap, reason })),\n });\n }\n if (findings.length === 0) {\n input.logger.debug('Every agent declaring a classifier-backed content guardrail can be served in this environment');\n }\n return findings;\n } catch (error) {\n // WARN, not debug: a report that did not run says nothing, and silence here reads as \"every guarded agent is served\".\n input.logger.warn('The content-guardrail classifier report could not run, so agents that refuse every turn here may be unreported',\n projectCaughtErrorLogFields(error));\n return [];\n }\n}\n\n/**\n * The WARN line for one agent: what it declares, that it refuses every turn here, and each distinct reason once with its\n * remedy (both guardrails usually fail for the same reason, a provider that cannot be reached).\n */\nfunction describeUnservableAgent(agentRef: string, unservable: readonly UnservableAgentContentGuardrail[]): string {\n const declared = unservable.map((entry) => `contentGuardrails.${entry.guardrail}`).join(' and ');\n const byReason = new Map<string, UnservableAgentContentGuardrail[]>();\n for (const entry of unservable) byReason.set(entry.reason, [...(byReason.get(entry.reason) ?? []), entry]);\n const reasons = [...byReason.entries()].map(([reason, entries]) => {\n const guardrails = entries.map((entry) => entry.guardrail).join(' and ');\n const remedy = entries.length === 1 ? entries[0]!.remedy : contentGuardrailClassifierGapRemedy(entries[0]!.gap, entries[0]!.guardrail)\n .replace(`\\`contentGuardrails.${entries[0]!.guardrail}\\``, 'these declarations');\n return `${guardrails}: ${reason}. ${remedy}`;\n });\n return `Agent '${agentRef}' declares ${declared}, and no classifier can serve ${unservable.length === 1 ? 'it' : 'them'} in this environment, `\n + `so the agent REFUSES EVERY TURN here (it does not run unguarded). ${reasons.join(' ')}`;\n}\n\n/** One stored organization agent policy, as far as the classifier question reads it. */\nexport interface StoredAgentPolicyClassifierNeed {\n readonly promptInjectionScreening?: unknown;\n readonly outputModeration?: readonly { readonly category: ContentSafety_HarmCategory }[] | null;\n}\n\n/**\n * The organization agent policies that switch prompt-injection screening on: `promptInjectionScreening` set. A raw filter\n * both adapters translate (`IS NOT NULL` on PostgreSQL's text column).\n */\nexport const ORGANIZATION_AGENT_POLICIES_SCREENING_ON_FILTER: Readonly<Record<string, unknown>> = Object.freeze({\n promptInjectionScreening: { $ne: null },\n});\n\n/**\n * The organization agent policies that switch output moderation on: a non-empty `outputModeration`. `.0` exists is the\n * array-non-empty idiom MongoDB documents, and PostgreSQL compiles it to `\"outputModeration\" #>> '{0}' is not null` on\n * the jsonb column.\n */\nexport const ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER: Readonly<Record<string, unknown>> = Object.freeze({\n 'outputModeration.0': { $exists: true },\n});\n\n/**\n * The boot report's second half (#2292 review F5): organization agent policies that switch a classifier-backed guardrail\n * on where no classifier can serve it. An agent that declares nothing is then refused on every turn acting for such an\n * organization, and the per-agent report above cannot see it, because the policy is a per-tenant row.\n *\n * What it reads, by case:\n * - a classifier serves both guardrails in every category: NOTHING;\n * - a guardrail cannot be served at all (no classifier, which is most applications, or one that cannot serve that\n * guardrail): a filtered COUNT of the rows switching that guardrail on, never the rows themselves;\n * - a classifier serves moderation but not every harm category: the moderation rows only (filtered), to see which\n * categories they name.\n *\n * Reported as a COUNT: a log line names no organization. Such a row is rare by construction: saving one is refused where\n * no classifier can serve it (`classifierRefusalOf`), so a row here was saved when one could, and the environment lost\n * it since (a provider removed, a key rotated out). Never throws; a read that fails is reported as not run.\n */\nexport async function reportOrganizationAgentPoliciesNoClassifierServes(input: {\n readonly resolveContentSafety: () => ContentSafetyBackendService | undefined;\n /** How many stored policies match a raw filter (the repository's count verb). */\n readonly countPolicies: (filter: Readonly<Record<string, unknown>>) => Promise<number>;\n /** The stored policies matching a raw filter (asked only with {@link ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER}). */\n readonly readPolicies: (filter: Readonly<Record<string, unknown>>) => Promise<readonly StoredAgentPolicyClassifierNeed[]>;\n readonly logger: Pick<LoggerService, 'warn' | 'debug'>;\n}): Promise<number> {\n try {\n const contentSafety = input.resolveContentSafety();\n const screeningGap = contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.PROMPT_INJECTION });\n // With no category named, moderation is unservable for a reason no category changes (no service, no recorder, no\n // provider, a provider without the operation or its key).\n const moderationGap = contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION, categories: [] });\n // Otherwise a provider that moderates may still not assess every category a policy names.\n const unassessedCategories = moderationGap ? [] : Object.values(ContentSafety_HarmCategory).filter((category) =>\n contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION, categories: [category] }) !== undefined);\n // A classifier that serves everything leaves no term and no unassessed category, so nothing below reads.\n const unservableTerms = [\n ...(screeningGap ? [ORGANIZATION_AGENT_POLICIES_SCREENING_ON_FILTER] : []),\n ...(moderationGap ? [ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER] : []),\n ];\n let unservable = unservableTerms.length === 0 ? 0 : await input.countPolicies(unservableTerms.length === 1 ? unservableTerms[0]! : { $or: unservableTerms });\n if (unassessedCategories.length > 0) {\n // Moderation rows naming a category the provider does not assess; one already counted for its screening is not\n // counted twice.\n unservable += (await input.readPolicies(ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER)).filter((policy) =>\n (policy.outputModeration ?? []).some((entry) => unassessedCategories.includes(entry.category))\n && !(screeningGap && policy.promptInjectionScreening != null)).length;\n }\n if (unservable > 0) {\n input.logger.warn(\n `${unservable} organization agent ${unservable === 1 ? 'policy switches' : 'policies switch'} on prompt-injection screening or output `\n + 'moderation that no classifier can serve in this environment, so every agent turn acting for '\n + `${unservable === 1 ? 'that organization' : 'those organizations'} is REFUSED. ${(screeningGap ?? moderationGap)?.reason ?? 'A harm category a policy names is not assessed by the selected provider'}. `\n + 'Make a provider serve AI_CONTENT_SAFETY here (or fix what the reason names); the organization\\'s administrator can relax the policy.',\n { unservableOrganizationAgentPolicyCount: unservable },\n );\n }\n return unservable;\n } catch (error) {\n input.logger.warn('The organization agent-policy classifier report could not run, so organizations whose agents refuse every turn here may be unreported',\n projectCaughtErrorLogFields(error));\n return 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"classifier-availability.backend.utils.js","sourceRoot":"","sources":["../../../../src/flows-actors/content-guardrails/classifier-availability.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * #2292 — whether a classifier can serve an agent's classifier-backed content guardrails in THIS process, and the boot\n * report that says so before any turn does.\n *\n * Two guardrails need a classifier (a provider for `EngineCapability.AI_CONTENT_SAFETY`): prompt-injection screening\n * (`contentGuardrails.promptInjection`) and output moderation (`contentGuardrails.outputModeration`). Where none can\n * serve them, an agent declaring either refuses every invocation (`AgentsBackendService.toolResultScreenOf` and\n * `outputModerationGuardOf`), and an organization's agent policy asking for either is refused when it is written\n * (`classifierRefusalOf`). That is correct and stays: running unscreened or unmoderated is what the declaration exists\n * to prevent.\n *\n * What was missing is the signal. An application that selects a classifier in one environment and not in another booted\n * the other one without a word, and its guarded agents' first failed turn was the only report. So the ONE predicate the\n * runtime refuses on lives here, and startup runs it over every registered agent ({@link reportUnservableAgentContentGuardrails}):\n * the boot and the turn cannot disagree about which agents refuse, because they ask the same function.\n *\n * Fail closed at use, warn at boot: the report never throws and never stops startup. The remedy (select a classifier for\n * this environment, or remove the declaration) is an edit to configuration, and a refused boot would also take down\n * everything the application serves that does not need a classifier.\n *\n * ## An environment may declare that its agents run unguarded\n *\n * `agentContentGuardrails: { withoutClassifier: RUN_UNGUARDED, reason }` in `wildo.infra.<env>.config.ts` (see\n * `EnvironmentAgentContentGuardrailsSchema` in `@wildo-ai/saas-models`). Where it is declared and NO selected classifier\n * offers a guardrail, the predicate below still reports the gap, and marks it `runsUnguarded`: the agent's turn then runs\n * without that guardrail, and the boot report names the agent as UNGUARDED (with the environment's reason) instead of as\n * refusing. \"No classifier\" means none is PRESENT for the guardrail (`ContentSafetyBackendService.classifierPresentFor`):\n * none declared, the selected one does not offer it, or its credentials are not authored in this environment. A\n * classifier that is there and cannot be used (declared and not loaded, a category it does not assess) is never waived,\n * and one that fails at call time (a key set and refused, an outage) still withholds: those are failures.\n */\nimport { ContentSafety_HarmCategory, ContentSafetyProvider_OperationKey } from '@wildo-ai/external-connectors-models';\nimport {\n AgentContentGuardrailsWithoutClassifier,\n EnvironmentAgentContentGuardrailsReadingKind,\n FlowsActors_Agent_Status,\n isLLMAgentConfiguration,\n outputModerationCategories,\n type FlowsActors_Agent,\n} from '@wildo-ai/saas-models';\nimport { type ContentSafetyBackendService } from '~wildo-backend-lib/external-providers/services/content-safety.backend.service';\nimport { describeCaughtError, projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\n\n/** The content guardrails that need a classifier, named by their key in `contentGuardrails`. */\nexport enum ClassifierBackedContentGuardrail {\n /** `contentGuardrails.promptInjection`: what somebody else wrote is screened before the model reads it. */\n PROMPT_INJECTION = 'promptInjection',\n /** `contentGuardrails.outputModeration`: what the model writes is judged before anyone reads it. */\n OUTPUT_MODERATION = 'outputModeration',\n}\n\n/**\n * Why no classifier can serve a guardrail here. Kept apart because each has its own remedy: two are about how the\n * process was assembled, two about the environment's provider configuration.\n */\nexport enum ContentGuardrailClassifierGap {\n /** The container binds no `ContentSafetyService`. The engine's default container binds it; a custom one may not. */\n NO_CONTENT_SAFETY_SERVICE = 'no_content_safety_service',\n /** No provider-call recorder is bound, so a screening or judgement could not be shown to have happened (#2292 R7). */\n NO_PROVIDER_CALL_RECORDER = 'no_provider_call_recorder',\n /** No provider serves `AI_CONTENT_SAFETY` in this runtime: the capability is off, or no provider in scope serves it. */\n NO_PROVIDER_SELECTED = 'no_provider_selected',\n /** A provider serves it and cannot be used: no such operation, an unassessed category, its API key or host slot not set, … */\n SELECTED_PROVIDER_CANNOT_SERVE = 'selected_provider_cannot_serve',\n}\n\n/** One guardrail no classifier can serve, with the sentence the runtime refuses with. */\nexport interface ContentGuardrailClassifierUnavailability {\n readonly gap: ContentGuardrailClassifierGap;\n /** The reason, in the runtime's words: it is the clause after \"cannot be screened:\" in the refusal. */\n readonly reason: string;\n /**\n * Set when this environment DECLARED that its agents run unguarded where no classifier serves them\n * (`agentContentGuardrails: { withoutClassifier: RUN_UNGUARDED, reason }`), and none is present for this guardrail:\n * none declared, the selected one does not offer it, or its credentials are not authored in this environment. An\n * agent's own turn then runs without the guardrail instead of being refused. Never set for a classifier that is there\n * and cannot be used (declared and not loaded, a category it does not assess, a broken contract), nor for a process\n * missing the service: those are failures, not the absence the environment declared.\n *\n * An organization's administrator still cannot switch the guardrail ON here (`classifierRefusalOf` refuses on any\n * unavailability): asking for a guardrail nothing can provide would read as a protection that does not exist.\n */\n readonly runsUnguarded?: {\n /** The environment's own `reason`, printed beside every agent it leaves unguarded. */\n readonly declaredReason: string;\n };\n}\n\n/**\n * Why `contentSafety` cannot serve `guardrail`, or `undefined` when it can. The ONE predicate: the runtime refuses an\n * invocation on it, an organization's agent policy is refused on it, and the boot report runs it over every agent.\n *\n * `holder` names what is missing the service or the recorder in the reason (\"this process\" at run time and at boot, \"this\n * application\" where an administrator reads it).\n */\nexport function contentGuardrailClassifierGapOf(\n contentSafety: ContentSafetyBackendService | undefined,\n guardrail: { readonly kind: ClassifierBackedContentGuardrail.PROMPT_INJECTION } | {\n readonly kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION;\n readonly categories: readonly ContentSafety_HarmCategory[];\n },\n holder = 'this process',\n): ContentGuardrailClassifierUnavailability | undefined {\n if (!contentSafety) {\n return { gap: ContentGuardrailClassifierGap.NO_CONTENT_SAFETY_SERVICE, reason: `${holder} binds no content-safety service` };\n }\n const unavailability = classifierGapOfBoundService(contentSafety, guardrail, holder);\n if (unavailability === undefined) return undefined;\n const runsUnguarded = environmentRunsGuardrailUnguarded(contentSafety, guardrail);\n return runsUnguarded === undefined ? unavailability : { ...unavailability, runsUnguarded };\n}\n\n/**\n * The environment's waiver for `guardrail`, when it declared one and no selected classifier offers the guardrail. The ONE\n * place the waiver is decided, so the turn, the boot report and the inbound-delivery screening cannot disagree.\n */\nfunction environmentRunsGuardrailUnguarded(\n contentSafety: ContentSafetyBackendService,\n guardrail: Parameters<typeof contentGuardrailClassifierGapOf>[1],\n): ContentGuardrailClassifierUnavailability['runsUnguarded'] {\n // A content-safety service that does not expose the declaration (a partial stand-in) waives nothing: fail closed.\n if (typeof contentSafety.agentGuardrailsWithoutClassifier !== 'function' || typeof contentSafety.classifierPresentFor !== 'function') return undefined;\n const reading = contentSafety.agentGuardrailsWithoutClassifier();\n if (reading.kind === EnvironmentAgentContentGuardrailsReadingKind.UNREADABLE) return undefined;\n const declaration = reading.declaration;\n if (declaration.withoutClassifier !== AgentContentGuardrailsWithoutClassifier.RUN_UNGUARDED) return undefined;\n // Per GUARDRAIL, never per category: a classifier that moderates some of the agent's categories and not others is a\n // mismatch the operator fixes (narrow the policy, or select one that assesses them), so the agent is refused. Waiving\n // there would switch off the categories it CAN judge too. Absent here means: none declared, the selected one does not\n // offer the guardrail, or its credentials are not authored in this environment (`classifierPresentFor`).\n const offered = contentSafety.classifierPresentFor(guardrail.kind === ClassifierBackedContentGuardrail.PROMPT_INJECTION\n ? ContentSafetyProvider_OperationKey.SCREEN_PROMPT_INJECTION\n : ContentSafetyProvider_OperationKey.MODERATE_OUTPUT);\n return offered ? undefined : { declaredReason: declaration.reason };\n}\n\n/** {@link contentGuardrailClassifierGapOf} for a process that binds the service. */\nfunction classifierGapOfBoundService(\n contentSafety: ContentSafetyBackendService,\n guardrail: Parameters<typeof contentGuardrailClassifierGapOf>[1],\n holder: string,\n): ContentGuardrailClassifierUnavailability | undefined {\n if (!contentSafety.recordsScreenings()) {\n // R7: every screening and judgement leaves a provider-call record; a process that cannot write one does neither.\n const act = guardrail.kind === ClassifierBackedContentGuardrail.PROMPT_INJECTION ? 'a screening' : 'a judgement';\n return { gap: ContentGuardrailClassifierGap.NO_PROVIDER_CALL_RECORDER, reason: `${holder} records no provider calls, so ${act} could not be recorded` };\n }\n try {\n const binding = guardrail.kind === ClassifierBackedContentGuardrail.PROMPT_INJECTION\n ? contentSafety.resolvePromptInjectionBinding()\n : contentSafety.resolveOutputModerationBinding(guardrail.categories);\n if (!binding.configured) return { gap: ContentGuardrailClassifierGap.NO_PROVIDER_SELECTED, reason: 'no provider is selected for AI_CONTENT_SAFETY' };\n } catch (error) {\n // A selected provider that cannot serve throws a named CONFIGURATION error: an operator's mistake, never an absence.\n // Its own sentence, without the closing period: every caller writes the reason as a clause (\"…: <reason>. It is not run.\").\n return { gap: ContentGuardrailClassifierGap.SELECTED_PROVIDER_CANNOT_SERVE, reason: describeCaughtError(error).replace(/[.\\s]+$/u, '') };\n }\n return undefined;\n}\n\n/** One guardrail an agent declares that no classifier can serve here. */\nexport interface UnservableAgentContentGuardrail extends ContentGuardrailClassifierUnavailability {\n readonly agentRef: string;\n readonly guardrail: ClassifierBackedContentGuardrail;\n /** What the operator does about it. */\n readonly remedy: string;\n}\n\n/** What to do about a gap, said once so the boot report and anything else that names it agree. */\nexport function contentGuardrailClassifierGapRemedy(gap: ContentGuardrailClassifierGap, guardrail: ClassifierBackedContentGuardrail): string {\n const orRemove = `or remove \\`contentGuardrails.${guardrail}\\` from the agent`;\n switch (gap) {\n case ContentGuardrailClassifierGap.NO_CONTENT_SAFETY_SERVICE:\n return `Bind SAAS_SERVICE_TYPES.ContentSafetyService in this runtime's container (the engine's default container does), ${orRemove}.`;\n case ContentGuardrailClassifierGap.NO_PROVIDER_CALL_RECORDER:\n return `Bind SAAS_SERVICE_TYPES.ProviderCallRecorder in this runtime's container (the engine's default container does), ${orRemove}.`;\n case ContentGuardrailClassifierGap.NO_PROVIDER_SELECTED:\n // A selection only REORDERS the providers that serve: what makes one serve is the capability being enabled and the\n // provider being in this runtime's scope with that capability.\n return 'Enable EngineCapability.AI_CONTENT_SAFETY and give this runtime\\'s provider scope a provider that serves it (its scope entry lists '\n + `AI_CONTENT_SAFETY); \\`providerSelection\\` in \\`wildo.infra.<env>.config.ts\\` only chooses among the providers that already serve, ${orRemove}.`;\n case ContentGuardrailClassifierGap.SELECTED_PROVIDER_CANNOT_SERVE:\n return `Fix what the reason names in this environment's provider configuration or secrets (an unset API key or host slot is one), `\n + `make a provider that can serve it the one asked first, ${orRemove}.`;\n default: {\n const unknownGap: never = gap;\n return `Unknown gap ${String(unknownGap)}.`;\n }\n }\n}\n\n/**\n * Every classifier-backed guardrail `agent` DECLARES that `contentSafety` cannot serve, empty when it can serve them all\n * (or the agent declares none). The agent's own declaration only: an organization's policy can switch a guardrail on for\n * the turns acting for it, and is read per turn, never at boot (see {@link reportUnservableAgentContentGuardrails}).\n */\nexport function unservableAgentContentGuardrails(\n agent: Pick<FlowsActors_Agent, 'ref' | 'contentGuardrails'>,\n contentSafety: ContentSafetyBackendService | undefined,\n): UnservableAgentContentGuardrail[] {\n const unservable: UnservableAgentContentGuardrail[] = [];\n const add = (guardrail: ClassifierBackedContentGuardrail, unavailability: ContentGuardrailClassifierUnavailability | undefined): void => {\n if (unavailability) unservable.push({ agentRef: agent.ref, guardrail, ...unavailability, remedy: contentGuardrailClassifierGapRemedy(unavailability.gap, guardrail) });\n };\n if (agent.contentGuardrails?.promptInjection) {\n add(ClassifierBackedContentGuardrail.PROMPT_INJECTION,\n contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.PROMPT_INJECTION }));\n }\n const moderation = agent.contentGuardrails?.outputModeration?.blockAtOrAbove;\n if (moderation) {\n add(ClassifierBackedContentGuardrail.OUTPUT_MODERATION,\n contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION, categories: outputModerationCategories(moderation) }));\n }\n return unservable;\n}\n\n/**\n * The boot report: one WARN per agent that declares a classifier-backed guardrail no classifier can serve in this\n * process, naming the agent, the guardrail, why, and what to do. Returns the findings; NEVER throws, because a\n * diagnostic must never be why startup fails (the remedy is a configuration edit, and the rest of the application runs\n * without a classifier).\n *\n * Reads the registered ACTIVE language-model agents: an inactive agent is never invoked, and only a language-model agent\n * runs guardrails (registration refuses one on any other). Organization agent policies are per-tenant rows and are not\n * read here; a policy asking for a guardrail was refused when written unless a classifier could serve it then, and an\n * agent it switches on refuses its turns exactly as a declaring agent does.\n */\nexport function reportUnservableAgentContentGuardrails(input: {\n /** The registered agents. A function, so a registry that cannot be read is reported here rather than thrown at startup. */\n readonly readAgents: () => readonly FlowsActors_Agent[];\n /** The process's content-safety service, `undefined` when none is bound. A function for the same reason. */\n readonly resolveContentSafety: () => ContentSafetyBackendService | undefined;\n readonly logger: Pick<LoggerService, 'warn' | 'debug'>;\n}): UnservableAgentContentGuardrail[] {\n try {\n const findings: UnservableAgentContentGuardrail[] = [];\n const guarded = input.readAgents().filter((agent) => agent.status === FlowsActors_Agent_Status.ACTIVE && isLLMAgentConfiguration(agent.config)\n && (agent.contentGuardrails?.promptInjection !== undefined || agent.contentGuardrails?.outputModeration !== undefined));\n // Resolved only when an agent needs it: an application with no guarded agent asks the container nothing.\n const contentSafety = guarded.length > 0 ? input.resolveContentSafety() : undefined;\n reportUnreadableGuardrailDeclaration(contentSafety, input.logger);\n for (const agent of guarded) {\n const unservable = unservableAgentContentGuardrails(agent, contentSafety);\n if (unservable.length === 0) continue;\n findings.push(...unservable);\n const refused = unservable.filter((entry) => entry.runsUnguarded === undefined);\n const unguarded = unservable.filter((entry) => entry.runsUnguarded !== undefined);\n if (refused.length > 0) {\n input.logger.warn(describeUnservableAgent(agent.ref, refused), {\n agentRef: agent.ref,\n guardrails: refused.map(({ guardrail, gap, reason }) => ({ guardrail, gap, reason })),\n });\n }\n if (unguarded.length > 0) {\n input.logger.warn(describeUnguardedAgent(agent.ref, unguarded), {\n agentRef: agent.ref,\n runsUnguarded: true,\n declaredReason: unguarded[0]!.runsUnguarded!.declaredReason,\n guardrails: unguarded.map(({ guardrail, gap, reason }) => ({ guardrail, gap, reason })),\n });\n }\n }\n if (findings.length === 0) {\n input.logger.debug('Every agent declaring a classifier-backed content guardrail can be served in this environment');\n }\n return findings;\n } catch (error) {\n // WARN, not debug: a report that did not run says nothing, and silence here reads as \"every guarded agent is served\".\n input.logger.warn('The content-guardrail classifier report could not run, so agents that refuse every turn here may be unreported',\n projectCaughtErrorLogFields(error));\n return [];\n }\n}\n\n/**\n * The WARN line for one agent: what it declares, that it refuses every turn here, and each distinct reason once with its\n * remedy (both guardrails usually fail for the same reason, a provider that cannot be reached).\n */\nfunction describeUnservableAgent(agentRef: string, unservable: readonly UnservableAgentContentGuardrail[]): string {\n const declared = unservable.map((entry) => `contentGuardrails.${entry.guardrail}`).join(' and ');\n const byReason = new Map<string, UnservableAgentContentGuardrail[]>();\n for (const entry of unservable) byReason.set(entry.reason, [...(byReason.get(entry.reason) ?? []), entry]);\n const reasons = [...byReason.entries()].map(([reason, entries]) => {\n const guardrails = entries.map((entry) => entry.guardrail).join(' and ');\n const remedy = entries.length === 1 ? entries[0]!.remedy : contentGuardrailClassifierGapRemedy(entries[0]!.gap, entries[0]!.guardrail)\n .replace(`\\`contentGuardrails.${entries[0]!.guardrail}\\``, 'these declarations');\n return `${guardrails}: ${reason}. ${remedy}`;\n });\n return `Agent '${agentRef}' declares ${declared}, and no classifier can serve ${unservable.length === 1 ? 'it' : 'them'} in this environment, `\n + `so the agent REFUSES EVERY TURN here (it does not run unguarded). ${reasons.join(' ')}`;\n}\n\n/**\n * The WARN line for an agent this environment runs unguarded: what it declares, that it runs WITHOUT it here, and the\n * environment's own reason. A WARN on every boot, on purpose: running an agent that declares a guardrail without it is a\n * decision someone must keep seeing until a classifier is selected or the declaration is removed.\n */\nfunction describeUnguardedAgent(agentRef: string, unguarded: readonly UnservableAgentContentGuardrail[]): string {\n const declared = unguarded.map((entry) => `contentGuardrails.${entry.guardrail}`).join(' and ');\n return `Agent '${agentRef}' declares ${declared}, no classifier serves ${unguarded.length === 1 ? 'it' : 'them'} in this environment, `\n + 'and the environment declares agentContentGuardrails.withoutClassifier = run_unguarded, so the agent RUNS UNGUARDED here '\n + `(its ${unguarded.map((entry) => GUARDRAIL_EFFECT[entry.guardrail]).join(' and ')}). The environment's reason: `\n + `\"${unguarded[0]!.runsUnguarded!.declaredReason}\". Select a provider for AI_CONTENT_SAFETY here to enforce it.`;\n}\n\n/** What running without each guardrail means, in a reader's words. TOTAL over the enum. */\nconst GUARDRAIL_EFFECT: Readonly<Record<ClassifierBackedContentGuardrail, string>> = {\n [ClassifierBackedContentGuardrail.PROMPT_INJECTION]: 'tool results and inbound deliveries reach its model unscreened',\n [ClassifierBackedContentGuardrail.OUTPUT_MODERATION]: 'replies, reasoning and tool inputs leave it unmoderated',\n};\n\n/**\n * One WARN when the environment's declaration (`WILDO_AGENT_CONTENT_GUARDRAILS`) does not parse. The runtime then reads\n * it as REFUSE, which is safe, but an operator who declared RUN_UNGUARDED would otherwise see agents refusing with no\n * word about why their declaration was ignored.\n */\nfunction reportUnreadableGuardrailDeclaration(contentSafety: ContentSafetyBackendService | undefined, logger: Pick<LoggerService, 'warn'>): void {\n const reading = typeof contentSafety?.agentGuardrailsWithoutClassifier === 'function' ? contentSafety.agentGuardrailsWithoutClassifier() : undefined;\n if (reading?.kind !== EnvironmentAgentContentGuardrailsReadingKind.UNREADABLE) return;\n logger.warn(`The environment's agentContentGuardrails declaration could not be read (${reading.problem}), so agents whose guardrails `\n + 'no classifier serves REFUSE their turns here. Correct `agentContentGuardrails` in this environment\\'s wildo.infra.<env>.config.ts '\n + 'and run `wildo config sync`.');\n}\n\n/** One stored organization agent policy, as far as the classifier question reads it. */\nexport interface StoredAgentPolicyClassifierNeed {\n readonly promptInjectionScreening?: unknown;\n readonly outputModeration?: readonly { readonly category: ContentSafety_HarmCategory }[] | null;\n}\n\n/**\n * The organization agent policies that switch prompt-injection screening on: `promptInjectionScreening` set. A raw filter\n * both adapters translate (`IS NOT NULL` on PostgreSQL's text column).\n */\nexport const ORGANIZATION_AGENT_POLICIES_SCREENING_ON_FILTER: Readonly<Record<string, unknown>> = Object.freeze({\n promptInjectionScreening: { $ne: null },\n});\n\n/**\n * The organization agent policies that switch output moderation on: a non-empty `outputModeration`. `.0` exists is the\n * array-non-empty idiom MongoDB documents, and PostgreSQL compiles it to `\"outputModeration\" #>> '{0}' is not null` on\n * the jsonb column.\n */\nexport const ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER: Readonly<Record<string, unknown>> = Object.freeze({\n 'outputModeration.0': { $exists: true },\n});\n\n/**\n * The boot report's second half (#2292 review F5): organization agent policies that switch a classifier-backed guardrail\n * on where no classifier can serve it. An agent that declares nothing is then refused on every turn acting for such an\n * organization, and the per-agent report above cannot see it, because the policy is a per-tenant row.\n *\n * What it reads, by case:\n * - a classifier serves both guardrails in every category: NOTHING;\n * - a guardrail cannot be served at all (no classifier, which is most applications, or one that cannot serve that\n * guardrail): a filtered COUNT of the rows switching that guardrail on, never the rows themselves;\n * - a classifier serves moderation but not every harm category: the moderation rows only (filtered), to see which\n * categories they name.\n *\n * Reported as a COUNT: a log line names no organization. Such a row is rare by construction: saving one is refused where\n * no classifier can serve it (`classifierRefusalOf`), so a row here was saved when one could, and the environment lost\n * it since (a provider removed, a key rotated out). Never throws; a read that fails is reported as not run.\n */\nexport async function reportOrganizationAgentPoliciesNoClassifierServes(input: {\n readonly resolveContentSafety: () => ContentSafetyBackendService | undefined;\n /** How many stored policies match a raw filter (the repository's count verb). */\n readonly countPolicies: (filter: Readonly<Record<string, unknown>>) => Promise<number>;\n /** The stored policies matching a raw filter (asked only with {@link ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER}). */\n readonly readPolicies: (filter: Readonly<Record<string, unknown>>) => Promise<readonly StoredAgentPolicyClassifierNeed[]>;\n readonly logger: Pick<LoggerService, 'warn' | 'debug'>;\n}): Promise<number> {\n try {\n const contentSafety = input.resolveContentSafety();\n const screeningGap = contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.PROMPT_INJECTION });\n // With no category named, moderation is unservable for a reason no category changes (no service, no recorder, no\n // provider, a provider without the operation or its key).\n const moderationGap = contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION, categories: [] });\n // Otherwise a provider that moderates may still not assess every category a policy names.\n const unassessedCategories = moderationGap ? [] : Object.values(ContentSafety_HarmCategory).filter((category) =>\n contentGuardrailClassifierGapOf(contentSafety, { kind: ClassifierBackedContentGuardrail.OUTPUT_MODERATION, categories: [category] }) !== undefined);\n // A classifier that serves everything leaves no term and no unassessed category, so nothing below reads.\n const unservableTerms = [\n ...(screeningGap ? [ORGANIZATION_AGENT_POLICIES_SCREENING_ON_FILTER] : []),\n ...(moderationGap ? [ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER] : []),\n ];\n let unservable = unservableTerms.length === 0 ? 0 : await input.countPolicies(unservableTerms.length === 1 ? unservableTerms[0]! : { $or: unservableTerms });\n if (unassessedCategories.length > 0) {\n // Moderation rows naming a category the provider does not assess; one already counted for its screening is not\n // counted twice.\n unservable += (await input.readPolicies(ORGANIZATION_AGENT_POLICIES_MODERATION_ON_FILTER)).filter((policy) =>\n (policy.outputModeration ?? []).some((entry) => unassessedCategories.includes(entry.category))\n && !(screeningGap && policy.promptInjectionScreening != null)).length;\n }\n if (unservable > 0) {\n // Under an environment that declares run_unguarded, a guardrail no classifier offers is not refused: the turn runs\n // without it (the predicate's `runsUnguarded`). Said as such, or the operator reads a refusal that is not happening.\n // A category the provider does not assess is never waived (the waiver is per guardrail), so those rows refuse.\n const waiver = [screeningGap, moderationGap].find((gap) => gap?.runsUnguarded !== undefined)?.runsUnguarded;\n const refusing = unassessedCategories.length > 0 || [screeningGap, moderationGap].some((gap) => gap !== undefined && gap.runsUnguarded === undefined);\n input.logger.warn(\n `${unservable} organization agent ${unservable === 1 ? 'policy switches' : 'policies switch'} on prompt-injection screening or output `\n + 'moderation that no classifier can serve in this environment, so every agent turn acting for '\n + `${unservable === 1 ? 'that organization' : 'those organizations'} ${waiver !== undefined && !refusing\n ? `RUNS UNGUARDED: the environment declares agentContentGuardrails.withoutClassifier = run_unguarded (\"${waiver.declaredReason}\")`\n : 'is REFUSED'}. ${(screeningGap ?? moderationGap)?.reason ?? 'A harm category a policy names is not assessed by the selected provider'}. `\n + 'Make a provider serve AI_CONTENT_SAFETY here (or fix what the reason names); the organization\\'s administrator can relax the policy.',\n { unservableOrganizationAgentPolicyCount: unservable, ...(waiver !== undefined && !refusing ? { runsUnguarded: true } : {}) },\n );\n }\n return unservable;\n } catch (error) {\n input.logger.warn('The organization agent-policy classifier report could not run, so organizations whose agents refuse every turn here may be unreported',\n projectCaughtErrorLogFields(error));\n return 0;\n }\n}\n"]}
|
|
@@ -115,8 +115,10 @@ export interface RecordOwnerPolicyContext {
|
|
|
115
115
|
/**
|
|
116
116
|
* The screen that screens rows whose owner asked when the call itself screens nothing (#3364): created once per call,
|
|
117
117
|
* recording each withholding as the call's own screen does. When no classifier can serve, it answers `NOT_SCREENED`.
|
|
118
|
+
* `undefined` where the environment declares its agents run unguarded and no classifier offers screening: the rows then
|
|
119
|
+
* reach the model unscreened, as the call's own results do there.
|
|
118
120
|
*/
|
|
119
|
-
readonly ownerScreen: () => ToolResultScreen;
|
|
121
|
+
readonly ownerScreen: () => ToolResultScreen | undefined;
|
|
120
122
|
/**
|
|
121
123
|
* #3364 step 3: told the policies of the organizations whose rows reached the model (beyond the call's own), as they
|
|
122
124
|
* enter, so the reply can be judged under the strictest of them and the call's own. Must not throw.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-owner-policy.backend.d.ts","sourceRoot":"","sources":["../../../../src/flows-actors/content-guardrails/record-owner-policy.backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,OAAO,EAKL,KAAK,iBAAiB,EAGtB,KAAK,4CAA4C,EAElD,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yEAAyE,CAAC;AACjH,OAAO,EAAc,KAAK,oBAAoB,EAAE,MAAM,oFAAoF,CAAC;AAC3I,OAAO,EAAsC,KAAK,YAAY,EAAE,MAAM,2EAA2E,CAAC;AAClJ,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sFAAsF,CAAC;AAE9H,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qFAAqF,CAAC;AAE5H,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAElG,sEAAsE;AACtE,MAAM,WAAW,wBAAwB;IACvC,yHAAyH;IACzH,QAAQ,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IACnD;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC1F,gGAAgG;IAChG,QAAQ,CAAC,mBAAmB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;IAChE;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IAChF;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,iBAAiB,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,4BAA4B,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAC/D;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,CAAC,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChF
|
|
1
|
+
{"version":3,"file":"record-owner-policy.backend.d.ts","sourceRoot":"","sources":["../../../../src/flows-actors/content-guardrails/record-owner-policy.backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,OAAO,EAKL,KAAK,iBAAiB,EAGtB,KAAK,4CAA4C,EAElD,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yEAAyE,CAAC;AACjH,OAAO,EAAc,KAAK,oBAAoB,EAAE,MAAM,oFAAoF,CAAC;AAC3I,OAAO,EAAsC,KAAK,YAAY,EAAE,MAAM,2EAA2E,CAAC;AAClJ,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sFAAsF,CAAC;AAE9H,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qFAAqF,CAAC;AAE5H,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAElG,sEAAsE;AACtE,MAAM,WAAW,wBAAwB;IACvC,yHAAyH;IACzH,QAAQ,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IACnD;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC1F,gGAAgG;IAChG,QAAQ,CAAC,mBAAmB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;IAChE;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IAChF;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,iBAAiB,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,4BAA4B,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAC/D;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,CAAC,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChF;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,gBAAgB,GAAG,SAAS,CAAC;IACzD;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,EAAE,CAAC,WAAW,EAAE,SAAS,4CAA4C,EAAE,KAAK,IAAI,CAAC;CAC/G;AAED;;GAEG;AACH,oBAAY,wBAAwB;IAClC;;;OAGG;IACH,mBAAmB,wBAAwB;IAC3C,wHAAwH;IACxH,mBAAmB,wBAAwB;IAC3C,kIAAkI;IAClI,4BAA4B,iCAAiC;IAC7D,yFAAyF;IACzF,aAAa,kBAAkB;CAChC;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,kBAAkB,GAAG,oBAAoB,CAAC,GAAG,wBAAwB,CAOtJ;AAED,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kHAAkH;IAClH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,sHAAsH;IACtH,QAAQ,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;IACpD,4GAA4G;IAC5G,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;CAChD;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,4CAKxC,CAAC;AA0GH;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,iBAAiB,GAAG,SAAS,EACxC,OAAO,EAAE,wBAAwB,EACjC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,OAAO,CAAC,CA+DlB;AAED;;;;;;;;;GASG;AACH,wBAAsB,sCAAsC,CAC1D,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,KAAK,OAAO,EAC7D,SAAS,EAAE,iBAAiB,GAAG,SAAS,EACxC,OAAO,EAAE,wBAAwB,EACjC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,OAAO,CAAC,CAoBlB;AAED,wGAAwG;AACxG,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8GAA8G;IAC9G,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wCAAwC,CAAC,KAAK,EAAE;IAC9D,2HAA2H;IAC3H,QAAQ,CAAC,UAAU,EAAE,MAAM,SAAS,iBAAiB,EAAE,CAAC;IACxD,QAAQ,CAAC,gBAAgB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;IAC7E,iHAAiH;IACjH,QAAQ,CAAC,mBAAmB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;IAChE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CACxD,GAAG,4BAA4B,EAAE,CA+BjC"}
|
|
@@ -205,7 +205,10 @@ async function screenOwnerRows(rows, indices, context, call) {
|
|
|
205
205
|
// verdict, the audit row and the operation record all name the call the result belongs to.
|
|
206
206
|
// Withheld is the screen's own answer, never inferred from the output (#3364 review R2): a clean string result is `text`
|
|
207
207
|
// too, and a record could even hold a notice's words.
|
|
208
|
-
const
|
|
208
|
+
const screen = context.ownerScreen();
|
|
209
|
+
if (screen === undefined)
|
|
210
|
+
return { rows, withheld: new Set() };
|
|
211
|
+
const { output, withheld } = await screen.screened(call.toolCallId, call.toolName, indices.map((index) => rows[index]));
|
|
209
212
|
if (!withheld)
|
|
210
213
|
return { rows, withheld: new Set() };
|
|
211
214
|
const screened = [...rows];
|
|
@@ -305,7 +308,10 @@ export async function treatToolTreatedResultByPossibleOwners(output, treat, call
|
|
|
305
308
|
: tightenings.some((tightening) => tightening.personalDataTreatment) ? treat(output, context.ownerGuard()) : output;
|
|
306
309
|
// Its rows name no owner, so the whole result is screened when any possible owner asked.
|
|
307
310
|
if (!call.callScreensResult && tightenings.some((tightening) => tightening.promptInjectionScreening)) {
|
|
308
|
-
const
|
|
311
|
+
const screen = context.ownerScreen();
|
|
312
|
+
const { output, withheld } = screen === undefined
|
|
313
|
+
? { output: { value: treated }, withheld: false }
|
|
314
|
+
: await screen.screened(call.toolCallId, call.toolName, treated);
|
|
309
315
|
// Withheld whole: nothing of it reached the model, so nothing tightens the reply.
|
|
310
316
|
if (withheld)
|
|
311
317
|
return output.value;
|