@parmana/shared 0.0.0-stage → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +16 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/config/ApiKeyEntry.d.ts +97 -0
- package/dist/config/ApiKeyEntry.d.ts.map +1 -0
- package/dist/config/ApiKeyEntry.js +2 -0
- package/dist/config/ApiKeyEntry.js.map +1 -0
- package/dist/config/Config.d.ts +227 -0
- package/dist/config/Config.d.ts.map +1 -0
- package/dist/config/Config.js +172 -0
- package/dist/config/Config.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +5 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +8 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/config/ConfigUtils.d.ts +6 -0
- package/dist/config/ConfigUtils.d.ts.map +1 -0
- package/dist/config/ConfigUtils.js +8 -0
- package/dist/config/ConfigUtils.js.map +1 -0
- package/dist/config/ConfigValidation.d.ts +30 -0
- package/dist/config/ConfigValidation.d.ts.map +1 -0
- package/dist/config/ConfigValidation.js +191 -0
- package/dist/config/ConfigValidation.js.map +1 -0
- package/dist/config/CryptoAlgorithms.d.ts +38 -0
- package/dist/config/CryptoAlgorithms.d.ts.map +1 -0
- package/dist/config/CryptoAlgorithms.js +38 -0
- package/dist/config/CryptoAlgorithms.js.map +1 -0
- package/dist/config/Doctor.d.ts +46 -0
- package/dist/config/Doctor.d.ts.map +1 -0
- package/dist/config/Doctor.js +781 -0
- package/dist/config/Doctor.js.map +1 -0
- package/dist/config/KeyProviders.d.ts +9 -0
- package/dist/config/KeyProviders.d.ts.map +1 -0
- package/dist/config/KeyProviders.js +8 -0
- package/dist/config/KeyProviders.js.map +1 -0
- package/dist/config/SecretsProviders.d.ts +6 -0
- package/dist/config/SecretsProviders.d.ts.map +1 -0
- package/dist/config/SecretsProviders.js +5 -0
- package/dist/config/SecretsProviders.js.map +1 -0
- package/dist/config/StorageProviders.d.ts +18 -0
- package/dist/config/StorageProviders.d.ts.map +1 -0
- package/dist/config/StorageProviders.js +20 -0
- package/dist/config/StorageProviders.js.map +1 -0
- package/dist/config/TrustProfiles.d.ts +5 -0
- package/dist/config/TrustProfiles.d.ts.map +1 -0
- package/dist/config/TrustProfiles.js +4 -0
- package/dist/config/TrustProfiles.js.map +1 -0
- package/dist/config/index.d.ts +12 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +12 -0
- package/dist/config/index.js.map +1 -0
- package/dist/domain/approval-artifact.d.ts +136 -0
- package/dist/domain/approval-artifact.d.ts.map +1 -0
- package/dist/domain/approval-artifact.js +2 -0
- package/dist/domain/approval-artifact.js.map +1 -0
- package/dist/domain/approval-issuer.d.ts +52 -0
- package/dist/domain/approval-issuer.d.ts.map +1 -0
- package/dist/domain/approval-issuer.js +2 -0
- package/dist/domain/approval-issuer.js.map +1 -0
- package/dist/domain/authority-grant.d.ts +54 -0
- package/dist/domain/authority-grant.d.ts.map +1 -0
- package/dist/domain/authority-grant.js +2 -0
- package/dist/domain/authority-grant.js.map +1 -0
- package/dist/domain/authority.d.ts +42 -0
- package/dist/domain/authority.d.ts.map +1 -0
- package/dist/domain/authority.js +11 -0
- package/dist/domain/authority.js.map +1 -0
- package/dist/domain/authorization.d.ts +54 -0
- package/dist/domain/authorization.d.ts.map +1 -0
- package/dist/domain/authorization.js +2 -0
- package/dist/domain/authorization.js.map +1 -0
- package/dist/domain/business-signal-source.d.ts +52 -0
- package/dist/domain/business-signal-source.d.ts.map +1 -0
- package/dist/domain/business-signal-source.js +2 -0
- package/dist/domain/business-signal-source.js.map +1 -0
- package/dist/domain/business-transaction.d.ts +99 -0
- package/dist/domain/business-transaction.d.ts.map +1 -0
- package/dist/domain/business-transaction.js +16 -0
- package/dist/domain/business-transaction.js.map +1 -0
- package/dist/domain/business-validation.d.ts +177 -0
- package/dist/domain/business-validation.d.ts.map +1 -0
- package/dist/domain/business-validation.js +60 -0
- package/dist/domain/business-validation.js.map +1 -0
- package/dist/domain/challenge-record.d.ts +181 -0
- package/dist/domain/challenge-record.d.ts.map +1 -0
- package/dist/domain/challenge-record.js +2 -0
- package/dist/domain/challenge-record.js.map +1 -0
- package/dist/domain/decision.d.ts +97 -0
- package/dist/domain/decision.d.ts.map +1 -0
- package/dist/domain/decision.js +9 -0
- package/dist/domain/decision.js.map +1 -0
- package/dist/domain/evidence-anchor.d.ts +54 -0
- package/dist/domain/evidence-anchor.d.ts.map +1 -0
- package/dist/domain/evidence-anchor.js +2 -0
- package/dist/domain/evidence-anchor.js.map +1 -0
- package/dist/domain/executable-content.d.ts +45 -0
- package/dist/domain/executable-content.d.ts.map +1 -0
- package/dist/domain/executable-content.js +39 -0
- package/dist/domain/executable-content.js.map +1 -0
- package/dist/domain/execution-audit-event.d.ts +65 -0
- package/dist/domain/execution-audit-event.d.ts.map +1 -0
- package/dist/domain/execution-audit-event.js +2 -0
- package/dist/domain/execution-audit-event.js.map +1 -0
- package/dist/domain/execution-authorization.d.ts +224 -0
- package/dist/domain/execution-authorization.d.ts.map +1 -0
- package/dist/domain/execution-authorization.js +2 -0
- package/dist/domain/execution-authorization.js.map +1 -0
- package/dist/domain/execution-evidence.d.ts +38 -0
- package/dist/domain/execution-evidence.d.ts.map +1 -0
- package/dist/domain/execution-evidence.js +2 -0
- package/dist/domain/execution-evidence.js.map +1 -0
- package/dist/domain/execution-intent.d.ts +92 -0
- package/dist/domain/execution-intent.d.ts.map +1 -0
- package/dist/domain/execution-intent.js +2 -0
- package/dist/domain/execution-intent.js.map +1 -0
- package/dist/domain/execution-metadata.d.ts +8 -0
- package/dist/domain/execution-metadata.d.ts.map +1 -0
- package/dist/domain/execution-metadata.js +2 -0
- package/dist/domain/execution-metadata.js.map +1 -0
- package/dist/domain/execution-outcome-store.d.ts +49 -0
- package/dist/domain/execution-outcome-store.d.ts.map +1 -0
- package/dist/domain/execution-outcome-store.js +10 -0
- package/dist/domain/execution-outcome-store.js.map +1 -0
- package/dist/domain/execution-result.d.ts +49 -0
- package/dist/domain/execution-result.d.ts.map +1 -0
- package/dist/domain/execution-result.js +2 -0
- package/dist/domain/execution-result.js.map +1 -0
- package/dist/domain/execution-trust-record.d.ts +142 -0
- package/dist/domain/execution-trust-record.d.ts.map +1 -0
- package/dist/domain/execution-trust-record.js +2 -0
- package/dist/domain/execution-trust-record.js.map +1 -0
- package/dist/domain/execution.d.ts +108 -0
- package/dist/domain/execution.d.ts.map +1 -0
- package/dist/domain/execution.js +18 -0
- package/dist/domain/execution.js.map +1 -0
- package/dist/domain/external-connector.d.ts +68 -0
- package/dist/domain/external-connector.d.ts.map +1 -0
- package/dist/domain/external-connector.js +2 -0
- package/dist/domain/external-connector.js.map +1 -0
- package/dist/domain/index.d.ts +37 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +37 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/intent.d.ts +66 -0
- package/dist/domain/intent.d.ts.map +1 -0
- package/dist/domain/intent.js +2 -0
- package/dist/domain/intent.js.map +1 -0
- package/dist/domain/metadata.d.ts +53 -0
- package/dist/domain/metadata.d.ts.map +1 -0
- package/dist/domain/metadata.js +11 -0
- package/dist/domain/metadata.js.map +1 -0
- package/dist/domain/override.d.ts +39 -0
- package/dist/domain/override.d.ts.map +1 -0
- package/dist/domain/override.js +2 -0
- package/dist/domain/override.js.map +1 -0
- package/dist/domain/pending-policy-change.d.ts +109 -0
- package/dist/domain/pending-policy-change.d.ts.map +1 -0
- package/dist/domain/pending-policy-change.js +12 -0
- package/dist/domain/pending-policy-change.js.map +1 -0
- package/dist/domain/policy-change-approval-record.d.ts +81 -0
- package/dist/domain/policy-change-approval-record.d.ts.map +1 -0
- package/dist/domain/policy-change-approval-record.js +2 -0
- package/dist/domain/policy-change-approval-record.js.map +1 -0
- package/dist/domain/policy-change-step-up-authorization.d.ts +97 -0
- package/dist/domain/policy-change-step-up-authorization.d.ts.map +1 -0
- package/dist/domain/policy-change-step-up-authorization.js +2 -0
- package/dist/domain/policy-change-step-up-authorization.js.map +1 -0
- package/dist/domain/policy-reference.d.ts +58 -0
- package/dist/domain/policy-reference.d.ts.map +1 -0
- package/dist/domain/policy-reference.js +2 -0
- package/dist/domain/policy-reference.js.map +1 -0
- package/dist/domain/receipt.d.ts +72 -0
- package/dist/domain/receipt.d.ts.map +1 -0
- package/dist/domain/receipt.js +2 -0
- package/dist/domain/receipt.js.map +1 -0
- package/dist/domain/refusal-record.d.ts +110 -0
- package/dist/domain/refusal-record.d.ts.map +1 -0
- package/dist/domain/refusal-record.js +2 -0
- package/dist/domain/refusal-record.js.map +1 -0
- package/dist/domain/release-approval.d.ts +14 -0
- package/dist/domain/release-approval.d.ts.map +1 -0
- package/dist/domain/release-approval.js +2 -0
- package/dist/domain/release-approval.js.map +1 -0
- package/dist/domain/signals.d.ts +10 -0
- package/dist/domain/signals.d.ts.map +1 -0
- package/dist/domain/signals.js +2 -0
- package/dist/domain/signals.js.map +1 -0
- package/dist/domain/signature-entry.d.ts +23 -0
- package/dist/domain/signature-entry.d.ts.map +1 -0
- package/dist/domain/signature-entry.js +2 -0
- package/dist/domain/signature-entry.js.map +1 -0
- package/dist/domain/signature.d.ts +26 -0
- package/dist/domain/signature.d.ts.map +1 -0
- package/dist/domain/signature.js +2 -0
- package/dist/domain/signature.js.map +1 -0
- package/dist/domain/unsigned-execution-trust-record.d.ts +7 -0
- package/dist/domain/unsigned-execution-trust-record.d.ts.map +1 -0
- package/dist/domain/unsigned-execution-trust-record.js +2 -0
- package/dist/domain/unsigned-execution-trust-record.js.map +1 -0
- package/dist/domain/verification.d.ts +48 -0
- package/dist/domain/verification.d.ts.map +1 -0
- package/dist/domain/verification.js +9 -0
- package/dist/domain/verification.js.map +1 -0
- package/dist/errors/approval-issuer-change-not-found-error.d.ts +9 -0
- package/dist/errors/approval-issuer-change-not-found-error.d.ts.map +1 -0
- package/dist/errors/approval-issuer-change-not-found-error.js +11 -0
- package/dist/errors/approval-issuer-change-not-found-error.js.map +1 -0
- package/dist/errors/authority-grant-change-not-found-error.d.ts +9 -0
- package/dist/errors/authority-grant-change-not-found-error.d.ts.map +1 -0
- package/dist/errors/authority-grant-change-not-found-error.js +11 -0
- package/dist/errors/authority-grant-change-not-found-error.js.map +1 -0
- package/dist/errors/authority-required-error.d.ts +5 -0
- package/dist/errors/authority-required-error.d.ts.map +1 -0
- package/dist/errors/authority-required-error.js +7 -0
- package/dist/errors/authority-required-error.js.map +1 -0
- package/dist/errors/authorization-no-longer-valid-error.d.ts +19 -0
- package/dist/errors/authorization-no-longer-valid-error.d.ts.map +1 -0
- package/dist/errors/authorization-no-longer-valid-error.js +23 -0
- package/dist/errors/authorization-no-longer-valid-error.js.map +1 -0
- package/dist/errors/authorization-required-error.d.ts +5 -0
- package/dist/errors/authorization-required-error.d.ts.map +1 -0
- package/dist/errors/authorization-required-error.js +7 -0
- package/dist/errors/authorization-required-error.js.map +1 -0
- package/dist/errors/business-signal-source-change-not-found-error.d.ts +9 -0
- package/dist/errors/business-signal-source-change-not-found-error.d.ts.map +1 -0
- package/dist/errors/business-signal-source-change-not-found-error.js +11 -0
- package/dist/errors/business-signal-source-change-not-found-error.js.map +1 -0
- package/dist/errors/business-transaction-not-found-error.d.ts +5 -0
- package/dist/errors/business-transaction-not-found-error.d.ts.map +1 -0
- package/dist/errors/business-transaction-not-found-error.js +7 -0
- package/dist/errors/business-transaction-not-found-error.js.map +1 -0
- package/dist/errors/challenge-record-not-found-error.d.ts +9 -0
- package/dist/errors/challenge-record-not-found-error.d.ts.map +1 -0
- package/dist/errors/challenge-record-not-found-error.js +11 -0
- package/dist/errors/challenge-record-not-found-error.js.map +1 -0
- package/dist/errors/conflict-error.d.ts +5 -0
- package/dist/errors/conflict-error.d.ts.map +1 -0
- package/dist/errors/conflict-error.js +7 -0
- package/dist/errors/conflict-error.js.map +1 -0
- package/dist/errors/connector-not-registered-error.d.ts +21 -0
- package/dist/errors/connector-not-registered-error.d.ts.map +1 -0
- package/dist/errors/connector-not-registered-error.js +24 -0
- package/dist/errors/connector-not-registered-error.js.map +1 -0
- package/dist/errors/decision-not-approved-error.d.ts +5 -0
- package/dist/errors/decision-not-approved-error.d.ts.map +1 -0
- package/dist/errors/decision-not-approved-error.js +7 -0
- package/dist/errors/decision-not-approved-error.js.map +1 -0
- package/dist/errors/duplicate-business-transaction-error.d.ts +26 -0
- package/dist/errors/duplicate-business-transaction-error.d.ts.map +1 -0
- package/dist/errors/duplicate-business-transaction-error.js +28 -0
- package/dist/errors/duplicate-business-transaction-error.js.map +1 -0
- package/dist/errors/external-connector-change-not-found-error.d.ts +9 -0
- package/dist/errors/external-connector-change-not-found-error.d.ts.map +1 -0
- package/dist/errors/external-connector-change-not-found-error.js +11 -0
- package/dist/errors/external-connector-change-not-found-error.js.map +1 -0
- package/dist/errors/forbidden-error.d.ts +5 -0
- package/dist/errors/forbidden-error.d.ts.map +1 -0
- package/dist/errors/forbidden-error.js +7 -0
- package/dist/errors/forbidden-error.js.map +1 -0
- package/dist/errors/index.d.ts +30 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +30 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/intent-required-error.d.ts +5 -0
- package/dist/errors/intent-required-error.d.ts.map +1 -0
- package/dist/errors/intent-required-error.js +7 -0
- package/dist/errors/intent-required-error.js.map +1 -0
- package/dist/errors/non-human-caller-denied-error.d.ts +10 -0
- package/dist/errors/non-human-caller-denied-error.d.ts.map +1 -0
- package/dist/errors/non-human-caller-denied-error.js +12 -0
- package/dist/errors/non-human-caller-denied-error.js.map +1 -0
- package/dist/errors/nonce-already-consumed-error.d.ts +26 -0
- package/dist/errors/nonce-already-consumed-error.d.ts.map +1 -0
- package/dist/errors/nonce-already-consumed-error.js +29 -0
- package/dist/errors/nonce-already-consumed-error.js.map +1 -0
- package/dist/errors/outcome-unknown-error.d.ts +15 -0
- package/dist/errors/outcome-unknown-error.d.ts.map +1 -0
- package/dist/errors/outcome-unknown-error.js +19 -0
- package/dist/errors/outcome-unknown-error.js.map +1 -0
- package/dist/errors/override-not-allowed-error.d.ts +5 -0
- package/dist/errors/override-not-allowed-error.d.ts.map +1 -0
- package/dist/errors/override-not-allowed-error.js +7 -0
- package/dist/errors/override-not-allowed-error.js.map +1 -0
- package/dist/errors/parmana-error.d.ts +15 -0
- package/dist/errors/parmana-error.d.ts.map +1 -0
- package/dist/errors/parmana-error.js +21 -0
- package/dist/errors/parmana-error.js.map +1 -0
- package/dist/errors/pending-policy-change-not-found-error.d.ts +9 -0
- package/dist/errors/pending-policy-change-not-found-error.d.ts.map +1 -0
- package/dist/errors/pending-policy-change-not-found-error.js +11 -0
- package/dist/errors/pending-policy-change-not-found-error.js.map +1 -0
- package/dist/errors/policy-not-found-error.d.ts +5 -0
- package/dist/errors/policy-not-found-error.d.ts.map +1 -0
- package/dist/errors/policy-not-found-error.js +7 -0
- package/dist/errors/policy-not-found-error.js.map +1 -0
- package/dist/errors/receipt-generation-error.d.ts +5 -0
- package/dist/errors/receipt-generation-error.d.ts.map +1 -0
- package/dist/errors/receipt-generation-error.js +7 -0
- package/dist/errors/receipt-generation-error.js.map +1 -0
- package/dist/errors/same-actor-cannot-approve-own-change-error.d.ts +12 -0
- package/dist/errors/same-actor-cannot-approve-own-change-error.d.ts.map +1 -0
- package/dist/errors/same-actor-cannot-approve-own-change-error.js +15 -0
- package/dist/errors/same-actor-cannot-approve-own-change-error.js.map +1 -0
- package/dist/errors/step-up-authorization-invalid-error.d.ts +25 -0
- package/dist/errors/step-up-authorization-invalid-error.d.ts.map +1 -0
- package/dist/errors/step-up-authorization-invalid-error.js +28 -0
- package/dist/errors/step-up-authorization-invalid-error.js.map +1 -0
- package/dist/errors/trust-chain-validation-error.d.ts +5 -0
- package/dist/errors/trust-chain-validation-error.d.ts.map +1 -0
- package/dist/errors/trust-chain-validation-error.js +7 -0
- package/dist/errors/trust-chain-validation-error.js.map +1 -0
- package/dist/errors/unauthorized-error.d.ts +5 -0
- package/dist/errors/unauthorized-error.d.ts.map +1 -0
- package/dist/errors/unauthorized-error.js +7 -0
- package/dist/errors/unauthorized-error.js.map +1 -0
- package/dist/errors/validation-error.d.ts +5 -0
- package/dist/errors/validation-error.d.ts.map +1 -0
- package/dist/errors/validation-error.js +7 -0
- package/dist/errors/validation-error.js.map +1 -0
- package/dist/errors/verification-failed-error.d.ts +5 -0
- package/dist/errors/verification-failed-error.d.ts.map +1 -0
- package/dist/errors/verification-failed-error.js +7 -0
- package/dist/errors/verification-failed-error.js.map +1 -0
- package/dist/gateway/GatewayAuthentication.d.ts +8 -0
- package/dist/gateway/GatewayAuthentication.d.ts.map +1 -0
- package/dist/gateway/GatewayAuthentication.js +2 -0
- package/dist/gateway/GatewayAuthentication.js.map +1 -0
- package/dist/gateway/GatewayAuthenticationClaims.d.ts +10 -0
- package/dist/gateway/GatewayAuthenticationClaims.d.ts.map +1 -0
- package/dist/gateway/GatewayAuthenticationClaims.js +2 -0
- package/dist/gateway/GatewayAuthenticationClaims.js.map +1 -0
- package/dist/gateway/GatewayAuthenticationPayload.d.ts +15 -0
- package/dist/gateway/GatewayAuthenticationPayload.d.ts.map +1 -0
- package/dist/gateway/GatewayAuthenticationPayload.js +2 -0
- package/dist/gateway/GatewayAuthenticationPayload.js.map +1 -0
- package/dist/gateway/SignedGatewayAuthentication.d.ts +9 -0
- package/dist/gateway/SignedGatewayAuthentication.d.ts.map +1 -0
- package/dist/gateway/SignedGatewayAuthentication.js +2 -0
- package/dist/gateway/SignedGatewayAuthentication.js.map +1 -0
- package/dist/gateway/index.d.ts +4 -0
- package/dist/gateway/index.d.ts.map +1 -0
- package/dist/gateway/index.js +4 -0
- package/dist/gateway/index.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/Logger.d.ts +65 -0
- package/dist/logging/Logger.d.ts.map +1 -0
- package/dist/logging/Logger.js +97 -0
- package/dist/logging/Logger.js.map +1 -0
- package/dist/network/externalEndpointAddress.d.ts +48 -0
- package/dist/network/externalEndpointAddress.d.ts.map +1 -0
- package/dist/network/externalEndpointAddress.js +147 -0
- package/dist/network/externalEndpointAddress.js.map +1 -0
- package/dist/repositories/approval-issuer-repository.d.ts +31 -0
- package/dist/repositories/approval-issuer-repository.d.ts.map +1 -0
- package/dist/repositories/approval-issuer-repository.js +2 -0
- package/dist/repositories/approval-issuer-repository.js.map +1 -0
- package/dist/repositories/authority-grant-repository.d.ts +22 -0
- package/dist/repositories/authority-grant-repository.d.ts.map +1 -0
- package/dist/repositories/authority-grant-repository.js +2 -0
- package/dist/repositories/authority-grant-repository.js.map +1 -0
- package/dist/repositories/business-signal-source-repository.d.ts +17 -0
- package/dist/repositories/business-signal-source-repository.d.ts.map +1 -0
- package/dist/repositories/business-signal-source-repository.js +2 -0
- package/dist/repositories/business-signal-source-repository.js.map +1 -0
- package/dist/repositories/business-transaction-repository.d.ts +34 -0
- package/dist/repositories/business-transaction-repository.d.ts.map +1 -0
- package/dist/repositories/business-transaction-repository.js +2 -0
- package/dist/repositories/business-transaction-repository.js.map +1 -0
- package/dist/repositories/caller-key-revocation-repository.d.ts +26 -0
- package/dist/repositories/caller-key-revocation-repository.d.ts.map +1 -0
- package/dist/repositories/caller-key-revocation-repository.js +2 -0
- package/dist/repositories/caller-key-revocation-repository.js.map +1 -0
- package/dist/repositories/challenge-record-repository.d.ts +67 -0
- package/dist/repositories/challenge-record-repository.d.ts.map +1 -0
- package/dist/repositories/challenge-record-repository.js +76 -0
- package/dist/repositories/challenge-record-repository.js.map +1 -0
- package/dist/repositories/execution-intent-repository.d.ts +38 -0
- package/dist/repositories/execution-intent-repository.d.ts.map +1 -0
- package/dist/repositories/execution-intent-repository.js +2 -0
- package/dist/repositories/execution-intent-repository.js.map +1 -0
- package/dist/repositories/execution-trust-record-repository.d.ts +62 -0
- package/dist/repositories/execution-trust-record-repository.d.ts.map +1 -0
- package/dist/repositories/execution-trust-record-repository.js +2 -0
- package/dist/repositories/execution-trust-record-repository.js.map +1 -0
- package/dist/repositories/external-connector-repository.d.ts +37 -0
- package/dist/repositories/external-connector-repository.d.ts.map +1 -0
- package/dist/repositories/external-connector-repository.js +2 -0
- package/dist/repositories/external-connector-repository.js.map +1 -0
- package/dist/repositories/handbook-download-lead-repository.d.ts +18 -0
- package/dist/repositories/handbook-download-lead-repository.d.ts.map +1 -0
- package/dist/repositories/handbook-download-lead-repository.js +2 -0
- package/dist/repositories/handbook-download-lead-repository.js.map +1 -0
- package/dist/repositories/inbound-decision-repository.d.ts +72 -0
- package/dist/repositories/inbound-decision-repository.d.ts.map +1 -0
- package/dist/repositories/inbound-decision-repository.js +10 -0
- package/dist/repositories/inbound-decision-repository.js.map +1 -0
- package/dist/repositories/inbound-outcome-repository.d.ts +23 -0
- package/dist/repositories/inbound-outcome-repository.d.ts.map +1 -0
- package/dist/repositories/inbound-outcome-repository.js +2 -0
- package/dist/repositories/inbound-outcome-repository.js.map +1 -0
- package/dist/repositories/index.d.ts +17 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +17 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/pending-policy-change-repository.d.ts +72 -0
- package/dist/repositories/pending-policy-change-repository.d.ts.map +1 -0
- package/dist/repositories/pending-policy-change-repository.js +46 -0
- package/dist/repositories/pending-policy-change-repository.js.map +1 -0
- package/dist/repositories/policy-change-approval-record-repository.d.ts +39 -0
- package/dist/repositories/policy-change-approval-record-repository.d.ts.map +1 -0
- package/dist/repositories/policy-change-approval-record-repository.js +2 -0
- package/dist/repositories/policy-change-approval-record-repository.js.map +1 -0
- package/dist/repositories/policy-repository.d.ts +15 -0
- package/dist/repositories/policy-repository.d.ts.map +1 -0
- package/dist/repositories/policy-repository.js +2 -0
- package/dist/repositories/policy-repository.js.map +1 -0
- package/dist/repositories/refusal-record-repository.d.ts +13 -0
- package/dist/repositories/refusal-record-repository.d.ts.map +1 -0
- package/dist/repositories/refusal-record-repository.js +2 -0
- package/dist/repositories/refusal-record-repository.js.map +1 -0
- package/dist/types/Json.d.ts +7 -0
- package/dist/types/Json.d.ts.map +1 -0
- package/dist/types/Json.js +2 -0
- package/dist/types/Json.js.map +1 -0
- package/dist/utils/normalize-policy.d.ts +16 -0
- package/dist/utils/normalize-policy.d.ts.map +1 -0
- package/dist/utils/normalize-policy.js +10 -0
- package/dist/utils/normalize-policy.js.map +1 -0
- package/package.json +39 -4
|
@@ -0,0 +1,781 @@
|
|
|
1
|
+
import { createPublicKey } from "node:crypto";
|
|
2
|
+
import { parseHybridRequiredFrom, parseHybridSchemaVersion } from "./Config.js";
|
|
3
|
+
import { CryptoModes, HashAlgorithms, SignatureAlgorithms, } from "./CryptoAlgorithms.js";
|
|
4
|
+
import { KeyProviders } from "./KeyProviders.js";
|
|
5
|
+
import { SecretsProviders } from "./SecretsProviders.js";
|
|
6
|
+
import { parseApiKeys, parseCryptoMode, parseHashAlgorithm, parseKeyProvider, parseSecretsProvider, parseSignatureAlgorithm, parseStorageProvider, parseTrustProfile, } from "./ConfigValidation.js";
|
|
7
|
+
/**
|
|
8
|
+
* The key pair the server requires for every signing operation. It is the same
|
|
9
|
+
* name the signing code uses (DEFAULT_KEY_ID in @parmana/crypto). That package
|
|
10
|
+
* depends on this one, so the name is repeated here rather than imported.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_KEY_ID = "default";
|
|
13
|
+
/** A plain Postgres schema name, as PostgresPoolFactory accepts. */
|
|
14
|
+
const SCHEMA_NAME = /^[a-z_][a-z0-9_]{0,62}$/;
|
|
15
|
+
/**
|
|
16
|
+
* Every PARMANA_ name read by this repository. A name outside this list is
|
|
17
|
+
* reported as a probable typo, because the server ignores it without a word.
|
|
18
|
+
*/
|
|
19
|
+
export const KNOWN_PARMANA_SETTINGS = [
|
|
20
|
+
"PARMANA_ALLOW_UNGOVERNED_POLICY",
|
|
21
|
+
"PARMANA_API_BASE_URL",
|
|
22
|
+
"PARMANA_API_KEYS",
|
|
23
|
+
"PARMANA_API_URL",
|
|
24
|
+
"PARMANA_AUTH_DISABLED",
|
|
25
|
+
"PARMANA_CORS_ORIGINS",
|
|
26
|
+
"PARMANA_DATABASE_CA",
|
|
27
|
+
"PARMANA_DATABASE_CA_FILE",
|
|
28
|
+
"PARMANA_DB_SCHEMA",
|
|
29
|
+
"PARMANA_GATEWAY_ID",
|
|
30
|
+
"PARMANA_GATEWAY_KEY_ID",
|
|
31
|
+
"PARMANA_KEY_DIR",
|
|
32
|
+
"PARMANA_KEY_MATERIAL_JSON",
|
|
33
|
+
"PARMANA_POLICY_DIR",
|
|
34
|
+
"PARMANA_SANDBOX",
|
|
35
|
+
"PARMANA_SANDBOX_APPROVER_ID",
|
|
36
|
+
"PARMANA_SANDBOX_APPROVER_KEY_ID",
|
|
37
|
+
"PARMANA_SANDBOX_APPROVER_PRIVATE_KEY",
|
|
38
|
+
"PARMANA_SECRETS_PROVIDER",
|
|
39
|
+
"PARMANA_SKIP_DOTENV",
|
|
40
|
+
"PARMANA_STORAGE",
|
|
41
|
+
"PARMANA_TEST_APPROVER_PUBLIC_KEY_FILE",
|
|
42
|
+
"PARMANA_VERIFICATION_KEY_ID",
|
|
43
|
+
"PARMANA_VERIFICATION_SECONDARY_KEY_ID",
|
|
44
|
+
"PARMANA_VERIFIER_KEY_ID",
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Runs the configuration checks and returns every result, not just the first
|
|
48
|
+
* failure. With `production: true`, the production rules are added and the
|
|
49
|
+
* stage 1 "not yet checked" warnings are replaced by real checks.
|
|
50
|
+
*
|
|
51
|
+
* Each setting is checked with the same parser the server uses, so a check
|
|
52
|
+
* cannot pass here and fail at startup. Parser error messages are never shown,
|
|
53
|
+
* because some of them echo the value they rejected. Messages name the setting
|
|
54
|
+
* and the allowed values only.
|
|
55
|
+
*/
|
|
56
|
+
export function diagnoseConfiguration(env, readers, options = { production: false }) {
|
|
57
|
+
const production = options.production;
|
|
58
|
+
const checks = [];
|
|
59
|
+
const add = (check) => checks.push(check);
|
|
60
|
+
checkStorage(env, add, production);
|
|
61
|
+
checkDatabaseCaFile(env, readers, add);
|
|
62
|
+
checkCrypto(env, add, production);
|
|
63
|
+
checkHybrid(env, add);
|
|
64
|
+
const keyProvider = keyProviderOf(env);
|
|
65
|
+
checkKeys(env, readers, add, keyProvider);
|
|
66
|
+
checkPolicy(env, readers, add);
|
|
67
|
+
checkAuth(env, add, production);
|
|
68
|
+
checkTrustProfile(env, add);
|
|
69
|
+
checkNumbers(env, add);
|
|
70
|
+
checkUnknownSettings(env, add);
|
|
71
|
+
if (production) {
|
|
72
|
+
checkProduction(env, add, keyProvider);
|
|
73
|
+
}
|
|
74
|
+
return checks;
|
|
75
|
+
}
|
|
76
|
+
function keyProviderOf(env) {
|
|
77
|
+
try {
|
|
78
|
+
return parseKeyProvider(env.KEY_PROVIDER);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return KeyProviders.LOCAL;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function checkStorage(env, add, production) {
|
|
85
|
+
const name = "PARMANA_STORAGE";
|
|
86
|
+
if (env.DATABASE_PROVIDER !== undefined) {
|
|
87
|
+
add({
|
|
88
|
+
name: "DATABASE_PROVIDER",
|
|
89
|
+
level: "fail",
|
|
90
|
+
message: "DATABASE_PROVIDER is no longer read by the server",
|
|
91
|
+
fix: "Rename it to PARMANA_STORAGE, and remove DATABASE_PROVIDER",
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
let provider;
|
|
96
|
+
try {
|
|
97
|
+
provider = parseStorageProvider(env.PARMANA_STORAGE);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
add({
|
|
101
|
+
name,
|
|
102
|
+
level: "fail",
|
|
103
|
+
message: `${name} has an unsupported value`,
|
|
104
|
+
fix: "Use one of: memory, postgres, supabase",
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (provider === "memory") {
|
|
109
|
+
if (production) {
|
|
110
|
+
add({
|
|
111
|
+
name,
|
|
112
|
+
level: "fail",
|
|
113
|
+
message: "memory storage is not durable, so it is not a production configuration",
|
|
114
|
+
fix: "Set PARMANA_STORAGE to postgres (or supabase), and set DATABASE_URL",
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
else if (env.NODE_ENV === "test") {
|
|
118
|
+
// Tests use in-memory storage on purpose, so this is not a warning there.
|
|
119
|
+
add({
|
|
120
|
+
name,
|
|
121
|
+
level: "pass",
|
|
122
|
+
message: "memory storage, as the test environment expects",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
add({
|
|
127
|
+
name,
|
|
128
|
+
level: "warn",
|
|
129
|
+
message: "memory storage: state is lost when the process stops. Use it for local work only",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
add({ name, level: "pass", message: `${name} is ${provider}` });
|
|
135
|
+
checkDatabaseUrl(env, add);
|
|
136
|
+
if (provider === "supabase" &&
|
|
137
|
+
(env.SUPABASE_URL === undefined || env.SUPABASE_URL === "")) {
|
|
138
|
+
add({
|
|
139
|
+
name: "SUPABASE_URL",
|
|
140
|
+
level: "warn",
|
|
141
|
+
message: "SUPABASE_URL is not set. The Supabase client settings are read by the nonce and audit stores",
|
|
142
|
+
fix: "Set SUPABASE_URL to the project URL",
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const schema = env.PARMANA_DB_SCHEMA;
|
|
147
|
+
if (schema !== undefined && schema !== "" && !SCHEMA_NAME.test(schema)) {
|
|
148
|
+
add({
|
|
149
|
+
name: "PARMANA_DB_SCHEMA",
|
|
150
|
+
level: "fail",
|
|
151
|
+
message: "PARMANA_DB_SCHEMA must be a plain Postgres name",
|
|
152
|
+
fix: "Use a lowercase name, such as parmana_sandbox",
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* PARMANA_DATABASE_CA_FILE: the CA certificate the database is verified against.
|
|
158
|
+
* Checked here as the pool checks it: readable, and holds a certificate. When it
|
|
159
|
+
* is set, an sslmode in DATABASE_URL is ignored, and the doctor says so.
|
|
160
|
+
*/
|
|
161
|
+
function checkDatabaseCaFile(env, readers, add) {
|
|
162
|
+
const path = env.PARMANA_DATABASE_CA_FILE;
|
|
163
|
+
const text = env.PARMANA_DATABASE_CA;
|
|
164
|
+
const hasPath = path !== undefined && path.trim() !== "";
|
|
165
|
+
const hasText = text !== undefined && text.trim() !== "";
|
|
166
|
+
if (!hasPath && !hasText)
|
|
167
|
+
return;
|
|
168
|
+
if (hasPath && hasText) {
|
|
169
|
+
add({
|
|
170
|
+
name: "PARMANA_DATABASE_CA",
|
|
171
|
+
level: "fail",
|
|
172
|
+
message: "both PARMANA_DATABASE_CA_FILE and PARMANA_DATABASE_CA are set",
|
|
173
|
+
fix: "Keep one of them. The server refuses to start with both",
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const name = hasText ? "PARMANA_DATABASE_CA" : "PARMANA_DATABASE_CA_FILE";
|
|
178
|
+
let pem;
|
|
179
|
+
if (hasText) {
|
|
180
|
+
pem = text.replace(/\\n/g, "\n");
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
try {
|
|
184
|
+
pem = readers.readFile(path);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
add({
|
|
188
|
+
name,
|
|
189
|
+
level: "fail",
|
|
190
|
+
message: "the CA file cannot be read",
|
|
191
|
+
fix: "Check the path, and that the service can read the file",
|
|
192
|
+
});
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (!pem.includes("-----BEGIN CERTIFICATE-----")) {
|
|
197
|
+
add({
|
|
198
|
+
name,
|
|
199
|
+
level: "fail",
|
|
200
|
+
message: "the CA value does not hold a PEM certificate",
|
|
201
|
+
fix: "Use the database's root certificate. Do not use a private key",
|
|
202
|
+
});
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (/PRIVATE KEY/.test(pem)) {
|
|
206
|
+
add({
|
|
207
|
+
name,
|
|
208
|
+
level: "fail",
|
|
209
|
+
message: "the CA value holds a private key",
|
|
210
|
+
fix: "Use the root certificate only. Treat the private key as compromised",
|
|
211
|
+
});
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
add({
|
|
215
|
+
name,
|
|
216
|
+
level: "pass",
|
|
217
|
+
message: "the database certificate is verified against this CA",
|
|
218
|
+
});
|
|
219
|
+
if (/[?&]sslmode=/.test(env.DATABASE_URL ?? "")) {
|
|
220
|
+
add({
|
|
221
|
+
name: "DATABASE_URL",
|
|
222
|
+
level: "warn",
|
|
223
|
+
message: "sslmode in DATABASE_URL is ignored while a CA is set. The CA decides the TLS settings",
|
|
224
|
+
fix: "Remove sslmode from DATABASE_URL to avoid confusion",
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* DATABASE_URL is required for postgres and supabase storage. Its value is never
|
|
230
|
+
* printed, because it holds a password. The check reads the scheme only.
|
|
231
|
+
*/
|
|
232
|
+
function checkDatabaseUrl(env, add) {
|
|
233
|
+
const url = env.DATABASE_URL;
|
|
234
|
+
if (url === undefined || url.trim() === "") {
|
|
235
|
+
add({
|
|
236
|
+
name: "DATABASE_URL",
|
|
237
|
+
level: "fail",
|
|
238
|
+
message: "DATABASE_URL is not set, and postgres and supabase storage need it",
|
|
239
|
+
fix: "Set DATABASE_URL to the connection string of the database. It holds a password, so never share it",
|
|
240
|
+
});
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!/^postgres(ql)?:\/\//.test(url)) {
|
|
244
|
+
add({
|
|
245
|
+
name: "DATABASE_URL",
|
|
246
|
+
level: "fail",
|
|
247
|
+
message: "DATABASE_URL does not start with postgres:// or postgresql://",
|
|
248
|
+
fix: "Correct the scheme of the connection string",
|
|
249
|
+
});
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const sslmode = /[?&]sslmode=([a-z-]+)/.exec(url)?.[1];
|
|
253
|
+
if (sslmode === undefined ||
|
|
254
|
+
!["require", "verify-ca", "verify-full"].includes(sslmode)) {
|
|
255
|
+
add({
|
|
256
|
+
name: "DATABASE_URL",
|
|
257
|
+
level: "warn",
|
|
258
|
+
message: `DATABASE_URL sslmode is ${sslmode ?? "not set"}, which does not require TLS. The connection may not be encrypted`,
|
|
259
|
+
fix: "Set sslmode=require (or verify-full) in the connection string, if the database supports TLS",
|
|
260
|
+
});
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
add({
|
|
264
|
+
name: "DATABASE_URL",
|
|
265
|
+
level: "pass",
|
|
266
|
+
message: "DATABASE_URL is set with a postgres scheme and sslmode",
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
function checkCrypto(env, add, production) {
|
|
270
|
+
parseOrFail(add, "CRYPTO_MODE", () => parseCryptoMode(env.CRYPTO_MODE), Object.values(CryptoModes));
|
|
271
|
+
parseOrFail(add, "HASH_PROVIDER", () => parseHashAlgorithm(env.HASH_PROVIDER), Object.values(HashAlgorithms));
|
|
272
|
+
parseOrFail(add, "PRIMARY_SIGNATURE_PROVIDER", () => parseSignatureAlgorithm(env.PRIMARY_SIGNATURE_PROVIDER), signatureNames());
|
|
273
|
+
if (env.SECONDARY_SIGNATURE_PROVIDER !== undefined &&
|
|
274
|
+
env.SECONDARY_SIGNATURE_PROVIDER !== "") {
|
|
275
|
+
parseOrFail(add, "SECONDARY_SIGNATURE_PROVIDER", () => parseSignatureAlgorithm(env.SECONDARY_SIGNATURE_PROVIDER, "SECONDARY_SIGNATURE_PROVIDER"), signatureNames());
|
|
276
|
+
}
|
|
277
|
+
let provider;
|
|
278
|
+
try {
|
|
279
|
+
provider = parseKeyProvider(env.KEY_PROVIDER);
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
add({
|
|
283
|
+
name: "KEY_PROVIDER",
|
|
284
|
+
level: "fail",
|
|
285
|
+
message: "KEY_PROVIDER has an unsupported value",
|
|
286
|
+
fix: "Use local, or aws-kms for production. Other providers are not implemented in this build",
|
|
287
|
+
});
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (provider === KeyProviders.AWS_KMS) {
|
|
291
|
+
if (env.CRYPTO_MODE === "hybrid") {
|
|
292
|
+
add({
|
|
293
|
+
name: "KEY_PROVIDER",
|
|
294
|
+
level: "fail",
|
|
295
|
+
message: "CRYPTO_MODE=hybrid is not supported with KEY_PROVIDER=aws-kms",
|
|
296
|
+
fix: "Use CRYPTO_MODE=single with KMS, or KEY_PROVIDER=local for hybrid signing",
|
|
297
|
+
});
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (production) {
|
|
301
|
+
if (env.AWS_REGION === undefined || env.AWS_REGION.trim() === "") {
|
|
302
|
+
add({
|
|
303
|
+
name: "AWS_REGION",
|
|
304
|
+
level: "fail",
|
|
305
|
+
message: "AWS_REGION is not set, and KMS signing needs it",
|
|
306
|
+
fix: "Set AWS_REGION to the region of the KMS key",
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
add({
|
|
311
|
+
name: "AWS_REGION",
|
|
312
|
+
level: "pass",
|
|
313
|
+
message: "AWS_REGION is set",
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
add({
|
|
317
|
+
name: "KEY_PROVIDER",
|
|
318
|
+
level: "pass",
|
|
319
|
+
message: env.AWS_ROLE_ARN
|
|
320
|
+
? "aws-kms, with AWS_ROLE_ARN for short-lived credentials"
|
|
321
|
+
: "aws-kms. No AWS_ROLE_ARN is set, so credentials come from the environment",
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
add({
|
|
326
|
+
name: "KEY_PROVIDER",
|
|
327
|
+
level: "warn",
|
|
328
|
+
message: "aws-kms: the KMS settings are checked with --production",
|
|
329
|
+
fix: "Run npm run doctor -- --production",
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
add({ name: "KEY_PROVIDER", level: "pass", message: "local key files" });
|
|
335
|
+
}
|
|
336
|
+
function checkHybrid(env, add) {
|
|
337
|
+
try {
|
|
338
|
+
parseHybridSchemaVersion(env.HYBRID_SCHEMA_VERSION, env.HYBRID_SCHEMA_V3_ACKNOWLEDGED);
|
|
339
|
+
add({
|
|
340
|
+
name: "HYBRID_SCHEMA_VERSION",
|
|
341
|
+
level: "pass",
|
|
342
|
+
message: "schema version is valid",
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
add({
|
|
347
|
+
name: "HYBRID_SCHEMA_VERSION",
|
|
348
|
+
level: "fail",
|
|
349
|
+
message: "HYBRID_SCHEMA_VERSION must be 2 or 3. Version 3 also needs HYBRID_SCHEMA_V3_ACKNOWLEDGED=true",
|
|
350
|
+
fix: "Set HYBRID_SCHEMA_VERSION to 2, or set both values for version 3 (ADR-0016)",
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
parseHybridRequiredFrom(env.HYBRID_REQUIRED_FROM);
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
add({
|
|
358
|
+
name: "HYBRID_REQUIRED_FROM",
|
|
359
|
+
level: "fail",
|
|
360
|
+
message: "HYBRID_REQUIRED_FROM must be an ISO-8601 UTC timestamp ending in Z",
|
|
361
|
+
fix: "Use a value such as 2026-12-01T00:00:00Z, or leave it unset",
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
if (env.HYBRID_SIGNATURE_REQUIRED === "true" &&
|
|
365
|
+
env.CRYPTO_MODE !== "hybrid") {
|
|
366
|
+
add({
|
|
367
|
+
name: "HYBRID_SIGNATURE_REQUIRED",
|
|
368
|
+
level: "warn",
|
|
369
|
+
message: "HYBRID_SIGNATURE_REQUIRED=true has no effect unless CRYPTO_MODE=hybrid",
|
|
370
|
+
fix: "Set CRYPTO_MODE=hybrid, or remove HYBRID_SIGNATURE_REQUIRED",
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
function checkKeys(env, readers, add, keyProvider) {
|
|
375
|
+
const name = "PARMANA_KEY_DIR";
|
|
376
|
+
const dir = env.PARMANA_KEY_DIR;
|
|
377
|
+
// The server requires this folder under every key provider, so the check does too.
|
|
378
|
+
if (dir === undefined || dir.trim() === "") {
|
|
379
|
+
add({
|
|
380
|
+
name,
|
|
381
|
+
level: "fail",
|
|
382
|
+
message: `${name} is not set`,
|
|
383
|
+
fix: `Set ${name} to the folder that holds the key files, for example ./keys`,
|
|
384
|
+
});
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
const materialSet = env.PARMANA_KEY_MATERIAL_JSON !== undefined &&
|
|
388
|
+
env.PARMANA_KEY_MATERIAL_JSON.trim() !== "";
|
|
389
|
+
if (materialSet) {
|
|
390
|
+
try {
|
|
391
|
+
const parsed = JSON.parse(env.PARMANA_KEY_MATERIAL_JSON);
|
|
392
|
+
if (typeof parsed !== "object" ||
|
|
393
|
+
parsed === null ||
|
|
394
|
+
Array.isArray(parsed))
|
|
395
|
+
throw new Error("not an object");
|
|
396
|
+
add({
|
|
397
|
+
name: "PARMANA_KEY_MATERIAL_JSON",
|
|
398
|
+
level: "pass",
|
|
399
|
+
message: "valid JSON. Its contents are not printed",
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
add({
|
|
404
|
+
name: "PARMANA_KEY_MATERIAL_JSON",
|
|
405
|
+
level: "fail",
|
|
406
|
+
message: "PARMANA_KEY_MATERIAL_JSON is not a JSON object keyed by key ID",
|
|
407
|
+
fix: 'Use { "<keyId>": { "privateKeyPem": "...", "publicKeyPem": "..." } }',
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
// With KMS the default private key never leaves KMS, so there is no local file to check.
|
|
412
|
+
if (keyProvider === KeyProviders.AWS_KMS) {
|
|
413
|
+
add({
|
|
414
|
+
name: "default key pair",
|
|
415
|
+
level: "pass",
|
|
416
|
+
message: "held in AWS KMS. Its reachability is checked with --online (stage 3)",
|
|
417
|
+
});
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const publicPath = `${dir}/${DEFAULT_KEY_ID}.public.pem`;
|
|
421
|
+
const files = readers.directoryExists(dir) ? readers.listDirectory(dir) : [];
|
|
422
|
+
const present = files.includes(`${DEFAULT_KEY_ID}.private.pem`) &&
|
|
423
|
+
files.includes(`${DEFAULT_KEY_ID}.public.pem`);
|
|
424
|
+
if (present) {
|
|
425
|
+
checkPublicKeyFile(publicPath, readers, add);
|
|
426
|
+
add({
|
|
427
|
+
name: "default key pair",
|
|
428
|
+
level: "pass",
|
|
429
|
+
message: `the default key pair is in ${name}`,
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
else if (materialSet) {
|
|
433
|
+
add({
|
|
434
|
+
name: "default key pair",
|
|
435
|
+
level: "warn",
|
|
436
|
+
message: `the default key pair is not in ${name} yet. The server writes it from PARMANA_KEY_MATERIAL_JSON at startup`,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
add({
|
|
441
|
+
name: "default key pair",
|
|
442
|
+
level: "fail",
|
|
443
|
+
message: `the default key pair is missing from ${name}. The server refuses to start without it`,
|
|
444
|
+
fix: `Generate or copy ${DEFAULT_KEY_ID}.private.pem and ${DEFAULT_KEY_ID}.public.pem into ${name}, or set PARMANA_KEY_MATERIAL_JSON`,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
if (env.CRYPTO_MODE === "hybrid") {
|
|
448
|
+
add({
|
|
449
|
+
name: "hybrid key pairs",
|
|
450
|
+
level: "warn",
|
|
451
|
+
message: "the server checks the hybrid key pairs at startup. This doctor checks only the default key pair",
|
|
452
|
+
fix: "Start the server once to confirm the hybrid keys",
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
/** A public key file must parse as a key and must not hold a private key. */
|
|
457
|
+
function checkPublicKeyFile(path, readers, add) {
|
|
458
|
+
let text;
|
|
459
|
+
try {
|
|
460
|
+
text = readers.readFile(path);
|
|
461
|
+
}
|
|
462
|
+
catch {
|
|
463
|
+
add({
|
|
464
|
+
name: "default public key",
|
|
465
|
+
level: "fail",
|
|
466
|
+
message: "the default public key cannot be read",
|
|
467
|
+
fix: "Check the file permissions in PARMANA_KEY_DIR",
|
|
468
|
+
});
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (/PRIVATE KEY/.test(text)) {
|
|
472
|
+
add({
|
|
473
|
+
name: "default public key",
|
|
474
|
+
level: "fail",
|
|
475
|
+
message: "the default public key file holds a private key",
|
|
476
|
+
fix: "Replace it with the public key. Treat the private key as compromised",
|
|
477
|
+
});
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
try {
|
|
481
|
+
createPublicKey(text);
|
|
482
|
+
add({
|
|
483
|
+
name: "default public key",
|
|
484
|
+
level: "pass",
|
|
485
|
+
message: "readable as a public key",
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
add({
|
|
490
|
+
name: "default public key",
|
|
491
|
+
level: "fail",
|
|
492
|
+
message: "the default public key file is not a valid PEM public key",
|
|
493
|
+
fix: "Regenerate the key pair",
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
function checkPolicy(env, readers, add) {
|
|
498
|
+
const name = "PARMANA_POLICY_DIR";
|
|
499
|
+
const dir = env.PARMANA_POLICY_DIR;
|
|
500
|
+
if (dir === undefined || dir.trim() === "") {
|
|
501
|
+
add({
|
|
502
|
+
name,
|
|
503
|
+
level: "fail",
|
|
504
|
+
message: `${name} is not set. The server refuses to start without it`,
|
|
505
|
+
fix: `Set ${name} to the folder that holds the policy files, for example ./policies`,
|
|
506
|
+
});
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
if (!readers.directoryExists(dir)) {
|
|
510
|
+
add({
|
|
511
|
+
name,
|
|
512
|
+
level: "fail",
|
|
513
|
+
message: `${name} points to a folder that does not exist`,
|
|
514
|
+
fix: `Create the folder, or correct ${name}`,
|
|
515
|
+
});
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
if (readers.listDirectory(dir).length === 0) {
|
|
519
|
+
add({
|
|
520
|
+
name,
|
|
521
|
+
level: "warn",
|
|
522
|
+
message: `${name} is empty. Any request that names a policy will fail with PolicyNotFound`,
|
|
523
|
+
fix: "Add the policy files to the folder",
|
|
524
|
+
});
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
add({
|
|
528
|
+
name,
|
|
529
|
+
level: "pass",
|
|
530
|
+
message: `${name} exists and holds policy files`,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
function checkAuth(env, add, production) {
|
|
534
|
+
// In production the production rules report this as a failure instead.
|
|
535
|
+
if (env.PARMANA_AUTH_DISABLED === "true" && !production) {
|
|
536
|
+
add({
|
|
537
|
+
name: "PARMANA_AUTH_DISABLED",
|
|
538
|
+
level: "warn",
|
|
539
|
+
message: "authentication is disabled. Acceptable only on a local machine",
|
|
540
|
+
fix: "Set PARMANA_AUTH_DISABLED to false, and configure PARMANA_API_KEYS",
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
try {
|
|
544
|
+
const keys = parseApiKeys(env.PARMANA_API_KEYS);
|
|
545
|
+
if (keys.length === 0 && env.PARMANA_AUTH_DISABLED !== "true") {
|
|
546
|
+
add({
|
|
547
|
+
name: "PARMANA_API_KEYS",
|
|
548
|
+
level: "fail",
|
|
549
|
+
message: "no API keys are configured. The server refuses to start unless authentication is disabled",
|
|
550
|
+
fix: 'Set PARMANA_API_KEYS to a JSON array of { "callerId", "keyHash" } entries',
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
else if (keys.length > 0) {
|
|
554
|
+
add({
|
|
555
|
+
name: "PARMANA_API_KEYS",
|
|
556
|
+
level: "pass",
|
|
557
|
+
message: `${keys.length} API key entr${keys.length === 1 ? "y" : "ies"} configured`,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
add({
|
|
563
|
+
name: "PARMANA_API_KEYS",
|
|
564
|
+
level: "fail",
|
|
565
|
+
message: "PARMANA_API_KEYS is not a valid JSON array of { callerId, keyHash } entries",
|
|
566
|
+
fix: "Correct the JSON. Each keyHash is a 64-character lowercase hex SHA-256",
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
function checkTrustProfile(env, add) {
|
|
571
|
+
parseOrFail(add, "TRUST_PROFILE", () => parseTrustProfile(env.TRUST_PROFILE), ["v1"]);
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Numbers are read with Number() and never validated by the server, so a typo
|
|
575
|
+
* becomes NaN and is used as is. Doctor is the one place that catches it.
|
|
576
|
+
*/
|
|
577
|
+
function checkNumbers(env, add) {
|
|
578
|
+
const numbers = [
|
|
579
|
+
{ name: "PORT", fallback: 3000 },
|
|
580
|
+
{ name: "EXECUTION_AUTHORIZATION_TTL_SECONDS", fallback: 120 },
|
|
581
|
+
{ name: "RATE_LIMIT_EXECUTE_PER_MINUTE", fallback: 30 },
|
|
582
|
+
{ name: "RATE_LIMIT_HEALTH_PER_MINUTE", fallback: 300 },
|
|
583
|
+
{ name: "RATE_LIMIT_PUBLIC_PER_MINUTE", fallback: 60 },
|
|
584
|
+
{ name: "RATE_LIMIT_AUTH_FAILURE_PER_MINUTE", fallback: 30 },
|
|
585
|
+
];
|
|
586
|
+
for (const { name, fallback } of numbers) {
|
|
587
|
+
const raw = env[name];
|
|
588
|
+
if (raw === undefined || raw === "")
|
|
589
|
+
continue;
|
|
590
|
+
const value = Number(raw);
|
|
591
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
592
|
+
add({
|
|
593
|
+
name,
|
|
594
|
+
level: "fail",
|
|
595
|
+
message: `${name} must be a whole number of at least 1`,
|
|
596
|
+
fix: `Set ${name} to a whole number, or remove it to use the default (${fallback})`,
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Production rules. Each one mirrors a refusal the server already makes, or a
|
|
603
|
+
* setting the production deployment needs. The server enforces them at startup
|
|
604
|
+
* or on the first request; this reports them before the first start.
|
|
605
|
+
*/
|
|
606
|
+
function checkProduction(env, add, keyProvider) {
|
|
607
|
+
if (env.NODE_ENV !== "production") {
|
|
608
|
+
add({
|
|
609
|
+
name: "NODE_ENV",
|
|
610
|
+
level: "warn",
|
|
611
|
+
message: "NODE_ENV is not production in this environment. The server applies its production refusals only when NODE_ENV=production, so the production deployment must set it",
|
|
612
|
+
fix: "Set NODE_ENV=production in the production environment. Do not set it in your shell for installs or builds",
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
add({ name: "NODE_ENV", level: "pass", message: "NODE_ENV is production" });
|
|
617
|
+
}
|
|
618
|
+
if (env.PARMANA_AUTH_DISABLED === "true") {
|
|
619
|
+
add({
|
|
620
|
+
name: "production: PARMANA_AUTH_DISABLED",
|
|
621
|
+
level: "fail",
|
|
622
|
+
message: "authentication cannot be disabled in production",
|
|
623
|
+
fix: "Set PARMANA_AUTH_DISABLED to false, and configure PARMANA_API_KEYS",
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
if (env.PARMANA_SANDBOX === "true") {
|
|
627
|
+
add({
|
|
628
|
+
name: "PARMANA_SANDBOX",
|
|
629
|
+
level: "fail",
|
|
630
|
+
message: "the sandbox is refused in production",
|
|
631
|
+
fix: "Set PARMANA_SANDBOX to false, or remove it",
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
const killSwitch = env.KILL_SWITCH_ENABLED;
|
|
635
|
+
if (killSwitch === undefined ||
|
|
636
|
+
killSwitch.trim() === "" ||
|
|
637
|
+
killSwitch === "false") {
|
|
638
|
+
add({
|
|
639
|
+
name: "KILL_SWITCH_ENABLED",
|
|
640
|
+
level: "warn",
|
|
641
|
+
message: "the kill switch is off. Production sets it to true (ADR-0017)",
|
|
642
|
+
fix: "Set KILL_SWITCH_ENABLED=true",
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
else if (killSwitch !== "true") {
|
|
646
|
+
add({
|
|
647
|
+
name: "KILL_SWITCH_ENABLED",
|
|
648
|
+
level: "fail",
|
|
649
|
+
message: 'KILL_SWITCH_ENABLED must be "true" or "false"',
|
|
650
|
+
fix: 'Set it to "true" for production',
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
else {
|
|
654
|
+
const twoPerson = env.KILL_SWITCH_RESET_NEEDS_SECOND_OPERATOR;
|
|
655
|
+
if (twoPerson !== "true" && twoPerson !== "false") {
|
|
656
|
+
add({
|
|
657
|
+
name: "KILL_SWITCH_RESET_NEEDS_SECOND_OPERATOR",
|
|
658
|
+
level: "fail",
|
|
659
|
+
message: "must be stated as true or false when the kill switch is on",
|
|
660
|
+
fix: 'Set it to "true" for production (ADR-0017 decision 1)',
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
add({
|
|
665
|
+
name: "KILL_SWITCH_ENABLED",
|
|
666
|
+
level: "pass",
|
|
667
|
+
message: `the kill switch is on, with a second operator required to reset: ${twoPerson}`,
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
try {
|
|
672
|
+
const secrets = parseSecretsProvider(env.PARMANA_SECRETS_PROVIDER);
|
|
673
|
+
if (secrets === SecretsProviders.AWS_SECRETS_MANAGER &&
|
|
674
|
+
(env.AWS_REGION === undefined || env.AWS_REGION.trim() === "")) {
|
|
675
|
+
add({
|
|
676
|
+
name: "PARMANA_SECRETS_PROVIDER",
|
|
677
|
+
level: "fail",
|
|
678
|
+
message: "aws-secrets-manager needs AWS_REGION",
|
|
679
|
+
fix: "Set AWS_REGION to the region of the secret store",
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
add({
|
|
684
|
+
name: "PARMANA_SECRETS_PROVIDER",
|
|
685
|
+
level: "pass",
|
|
686
|
+
message: `secrets come from ${secrets}`,
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
catch {
|
|
691
|
+
add({
|
|
692
|
+
name: "PARMANA_SECRETS_PROVIDER",
|
|
693
|
+
level: "fail",
|
|
694
|
+
message: "PARMANA_SECRETS_PROVIDER has an unsupported value",
|
|
695
|
+
fix: "Use env, or aws-secrets-manager",
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
if (env.PARMANA_KEY_MATERIAL_JSON !== undefined &&
|
|
699
|
+
env.PARMANA_KEY_MATERIAL_JSON.trim() !== "") {
|
|
700
|
+
add({
|
|
701
|
+
name: "production: PARMANA_KEY_MATERIAL_JSON",
|
|
702
|
+
level: "warn",
|
|
703
|
+
message: "keys are written at startup from an environment variable. That is a fallback for platforms without a secret mount",
|
|
704
|
+
fix: "Prefer a mounted secret file, or KEY_PROVIDER=aws-kms",
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
if (keyProvider === KeyProviders.LOCAL) {
|
|
708
|
+
add({
|
|
709
|
+
name: "production: KEY_PROVIDER",
|
|
710
|
+
level: "warn",
|
|
711
|
+
message: "signing keys are local files. Production is designed for aws-kms",
|
|
712
|
+
fix: "Confirm the key files are on a protected volume, or move to KEY_PROVIDER=aws-kms",
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* A PARMANA_ name no code reads is almost always a typo, and the server ignores
|
|
718
|
+
* it silently. Each one is reported with the closest real name, and its value
|
|
719
|
+
* is never printed.
|
|
720
|
+
*/
|
|
721
|
+
function checkUnknownSettings(env, add) {
|
|
722
|
+
const known = new Set(KNOWN_PARMANA_SETTINGS);
|
|
723
|
+
for (const key of Object.keys(env)) {
|
|
724
|
+
if (!key.startsWith("PARMANA_") || known.has(key) || env[key] === undefined)
|
|
725
|
+
continue;
|
|
726
|
+
const closest = closestSetting(key);
|
|
727
|
+
add({
|
|
728
|
+
name: key,
|
|
729
|
+
level: "warn",
|
|
730
|
+
message: closest === undefined
|
|
731
|
+
? `${key} is not read by any Parmana component, so it has no effect`
|
|
732
|
+
: `${key} is not read by any Parmana component. Did you mean ${closest}?`,
|
|
733
|
+
fix: closest === undefined
|
|
734
|
+
? "Remove it, or correct its name"
|
|
735
|
+
: `Rename ${key} to ${closest}, or remove it`,
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
function parseOrFail(add, name, parse, allowed) {
|
|
740
|
+
try {
|
|
741
|
+
parse();
|
|
742
|
+
add({ name, level: "pass", message: `${name} is valid` });
|
|
743
|
+
}
|
|
744
|
+
catch {
|
|
745
|
+
add({
|
|
746
|
+
name,
|
|
747
|
+
level: "fail",
|
|
748
|
+
message: `${name} has an unsupported value`,
|
|
749
|
+
fix: `Use one of: ${allowed.join(", ")}`,
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
function signatureNames() {
|
|
754
|
+
return [...Object.values(SignatureAlgorithms), "ml-dsa-65"];
|
|
755
|
+
}
|
|
756
|
+
/** The known setting within two edits of the given name, if there is one. */
|
|
757
|
+
export function closestSetting(name) {
|
|
758
|
+
let best;
|
|
759
|
+
let bestDistance = 3;
|
|
760
|
+
for (const candidate of KNOWN_PARMANA_SETTINGS) {
|
|
761
|
+
const distance = editDistance(name, candidate);
|
|
762
|
+
if (distance < bestDistance) {
|
|
763
|
+
best = candidate;
|
|
764
|
+
bestDistance = distance;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return best;
|
|
768
|
+
}
|
|
769
|
+
function editDistance(a, b) {
|
|
770
|
+
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
771
|
+
for (let i = 1; i <= a.length; i++) {
|
|
772
|
+
const current = [i];
|
|
773
|
+
for (let j = 1; j <= b.length; j++) {
|
|
774
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
775
|
+
current.push(Math.min((current[j - 1] ?? 0) + 1, (previous[j] ?? 0) + 1, (previous[j - 1] ?? 0) + cost));
|
|
776
|
+
}
|
|
777
|
+
previous = current;
|
|
778
|
+
}
|
|
779
|
+
return previous[b.length] ?? 0;
|
|
780
|
+
}
|
|
781
|
+
//# sourceMappingURL=Doctor.js.map
|