@wildo-ai/saas-models 1.1.9 → 1.1.10
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/_inspect.d.ts.map +1 -1
- package/dist/esm/_inspect.js.map +1 -1
- package/dist/esm/applications/application-metadata.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/applications/application-metadata.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/applications/application-subject.shared.schemas.d.ts.map +1 -1
- package/dist/esm/applications/application-subject.shared.schemas.js.map +1 -1
- package/dist/esm/applications/application-versions.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/applications/application-versions.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/applications/applications-context.schemas.d.ts +68 -2
- package/dist/esm/applications/applications-context.schemas.d.ts.map +1 -1
- package/dist/esm/applications/applications-context.schemas.js.map +1 -1
- package/dist/esm/applications/applications.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/applications/applications.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/applications/applications.shared.schemas.d.ts.map +1 -1
- package/dist/esm/applications/applications.shared.schemas.js.map +1 -1
- package/dist/esm/billing/billing-account.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/billing-account.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/billing-account.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/billing-account.shared.schemas.js.map +1 -1
- package/dist/esm/billing/billing-configuration.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/billing-configuration.shared.schemas.js.map +1 -1
- package/dist/esm/billing/billing-enums.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/billing-enums.shared.schemas.js.map +1 -1
- package/dist/esm/billing/billing-types.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/billing-types.shared.schemas.js.map +1 -1
- package/dist/esm/billing/credit-pool.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/credit-pool.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/credit-pool.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/credit-pool.shared.schemas.js.map +1 -1
- package/dist/esm/billing/invoice-ref.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/invoice-ref.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/invoice-ref.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/invoice-ref.shared.schemas.js.map +1 -1
- package/dist/esm/billing/price.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/price.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/price.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/price.shared.schemas.js.map +1 -1
- package/dist/esm/billing/product-behavior-policy.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/product-behavior-policy.shared.schemas.js.map +1 -1
- package/dist/esm/billing/product-definition.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/product-definition.shared.schemas.js.map +1 -1
- package/dist/esm/billing/product.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/product.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/product.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/product.shared.schemas.js.map +1 -1
- package/dist/esm/billing/promotions.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/promotions.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/promotions.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/promotions.shared.schemas.js.map +1 -1
- package/dist/esm/billing/public-pricing-catalog.shared.atoms.d.ts.map +1 -1
- package/dist/esm/billing/public-pricing-catalog.shared.atoms.js.map +1 -1
- package/dist/esm/billing/public-pricing-catalog.shared.d.ts.map +1 -1
- package/dist/esm/billing/public-pricing-catalog.shared.js.map +1 -1
- package/dist/esm/billing/referral-reward.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/referral-reward.shared.schemas.js.map +1 -1
- package/dist/esm/billing/referral.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/referral.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/referral.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/referral.shared.schemas.js.map +1 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/subscription.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/subscription.shared.schemas.js.map +1 -1
- package/dist/esm/billing/usage-flush-evidence.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/usage-flush-evidence.shared.schemas.js.map +1 -1
- package/dist/esm/billing/usage-record.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/usage-record.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/usage-record.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/usage-record.shared.schemas.js.map +1 -1
- package/dist/esm/charts/aggregation-query.shared.schemas.d.ts.map +1 -1
- package/dist/esm/charts/aggregation-query.shared.schemas.js.map +1 -1
- package/dist/esm/charts/aggregation.shared.definitions.d.ts.map +1 -1
- package/dist/esm/charts/aggregation.shared.definitions.js.map +1 -1
- package/dist/esm/charts/chart-definition-builder.shared.d.ts.map +1 -1
- package/dist/esm/charts/chart-definition-builder.shared.js.map +1 -1
- package/dist/esm/companion/artifact-placement.shared.definitions.d.ts.map +1 -1
- package/dist/esm/companion/artifact-placement.shared.definitions.js.map +1 -1
- package/dist/esm/companion/provider-discovery.shared.schemas.d.ts.map +1 -1
- package/dist/esm/companion/provider-discovery.shared.schemas.js.map +1 -1
- package/dist/esm/companion/shared-library-companion.shared.definitions.d.ts.map +1 -1
- package/dist/esm/companion/shared-library-companion.shared.definitions.js.map +1 -1
- package/dist/esm/companion-exports.d.ts.map +1 -1
- package/dist/esm/companion-exports.js.map +1 -1
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.d.ts +1 -1
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.js +5 -2
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-actor.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-actor.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-event-classification.shared.d.ts +28 -0
- package/dist/esm/compliance/audit-trails/audit-event-classification.shared.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/audit-event-classification.shared.js +30 -0
- package/dist/esm/compliance/audit-trails/audit-event-classification.shared.js.map +1 -0
- package/dist/esm/compliance/audit-trails/audit-export-projection.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-export-projection.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-log-sink.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-log-sink.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-logs.shared.resources-config.schemas.d.ts +1 -1
- package/dist/esm/compliance/audit-trails/audit-logs.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-logs.shared.resources-config.schemas.js +2 -1
- package/dist/esm/compliance/audit-trails/audit-logs.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.d.ts +20 -0
- package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.js +40 -0
- package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.d.ts +1 -14
- package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.js +1 -16
- package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.js.map +1 -1
- package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.d.ts +17 -4
- package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.js +25 -5
- package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.js.map +1 -1
- package/dist/esm/compliance/data-classification/data-classification.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/data-classification/data-classification.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/documents/governed-document-interactions.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/documents/governed-document-interactions.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/documents/governed-documents.shared.schemas.d.ts +0 -50
- package/dist/esm/compliance/documents/governed-documents.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/documents/governed-documents.shared.schemas.js +4 -51
- package/dist/esm/compliance/documents/governed-documents.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/documents/public-governed-documents.shared.d.ts +67 -0
- package/dist/esm/compliance/documents/public-governed-documents.shared.d.ts.map +1 -0
- package/dist/esm/compliance/documents/public-governed-documents.shared.js +69 -0
- package/dist/esm/compliance/documents/public-governed-documents.shared.js.map +1 -0
- package/dist/esm/compliance/documents/user-governed-document-acceptances.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/documents/user-governed-document-acceptances.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/compliance/documents/user-governed-document-acceptances.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/documents/user-governed-document-acceptances.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/ai-use-posture.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/ai-use-posture.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/capability-consent-purposes.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/capability-consent-purposes.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/client-storage.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/client-storage.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/consent-gate-vocabulary.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/consent-gate-vocabulary.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/consent-purposes.shared.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/consent-purposes.shared.js.map +1 -1
- package/dist/esm/compliance/privacy/data-subject-rights.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/data-subject-rights.shared.schemas.js +1 -1
- package/dist/esm/compliance/privacy/data-subject-rights.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization-scrub.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization-scrub.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/jurisdiction-containment.shared.d.ts +32 -0
- package/dist/esm/compliance/privacy/jurisdiction-containment.shared.d.ts.map +1 -0
- package/dist/esm/compliance/privacy/jurisdiction-containment.shared.js +46 -0
- package/dist/esm/compliance/privacy/jurisdiction-containment.shared.js.map +1 -0
- package/dist/esm/compliance/privacy/legal-hold-subject-attribution.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/legal-hold-subject-attribution.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/legal-holds.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/legal-holds.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/legal-holds.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/legal-holds.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/legal-notice-obligation.shared.d.ts +47 -0
- package/dist/esm/compliance/privacy/legal-notice-obligation.shared.d.ts.map +1 -0
- package/dist/esm/compliance/privacy/legal-notice-obligation.shared.js +54 -0
- package/dist/esm/compliance/privacy/legal-notice-obligation.shared.js.map +1 -0
- package/dist/esm/compliance/privacy/legal-notice.shared.d.ts +105 -0
- package/dist/esm/compliance/privacy/legal-notice.shared.d.ts.map +1 -0
- package/dist/esm/compliance/privacy/legal-notice.shared.js +112 -0
- package/dist/esm/compliance/privacy/legal-notice.shared.js.map +1 -0
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts +1 -27
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.js +2 -41
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/operator-compliance-identity.shared.schemas.d.ts +51 -0
- package/dist/esm/compliance/privacy/operator-compliance-identity.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/operator-compliance-identity.shared.schemas.js +65 -0
- package/dist/esm/compliance/privacy/operator-compliance-identity.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/personal-data-category.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/personal-data-category.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/personal-data-declaration.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/personal-data-declaration.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/privacy.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/privacy.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/provider-capability-disclosure.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/provider-capability-disclosure.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/purpose-ref.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/purpose-ref.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/redaction.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/redaction.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/retention-binding.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/retention-binding.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/retention-enforcement-records.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/retention-enforcement-records.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/retention-enforcement-records.shared.schemas.d.ts +8 -8
- package/dist/esm/compliance/privacy/retention-enforcement-records.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/retention-enforcement-records.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/retention-schedule.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/retention-schedule.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/retention-scope-deleted.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/retention-scope-deleted.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/sharing.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/sharing.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/subject-data-recipients.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/subject-data-recipients.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/subject-erasure-lane-evidence.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/subject-erasure-lane-evidence.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/subject-erasure.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/subject-erasure.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/subject-export-render.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/subject-export-render.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/subject-export.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/subject-export.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/review-cadence.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/review-cadence.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/risk-posture.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/risk-posture.shared.schemas.js.map +1 -1
- package/dist/esm/config/analytics-value-moments.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/analytics-value-moments.shared.schemas.js.map +1 -1
- package/dist/esm/config/app-configuration-shared.shared.schemas.d.ts +63 -1
- package/dist/esm/config/app-configuration-shared.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/app-configuration-shared.shared.schemas.js +11 -0
- package/dist/esm/config/app-configuration-shared.shared.schemas.js.map +1 -1
- package/dist/esm/config/app-frontend-type.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/app-frontend-type.shared.schemas.js.map +1 -1
- package/dist/esm/config/auth-config-resolution.shared.utils.d.ts.map +1 -1
- package/dist/esm/config/auth-config-resolution.shared.utils.js.map +1 -1
- package/dist/esm/config/brand-assets.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/brand-assets.shared.schemas.js.map +1 -1
- package/dist/esm/config/configuration-validation.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/configuration-validation.shared.schemas.js.map +1 -1
- package/dist/esm/config/entity-identity-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/entity-identity-config.shared.schemas.js.map +1 -1
- package/dist/esm/config/frontend/chart-definition.shared.schemas.d.ts +16 -16
- package/dist/esm/config/frontend/chart-definition.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/frontend/chart-definition.shared.schemas.js.map +1 -1
- package/dist/esm/config/frontend/chart-registration-alignment.shared.d.ts.map +1 -1
- package/dist/esm/config/frontend/chart-registration-alignment.shared.js.map +1 -1
- package/dist/esm/config/frontend/navigation.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/frontend/navigation.shared.schemas.js.map +1 -1
- package/dist/esm/config/frontend/onboarding.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/frontend/onboarding.shared.schemas.js.map +1 -1
- package/dist/esm/config/postgresql.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/postgresql.shared.schemas.js.map +1 -1
- package/dist/esm/config/registration-acquisition-policy.shared.utils.d.ts.map +1 -1
- package/dist/esm/config/registration-acquisition-policy.shared.utils.js.map +1 -1
- package/dist/esm/config-authoring.entry.d.ts.map +1 -1
- package/dist/esm/config-authoring.entry.js.map +1 -1
- package/dist/esm/crdt/crdt-merge.shared.utils.d.ts.map +1 -1
- package/dist/esm/crdt/crdt-merge.shared.utils.js.map +1 -1
- package/dist/esm/data-seeding/data-seeding-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/data-seeding/data-seeding-config.shared.schemas.js.map +1 -1
- package/dist/esm/errors/caught-error-description.shared.utils.d.ts +5 -1
- package/dist/esm/errors/caught-error-description.shared.utils.d.ts.map +1 -1
- package/dist/esm/errors/caught-error-description.shared.utils.js +48 -4
- package/dist/esm/errors/caught-error-description.shared.utils.js.map +1 -1
- package/dist/esm/errors/errors.custom-message-ref.shared.definitions.d.ts.map +1 -1
- package/dist/esm/errors/errors.custom-message-ref.shared.definitions.js.map +1 -1
- package/dist/esm/errors/errors.shared.definitions.d.ts.map +1 -1
- package/dist/esm/errors/errors.shared.definitions.js.map +1 -1
- package/dist/esm/errors/errors.shared.schemas.d.ts.map +1 -1
- package/dist/esm/errors/errors.shared.schemas.js.map +1 -1
- package/dist/esm/errors/errors.shared.utils.d.ts.map +1 -1
- package/dist/esm/errors/errors.shared.utils.js.map +1 -1
- package/dist/esm/errors/resource-access-forbidden.shared.error.d.ts.map +1 -1
- package/dist/esm/errors/resource-access-forbidden.shared.error.js.map +1 -1
- package/dist/esm/errors/thrown-value-description.shared.utils.d.ts.map +1 -1
- package/dist/esm/errors/thrown-value-description.shared.utils.js.map +1 -1
- package/dist/esm/errors/zod-issue-formatting.shared.utils.d.ts.map +1 -1
- package/dist/esm/errors/zod-issue-formatting.shared.utils.js.map +1 -1
- package/dist/esm/exports/tabular-csv.shared.utils.d.ts.map +1 -1
- package/dist/esm/exports/tabular-csv.shared.utils.js.map +1 -1
- package/dist/esm/external-data/external-data-pipeline-description.shared.d.ts.map +1 -1
- package/dist/esm/external-data/external-data-pipeline-description.shared.js.map +1 -1
- package/dist/esm/external-data/external-data-pipeline-pass-mode.shared.d.ts.map +1 -1
- package/dist/esm/external-data/external-data-pipeline-pass-mode.shared.js.map +1 -1
- package/dist/esm/external-data/external-data-pipeline.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-data/external-data-pipeline.shared.schemas.js.map +1 -1
- package/dist/esm/external-data/external-data-provenance.shared.d.ts.map +1 -1
- package/dist/esm/external-data/external-data-provenance.shared.js.map +1 -1
- package/dist/esm/external-data.exports.d.ts.map +1 -1
- package/dist/esm/external-data.exports.js.map +1 -1
- package/dist/esm/external-providers/compose-provider-registry.shared.d.ts.map +1 -1
- package/dist/esm/external-providers/compose-provider-registry.shared.js.map +1 -1
- package/dist/esm/external-providers/engine-capabilities.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/engine-capabilities.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/engine-capability-resolution-mode.shared.d.ts.map +1 -1
- package/dist/esm/external-providers/engine-capability-resolution-mode.shared.js.map +1 -1
- package/dist/esm/external-providers/engine-capability-surface.shared.d.ts.map +1 -1
- package/dist/esm/external-providers/engine-capability-surface.shared.js.map +1 -1
- package/dist/esm/external-providers/external-providers.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/external-providers.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/frontend-bootstrap.shared.schemas.d.ts +34 -1
- package/dist/esm/external-providers/frontend-bootstrap.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/frontend-bootstrap.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/frontend-capability-runtime.shared.types.d.ts.map +1 -1
- package/dist/esm/external-providers/frontend-capability-runtime.shared.types.js.map +1 -1
- package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/frontend-provider-public-config.shared.d.ts.map +1 -1
- package/dist/esm/external-providers/frontend-provider-public-config.shared.js.map +1 -1
- package/dist/esm/external-providers/model-cost-accounting-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/model-cost-accounting-config.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-address-lookup-contract.shared.types.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-address-lookup-contract.shared.types.js.map +1 -1
- package/dist/esm/external-providers/provider-augmentation-opt-ins.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-augmentation-opt-ins.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-authentication-assurance.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-authentication-assurance.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-browser-operations.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-browser-operations.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-capability.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-capability.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-compliance-profile.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-compliance-profile.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-frontend-component-contract.shared.types.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-frontend-component-contract.shared.types.js.map +1 -1
- package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-metadata.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-metadata.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-package-allow-list.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-package-allow-list.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-protocol.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-protocol.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-scope-reauthorization.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-scope-reauthorization.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-shared-connections.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-shared-connections.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-tier-rule.shared.utils.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-tier-rule.shared.utils.js.map +1 -1
- package/dist/esm/external-providers/provider-usage-cost.shared.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-usage-cost.shared.js.map +1 -1
- package/dist/esm/external-providers/provider-usage-pricing.example.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-usage-pricing.example.js.map +1 -1
- package/dist/esm/external-providers/provider-usage-pricing.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-usage-pricing.shared.schemas.js.map +1 -1
- package/dist/esm/features/application-features.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/features/application-features.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/features/connected-feature.example.d.ts.map +1 -1
- package/dist/esm/features/connected-feature.example.js.map +1 -1
- package/dist/esm/features/core-feature-definitions.shared.d.ts.map +1 -1
- package/dist/esm/features/core-feature-definitions.shared.js.map +1 -1
- package/dist/esm/features/feature-builders.shared.d.ts.map +1 -1
- package/dist/esm/features/feature-builders.shared.js.map +1 -1
- package/dist/esm/features/feature-definition.shared.schemas.d.ts.map +1 -1
- package/dist/esm/features/feature-definition.shared.schemas.js.map +1 -1
- package/dist/esm/features/feature-registry.shared.d.ts.map +1 -1
- package/dist/esm/features/feature-registry.shared.js.map +1 -1
- package/dist/esm/features/feature-resolution.shared.schemas.d.ts.map +1 -1
- package/dist/esm/features/feature-resolution.shared.schemas.js.map +1 -1
- package/dist/esm/features/scope-features.shared.schemas.d.ts.map +1 -1
- package/dist/esm/features/scope-features.shared.schemas.js.map +1 -1
- package/dist/esm/features/user-features.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/features/user-features.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/files/file-remote-reference-link.shared.schemas.d.ts.map +1 -1
- package/dist/esm/files/file-remote-reference-link.shared.schemas.js.map +1 -1
- package/dist/esm/files/file-upload-grant.shared.schemas.d.ts.map +1 -1
- package/dist/esm/files/file-upload-grant.shared.schemas.js.map +1 -1
- package/dist/esm/files/files.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/files/files.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/files/files.shared.schemas.d.ts.map +1 -1
- package/dist/esm/files/files.shared.schemas.js.map +1 -1
- package/dist/esm/files/files.shared.utils.d.ts.map +1 -1
- package/dist/esm/files/files.shared.utils.js.map +1 -1
- package/dist/esm/flows-actors/a2a-push-delivery-log.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a-push-delivery-log.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/a2a-push-delivery-log.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a-push-delivery-log.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/a2a-token-budget-state.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a-token-budget-state.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/a2a-token-budget-state.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a-token-budget-state.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/actors.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/actors.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/agent-traceability.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/agent-traceability.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/agent-work-decisions.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/agent-work-decisions.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/agent-work-decisions.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/agent-work-decisions.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/agents.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/agents.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/autonomous-agents.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/autonomous-agents.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/deliberation.shared.schemas.d.ts +2 -1
- package/dist/esm/flows-actors/deliberation.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/deliberation.shared.schemas.js +2 -1
- package/dist/esm/flows-actors/deliberation.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/execution-plan-readiness.shared.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/execution-plan-readiness.shared.utils.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors-execution.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors-execution.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors-execution.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors-execution.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors-task.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors-task.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors-task.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors-task.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors.commons.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors.commons.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors.configuration.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors.configuration.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors.frontend.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors.frontend.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors.io.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors.io.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors.system.shared.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors.system.shared.definitions.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors.system.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows-actors.system.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/flows.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/human-decision.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/human-decision.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/mcp-servers.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/mcp-servers.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/model-call-attributions.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/model-call-attributions.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/model-call-attributions.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/model-call-attributions.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/model-cost-period-aggregates.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/model-cost-period-aggregates.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/model-cost-period-aggregates.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/model-cost-period-aggregates.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/model-cost-summary.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/model-cost-summary.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/prompt-ir.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/prompt-ir.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/provider-call-records.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/provider-call-records.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/flows-actors/provider-call-records.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/provider-call-records.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/review-deadlines.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/review-deadlines.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/tasks.actors.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/tasks.actors.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/work-attribution.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/work-attribution.shared.schemas.js.map +1 -1
- package/dist/esm/frontend-definitions/frontend-notification-custom-message-ref.definitions.d.ts.map +1 -1
- package/dist/esm/frontend-definitions/frontend-notification-custom-message-ref.definitions.js.map +1 -1
- package/dist/esm/frontend-definitions/settings-destination-ref.definitions.d.ts.map +1 -1
- package/dist/esm/frontend-definitions/settings-destination-ref.definitions.js.map +1 -1
- package/dist/esm/guidance/guidance-flow.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/guidance-flow.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/guidance-state.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/guidance-state.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/guidance/guidance-state.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/guidance-state.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/guidance-state.shared.utils.d.ts.map +1 -1
- package/dist/esm/guidance/guidance-state.shared.utils.js.map +1 -1
- package/dist/esm/guidance/lifecycle-config.shared.schemas.d.ts +2 -2
- package/dist/esm/guidance/lifecycle-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/lifecycle-config.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/lifecycle-state.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/lifecycle-state.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/guidance/lifecycle-state.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/lifecycle-state.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/milestone-builders.shared.d.ts.map +1 -1
- package/dist/esm/guidance/milestone-builders.shared.js.map +1 -1
- package/dist/esm/guidance/milestone-definition.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/milestone-definition.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/progression-presentation.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/progression-presentation.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/progression-state.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/progression-state.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/guidance/progression-state.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/progression-state.shared.schemas.js.map +1 -1
- package/dist/esm/http-api-binding/http-api-binding-id.shared.utils.d.ts.map +1 -1
- package/dist/esm/http-api-binding/http-api-binding-id.shared.utils.js.map +1 -1
- package/dist/esm/http-api-binding/http-api-binding.shared.schemas.d.ts.map +1 -1
- package/dist/esm/http-api-binding/http-api-binding.shared.schemas.js.map +1 -1
- package/dist/esm/http-api-binding/http-api-erasure-stance.shared.d.ts.map +1 -1
- package/dist/esm/http-api-binding/http-api-erasure-stance.shared.js.map +1 -1
- package/dist/esm/http-api-binding/http-api-rest-write-operations.shared.schemas.d.ts.map +1 -1
- package/dist/esm/http-api-binding/http-api-rest-write-operations.shared.schemas.js.map +1 -1
- package/dist/esm/http-api-binding/http-api-transport-dialect.shared.d.ts.map +1 -1
- package/dist/esm/http-api-binding/http-api-transport-dialect.shared.js.map +1 -1
- package/dist/esm/http-api-binding/read-through-engine-anchors.shared.d.ts.map +1 -1
- package/dist/esm/http-api-binding/read-through-engine-anchors.shared.js.map +1 -1
- package/dist/esm/i18n/application-config-vocabulary.shared.d.ts.map +1 -1
- package/dist/esm/i18n/application-config-vocabulary.shared.js.map +1 -1
- package/dist/esm/i18n/engine-open-vocabulary-values.shared.d.ts.map +1 -1
- package/dist/esm/i18n/engine-open-vocabulary-values.shared.js.map +1 -1
- package/dist/esm/i18n/engine-open-vocabulary.shared.d.ts.map +1 -1
- package/dist/esm/i18n/engine-open-vocabulary.shared.js.map +1 -1
- package/dist/esm/i18n/interpolate-label-params.shared.utils.d.ts.map +1 -1
- package/dist/esm/i18n/interpolate-label-params.shared.utils.js.map +1 -1
- package/dist/esm/i18n/labelling.dto.shared.schemas.d.ts.map +1 -1
- package/dist/esm/i18n/labelling.dto.shared.schemas.js.map +1 -1
- package/dist/esm/inbound/conversation-threads.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/inbound/conversation-threads.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/inbound/conversation-threads.shared.schemas.d.ts.map +1 -1
- package/dist/esm/inbound/conversation-threads.shared.schemas.js.map +1 -1
- package/dist/esm/inbound/inbound-channels.shared.schemas.d.ts.map +1 -1
- package/dist/esm/inbound/inbound-channels.shared.schemas.js.map +1 -1
- package/dist/esm/inbound/inbound-delivery.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/inbound/inbound-delivery.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/inbound/inbound-delivery.shared.schemas.d.ts.map +1 -1
- package/dist/esm/inbound/inbound-delivery.shared.schemas.js.map +1 -1
- package/dist/esm/inbound/inbound-endpoint-env.shared.d.ts.map +1 -1
- package/dist/esm/inbound/inbound-endpoint-env.shared.js.map +1 -1
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/meta-workflows/actions.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/actions.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows/catalog.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/catalog.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows/coding-tasks.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/coding-tasks.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows/context-selection.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/context-selection.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows/decisions.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/decisions.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows/elicitation-depth.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/elicitation-depth.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows/orchestration.meta-workflows.shared.schemas.d.ts +13 -1
- package/dist/esm/meta-workflows/orchestration.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/orchestration.meta-workflows.shared.schemas.js +21 -1
- package/dist/esm/meta-workflows/orchestration.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows/portable-primitives.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/meta-workflows/portable-primitives.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/meta-workflows.exports.d.ts.map +1 -1
- package/dist/esm/meta-workflows.exports.js.map +1 -1
- package/dist/esm/monitoring/monitoring.shared.schemas.d.ts.map +1 -1
- package/dist/esm/monitoring/monitoring.shared.schemas.js.map +1 -1
- package/dist/esm/notifications/email/email-context.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/email/email-context.shared.schemas.js.map +1 -1
- package/dist/esm/notifications/email/email-submission.shared.enums.d.ts.map +1 -1
- package/dist/esm/notifications/email/email-submission.shared.enums.js.map +1 -1
- package/dist/esm/notifications/email/email-template-registry.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/email/email-template-registry.shared.schemas.js.map +1 -1
- package/dist/esm/notifications/email/email-template.shared.enums.d.ts.map +1 -1
- package/dist/esm/notifications/email/email-template.shared.enums.js.map +1 -1
- package/dist/esm/notifications/inbound-email/inbound-email.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/inbound-email/inbound-email.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/notifications/inbound-email/inbound-email.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/inbound-email/inbound-email.shared.schemas.js.map +1 -1
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-contract.shared.d.ts.map +1 -1
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-contract.shared.js.map +1 -1
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-log.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-log.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-log.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-log.shared.schemas.js.map +1 -1
- package/dist/esm/notifications/m2m/webhook-config.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/m2m/webhook-config.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/notifications/m2m/webhook-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/m2m/webhook-config.shared.schemas.js.map +1 -1
- package/dist/esm/notifications/notification-badges.core.definitions.d.ts.map +1 -1
- package/dist/esm/notifications/notification-badges.core.definitions.js.map +1 -1
- package/dist/esm/notifications/notification-badges.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/notification-badges.schemas.js.map +1 -1
- package/dist/esm/notifications/notification-badges.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/notification-badges.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/notifications/notifications.shared.schemas.d.ts +5 -3
- package/dist/esm/notifications/notifications.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/notifications.shared.schemas.js +5 -3
- package/dist/esm/notifications/notifications.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/application-owner-organization.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/application-owner-organization.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-features.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-features.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-features.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-features.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-members.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-members.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-members.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-members.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-notifications.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-notifications.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-notifications.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-notifications.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-preferences.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-preferences.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-preferences.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-preferences.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-profile.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-profile.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-profile.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-profile.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-unit-inheritance.shared.d.ts.map +1 -1
- package/dist/esm/organizations/organization-unit-inheritance.shared.js.map +1 -1
- package/dist/esm/organizations/organization-unit-members.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-unit-members.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-unit-members.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-unit-members.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing-decision.shared.d.ts.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing-decision.shared.js.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing.example.d.ts.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing.example.js.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing.shared.d.ts.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing.shared.js.map +1 -1
- package/dist/esm/organizations/organization-units.shared.path.d.ts.map +1 -1
- package/dist/esm/organizations/organization-units.shared.path.js.map +1 -1
- package/dist/esm/organizations/organization-units.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-units.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-units.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-units.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organizations.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organizations.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/organizations.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organizations.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/service-provider-activity-feed.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/service-provider-activity-feed.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/service-provider-activity-feed.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/service-provider-activity-feed.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/service-provider-capability-grants.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/service-provider-capability-grants.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/service-provider-capability-grants.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/service-provider-capability-grants.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/service-provider-client-controls.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/service-provider-client-controls.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/service-provider-relationships.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/service-provider-relationships.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/organizations/service-provider-relationships.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/service-provider-relationships.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/tenant-teardown-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/tenant-teardown-config.shared.schemas.js.map +1 -1
- package/dist/esm/provider-registration-runtime.exports.d.ts.map +1 -1
- package/dist/esm/provider-registration-runtime.exports.js.map +1 -1
- package/dist/esm/public-runtime/index.d.ts +13 -0
- package/dist/esm/public-runtime/index.d.ts.map +1 -1
- package/dist/esm/public-runtime/index.js +13 -0
- package/dist/esm/public-runtime/index.js.map +1 -1
- package/dist/esm/queue/jobs.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/queue/jobs.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/queue/jobs.shared.schemas.d.ts +1 -1
- package/dist/esm/queue/jobs.shared.schemas.d.ts.map +1 -1
- package/dist/esm/queue/jobs.shared.schemas.js.map +1 -1
- package/dist/esm/queue/jobs.shared.utils.d.ts.map +1 -1
- package/dist/esm/queue/jobs.shared.utils.js.map +1 -1
- package/dist/esm/queue/queues.shared.schemas.d.ts.map +1 -1
- package/dist/esm/queue/queues.shared.schemas.js.map +1 -1
- package/dist/esm/queue/queues.shared.utils.d.ts.map +1 -1
- package/dist/esm/queue/queues.shared.utils.js.map +1 -1
- package/dist/esm/queue/rabbitmq-queue-args.shared.d.ts.map +1 -1
- package/dist/esm/queue/rabbitmq-queue-args.shared.js.map +1 -1
- package/dist/esm/rag/rag-retrieval-health.shared.d.ts.map +1 -1
- package/dist/esm/rag/rag-retrieval-health.shared.js.map +1 -1
- package/dist/esm/requests/header-keys.shared.d.ts.map +1 -1
- package/dist/esm/requests/header-keys.shared.js.map +1 -1
- package/dist/esm/requests/http-requests.shared.d.ts.map +1 -1
- package/dist/esm/requests/http-requests.shared.js.map +1 -1
- package/dist/esm/requests/idempotency-key.shared.d.ts.map +1 -1
- package/dist/esm/requests/idempotency-key.shared.js.map +1 -1
- package/dist/esm/requests/manual-controllers-routes-documentation.d.ts.map +1 -1
- package/dist/esm/requests/manual-controllers-routes-documentation.js.map +1 -1
- package/dist/esm/requests/manual-controllers-routes-urls.d.ts.map +1 -1
- package/dist/esm/requests/manual-controllers-routes-urls.js.map +1 -1
- package/dist/esm/requests/rate-limits.shared.schemas.d.ts.map +1 -1
- package/dist/esm/requests/rate-limits.shared.schemas.js.map +1 -1
- package/dist/esm/requests/websocket.shared.schemas.d.ts +2 -2
- package/dist/esm/requests/websocket.shared.schemas.d.ts.map +1 -1
- package/dist/esm/requests/websocket.shared.schemas.js.map +1 -1
- package/dist/esm/resources/child-operations.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/child-operations.shared.schemas.js.map +1 -1
- package/dist/esm/resources/collection-query-parameters.shared.d.ts.map +1 -1
- package/dist/esm/resources/collection-query-parameters.shared.js.map +1 -1
- package/dist/esm/resources/context-policy.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/context-policy.shared.schemas.js.map +1 -1
- package/dist/esm/resources/embedded-resource-mark.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/embedded-resource-mark.shared.utils.js.map +1 -1
- package/dist/esm/resources/relationship-display.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/relationship-display.shared.schemas.js.map +1 -1
- package/dist/esm/resources/resource-status-lifecycle.example.d.ts +100 -0
- package/dist/esm/resources/resource-status-lifecycle.example.d.ts.map +1 -0
- package/dist/esm/resources/resource-status-lifecycle.example.js +156 -0
- package/dist/esm/resources/resource-status-lifecycle.example.js.map +1 -0
- package/dist/esm/resources/resources-config.shared.factory.d.ts +25 -1
- package/dist/esm/resources/resources-config.shared.factory.d.ts.map +1 -1
- package/dist/esm/resources/resources-config.shared.factory.js +31 -8
- package/dist/esm/resources/resources-config.shared.factory.js.map +1 -1
- package/dist/esm/resources/resources-config.shared.schemas.d.ts +33 -0
- package/dist/esm/resources/resources-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/resources-config.shared.schemas.js.map +1 -1
- package/dist/esm/resources/resources-registry.shared.core.definitions.d.ts.map +1 -1
- package/dist/esm/resources/resources-registry.shared.core.definitions.js.map +1 -1
- package/dist/esm/resources/resources-relationships.shared.factory.d.ts.map +1 -1
- package/dist/esm/resources/resources-relationships.shared.factory.js.map +1 -1
- package/dist/esm/resources/resources-serialization.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/resources-serialization.shared.schemas.js.map +1 -1
- package/dist/esm/resources/resources.shared.core.definitions.d.ts.map +1 -1
- package/dist/esm/resources/resources.shared.core.definitions.js.map +1 -1
- package/dist/esm/resources/resources.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/resources.shared.schemas.js.map +1 -1
- package/dist/esm/resources/resources.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/resources.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/collection-export.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/collection-export.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/composition-cascade-deletability.validation.d.ts.map +1 -1
- package/dist/esm/resources/utils/composition-cascade-deletability.validation.js.map +1 -1
- package/dist/esm/resources/utils/composition-seedability.validation.d.ts.map +1 -1
- package/dist/esm/resources/utils/composition-seedability.validation.js.map +1 -1
- package/dist/esm/resources/utils/context-addressed-composition-singleton.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/context-addressed-composition-singleton.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/dependent-lifecycle-classification.validation.d.ts.map +1 -1
- package/dist/esm/resources/utils/dependent-lifecycle-classification.validation.js.map +1 -1
- package/dist/esm/resources/utils/duplicate-relationship-registration.validation.d.ts.map +1 -1
- package/dist/esm/resources/utils/duplicate-relationship-registration.validation.js.map +1 -1
- package/dist/esm/resources/utils/field-value-disclosure.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/field-value-disclosure.utils.js.map +1 -1
- package/dist/esm/resources/utils/http-api-write-declaration.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/http-api-write-declaration.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/initiator-stamped-field-satisfiability.validation.d.ts.map +1 -1
- package/dist/esm/resources/utils/initiator-stamped-field-satisfiability.validation.js.map +1 -1
- package/dist/esm/resources/utils/no-subject-data-stance-coherence.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/no-subject-data-stance-coherence.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/persistence-adapter-discrimination.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/persistence-adapter-discrimination.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/populated-file-fields.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/populated-file-fields.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/repository-dto-builder.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/repository-dto-builder.utils.js.map +1 -1
- package/dist/esm/resources/utils/request-schema-field-carriage.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/request-schema-field-carriage.shared.utils.js.map +1 -1
- package/dist/esm/resources/utils/required-fk-fillability.validation.d.ts.map +1 -1
- package/dist/esm/resources/utils/required-fk-fillability.validation.js.map +1 -1
- package/dist/esm/resources/utils/resource-operation-type-guards.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resource-operation-type-guards.utils.js.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.factory.d.ts.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.factory.js.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.relationships.d.ts.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.relationships.js.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.schemas.d.ts.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.schemas.js.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resource-polymorphism.utils.js.map +1 -1
- package/dist/esm/resources/utils/resource-subtree.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resource-subtree.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-config-context-needs.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-config-context-needs.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-config-naming.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-config-naming.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.dtos-builder.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.dtos-builder.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.path.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.path.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.urls-builder.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.urls-builder.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-config-operations.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-serialization.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-serialization.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-summary.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-summary.utils.js.map +1 -1
- package/dist/esm/resources/utils/schema-family-builder.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/schema-family-builder.utils.js.map +1 -1
- package/dist/esm/resources/utils/schema-type-inference.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/schema-type-inference.utils.js.map +1 -1
- package/dist/esm/resources/utils/schema-type-utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/schema-type-utils.js.map +1 -1
- package/dist/esm/resources/utils/schema-variant-resolver.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/schema-variant-resolver.utils.js.map +1 -1
- package/dist/esm/resources/utils/shared-persistence-collection.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/shared-persistence-collection.utils.js.map +1 -1
- package/dist/esm/resources/utils/templatable-file-fields.shared.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/templatable-file-fields.shared.utils.js.map +1 -1
- package/dist/esm/resources/work-unit.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/work-unit.shared.schemas.js.map +1 -1
- package/dist/esm/runtime/domain-module.shared.definitions.d.ts.map +1 -1
- package/dist/esm/runtime/domain-module.shared.definitions.js.map +1 -1
- package/dist/esm/runtime/execution-context.shared.schemas.d.ts.map +1 -1
- package/dist/esm/runtime/execution-context.shared.schemas.js.map +1 -1
- package/dist/esm/runtime/runtime.shared.schemas.d.ts.map +1 -1
- package/dist/esm/runtime/runtime.shared.schemas.js.map +1 -1
- package/dist/esm/security/api-keys/api-keys-application.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/api-keys/api-keys-application.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/api-keys/api-keys-organization.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/api-keys/api-keys-organization.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/api-keys/api-keys.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/api-keys/api-keys.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/anonymous-session/anonymous-session.shared.contract.d.ts.map +1 -1
- package/dist/esm/security/authentications/anonymous-session/anonymous-session.shared.contract.js.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.dto.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.dto.schemas.js.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.utils.js.map +1 -1
- package/dist/esm/security/authentications/consumable-token.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/consumable-token.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/cross-frontend-handoff.shared.dto.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/cross-frontend-handoff.shared.dto.schemas.js.map +1 -1
- package/dist/esm/security/authentications/mfa-backup-code-contract.shared.d.ts.map +1 -1
- package/dist/esm/security/authentications/mfa-backup-code-contract.shared.js.map +1 -1
- package/dist/esm/security/authentications/password-blocklist.shared.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/password-blocklist.shared.utils.js.map +1 -1
- package/dist/esm/security/authentications/password-reset.shared.dto.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/password-reset.shared.dto.schemas.js.map +1 -1
- package/dist/esm/security/authentications/registration.shared.dto.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/registration.shared.dto.schemas.js.map +1 -1
- package/dist/esm/security/authentications/same-origin-redirect-path.shared.d.ts.map +1 -1
- package/dist/esm/security/authentications/same-origin-redirect-path.shared.js.map +1 -1
- package/dist/esm/security/authentications/scim/scim-organization-unit-mapping.shared.d.ts.map +1 -1
- package/dist/esm/security/authentications/scim/scim-organization-unit-mapping.shared.js.map +1 -1
- package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/scim/scim-tokens.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/scim/scim-tokens.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/scim/scim-tokens.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/scim/scim-tokens.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/service-provider-client-authentication.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/service-provider-client-authentication.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-dlq.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-dlq.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-dlq.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-dlq.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-outbox.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-outbox.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-outbox.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-outbox.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-reliability-contract.shared.d.ts.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-reliability-contract.shared.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-export-config.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/siem/siem-export-config.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-export-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/siem/siem-export-config.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/sso/sso-config.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/sso/sso-config.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/sso/sso-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/sso/sso-config.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/sso/sso-connection.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/sso/sso-connection.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/administrative-continuity.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authorizations/administrative-continuity.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/application-access-grants.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authorizations/application-access-grants.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/application-access-grants.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authorizations/application-access-grants.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/roles.application-roles.example.d.ts +37 -0
- package/dist/esm/security/authorizations/roles.application-roles.example.d.ts.map +1 -0
- package/dist/esm/security/authorizations/roles.application-roles.example.js +50 -0
- package/dist/esm/security/authorizations/roles.application-roles.example.js.map +1 -0
- package/dist/esm/security/authorizations/roles.shared.defaults.d.ts +13 -0
- package/dist/esm/security/authorizations/roles.shared.defaults.d.ts.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.defaults.js +13 -0
- package/dist/esm/security/authorizations/roles.shared.defaults.js.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.schemas.d.ts +29 -0
- package/dist/esm/security/authorizations/roles.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.schemas.js +28 -0
- package/dist/esm/security/authorizations/roles.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.utils.js.map +1 -1
- package/dist/esm/security/connected-accounts/provider-connection-listing.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/provider-connection-listing.shared.schemas.js.map +1 -1
- package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.js.map +1 -1
- package/dist/esm/security/credential-rotation-grace.shared.utils.d.ts.map +1 -1
- package/dist/esm/security/credential-rotation-grace.shared.utils.js.map +1 -1
- package/dist/esm/security/crypto-keys/crypto-keys.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/crypto-keys/crypto-keys.shared.schemas.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients-application.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients-application.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients-organization.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients-organization.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients.shared.schemas.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-resource-server.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-resource-server.shared.schemas.js.map +1 -1
- package/dist/esm/security/outbound-target-control.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/outbound-target-control.shared.schemas.js.map +1 -1
- package/dist/esm/security/submission-challenge/submission-challenge.shared.d.ts.map +1 -1
- package/dist/esm/security/submission-challenge/submission-challenge.shared.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-actions.shared.schemas.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-actions.shared.schemas.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-credential-kind.shared.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-credential-kind.shared.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-declaration.shared.schemas.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-declaration.shared.schemas.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-env.shared.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-env.shared.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-error-codes.shared.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-error-codes.shared.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-facet.shared.schemas.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-facet.shared.schemas.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-partition-assignments.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-partition-assignments.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-partition-assignments.shared.schemas.d.ts.map +1 -1
- package/dist/esm/systems-of-record/system-of-record-partition-assignments.shared.schemas.js.map +1 -1
- package/dist/esm/testing/resource-config-builders.d.ts.map +1 -1
- package/dist/esm/testing/resource-config-builders.js.map +1 -1
- package/dist/esm/testing.d.ts.map +1 -1
- package/dist/esm/testing.js.map +1 -1
- package/dist/esm/users/anonymous-user-marketing-metadata.shared.schemas.d.ts.map +1 -1
- package/dist/esm/users/anonymous-user-marketing-metadata.shared.schemas.js.map +1 -1
- package/dist/esm/users/anonymous-users.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/anonymous-users.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/anonymous-users.shared.schema.d.ts.map +1 -1
- package/dist/esm/users/anonymous-users.shared.schema.js.map +1 -1
- package/dist/esm/users/inbound-contacts.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/inbound-contacts.shared.resources-config.schemas.js +2 -0
- package/dist/esm/users/inbound-contacts.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/inbound-contacts.shared.schemas.d.ts.map +1 -1
- package/dist/esm/users/inbound-contacts.shared.schemas.js.map +1 -1
- package/dist/esm/users/user-consent-decision.shared.utils.d.ts.map +1 -1
- package/dist/esm/users/user-consent-decision.shared.utils.js.map +1 -1
- package/dist/esm/users/user-credentials.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-credentials.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/user-credentials.shared.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-credentials.shared.schemas.js.map +1 -1
- package/dist/esm/users/user-identity-links.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-identity-links.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/user-identity-links.shared.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-identity-links.shared.schemas.js.map +1 -1
- package/dist/esm/users/user-preferences-reset.shared.utils.d.ts.map +1 -1
- package/dist/esm/users/user-preferences-reset.shared.utils.js.map +1 -1
- package/dist/esm/users/user-preferences.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-preferences.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/user-profiles.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-profiles.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/user-self-preferences.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-self-preferences.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/user-self-profiles.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-self-profiles.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/user-self.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/user-self.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/users.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/users/users.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/users.shared.schemas.d.ts.map +1 -1
- package/dist/esm/users/users.shared.schemas.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-use-posture.shared.schemas.js","sourceRoot":"","sources":["../../../../../src/compliance/privacy/ai-use-posture.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,qCAAqC,EAAE,MAAM,2DAA2D,CAAC;AAClH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6DAA6D,CAAC;AAE/F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAN,IAAY,qBAoBX;AApBD,WAAY,qBAAqB;IAC/B;;;;;;OAMG;IACH,oDAA2B,CAAA;IAC3B;;;;;;;OAOG;IACH,0EAAiD,CAAA;IACjD,+FAA+F;IAC/F,sEAA6C,CAAA;AAC/C,CAAC,EApBW,qBAAqB,KAArB,qBAAqB,QAoBhC;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,YAAY,CAAC;IACZ,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC;IAC1C;;;;;;OAMG;IACH,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC;;;;;;;OAOG;IACH,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC;KACD,WAAW,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;IAChC,IAAI,OAAO,CAAC,WAAW,KAAK,qBAAqB,CAAC,WAAW,EAAE,CAAC;QAC9D,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YAC5C,OAAO,CAAC,QAAQ,CAAC;gBACf,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,wBAAwB,CAAC;gBAChC,OAAO,EAAE,wEAAwE;aAClF,CAAC,CAAC;QACL,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,CAAC,QAAQ,CAAC;YACf,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,wBAAwB,CAAC;YAChC,OAAO,EAAE,KAAK,OAAO,CAAC,WAAW,0EAA0E;SAC5G,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAGL;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,CAAC;AAG3G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAgC,MAAM,CAAC,MAAM,CAAC;IAC/E,gBAAgB,CAAC,MAAM;IACvB,gBAAgB,CAAC,aAAa;IAC9B,gBAAgB,CAAC,sBAAsB;IACvC,gBAAgB,CAAC,eAAe;IAChC;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,mBAAmB;CACrC,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,gDAAgD,GAAgC,MAAM,CAAC,MAAM,CACxG,sBAAsB,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,qCAAqC,CAAC,UAAU,CAAC,CAAC,CACjG,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CACzC,mBAAsC,EACtC,OAA4C;IAE5C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC7C,OAAO,gDAAgD,CAAC,MAAM,CAC5D,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC,UAAU,CAAC,KAAK,SAAS,CAC/E,CAAC;AACJ,CAAC","sourcesContent":["import { z } from \"zod\";\n\nimport { engineCapabilityReachesRuntimeService } from '../../external-providers/engine-capability-surface.shared';\nimport { EngineCapability } from \"../../external-providers/engine-capabilities.shared.schemas\";\n\n/**\n * **Whether an AI use DECIDES something about a person, and who reviews it if so.**\n *\n * ## What the capability already says, and what it cannot\n *\n * `AI_LLM`, `AI_EMBEDDINGS`, `AI_DOCUMENT_EXTRACTION` and `AI_CODING_AGENT` establish that AI is in use\n * and for what FUNCTION. They cannot establish the two things that carry legal weight (issue #92):\n * whether any of it produces a decision with a legal or similarly significant effect on a person, and\n * whether a human reviews such a decision.\n *\n * Neither is inferable from a capability being enabled — the same `AI_LLM` backs a summarisation\n * feature that decides nothing and a screening feature that decides a great deal.\n *\n * ## Why silence here is worse than silence elsewhere\n *\n * Automated decision-making with significant effects attracts specific obligations: information about\n * the logic involved, and a right to obtain human intervention. A notice that describes AI use and says\n * nothing about consequence does not read as \"unknown\" — it reads as \"nothing significant happens\n * here\", which **silently claims the exemption**. That is why the posture is declared rather than\n * defaulted, and why an undeclared capability is reported as undeclared rather than assumed harmless.\n */\nexport enum AiDecisionConsequence {\n /**\n * The AI produces no decision about a person — it summarises, drafts, classifies content, or assists\n * a task whose outcome affects nobody's rights.\n *\n * A real and common answer, and the one that must be DECLARED rather than assumed: it is exactly the\n * claim a silent notice makes for free.\n */\n NO_DECISION = \"NO_DECISION\",\n /**\n * The AI informs a decision a HUMAN takes. The human is the decision-maker and can disregard it.\n *\n * Distinct from {@link NO_DECISION} because a person is affected, and distinct from\n * {@link DECIDES_AUTONOMOUSLY} because the obligation attaches to solely-automated decisions. Where\n * the human merely rubber-stamps, this is the wrong answer — the review must be capable of changing\n * the outcome.\n */\n ASSISTS_HUMAN_DECISION = \"ASSISTS_HUMAN_DECISION\",\n /** The AI's output IS the decision, with no human able to change it before it takes effect. */\n DECIDES_AUTONOMOUSLY = \"DECIDES_AUTONOMOUSLY\",\n}\n\n/** One AI capability's declared posture. */\nexport const AiUsePostureSchema = z\n .strictObject({\n consequence: z.enum(AiDecisionConsequence),\n /**\n * What the AI is used FOR, in the operator's words.\n *\n * Required, and it is what makes the posture checkable: \"summarising a contact's interaction\n * history\" and \"scoring a lead's creditworthiness\" are the same capability and different postures,\n * so a consequence with no stated use cannot be reviewed by anyone.\n */\n purpose: z.string().trim().min(1),\n /**\n * How a person obtains human intervention — REQUIRED unless the posture is\n * {@link AiDecisionConsequence.NO_DECISION}.\n *\n * The pairing is enforced below rather than left to a reviewer: an application declaring that AI\n * decides something about a person, and saying nothing about review, has described the obligation\n * without answering it.\n */\n humanReviewArrangement: z.string().trim().min(1).nullable(),\n })\n .superRefine((posture, context) => {\n if (posture.consequence === AiDecisionConsequence.NO_DECISION) {\n if (posture.humanReviewArrangement !== null) {\n context.addIssue({\n code: \"custom\",\n path: [\"humanReviewArrangement\"],\n message: \"a use that decides nothing has no human-review arrangement to describe\",\n });\n }\n return;\n }\n if (posture.humanReviewArrangement === null) {\n context.addIssue({\n code: \"custom\",\n path: [\"humanReviewArrangement\"],\n message: `a ${posture.consequence} use affects a person, so it must say how human intervention is obtained`,\n });\n }\n });\nexport type AiUsePosture = z.infer<typeof AiUsePostureSchema>;\n\n/**\n * The application's declared AI postures, keyed by the capability they describe.\n *\n * Keyed by CAPABILITY rather than by feature, deliberately. The issue suggested \"an AI use\", and a\n * feature-level posture is more precise — and it is a granularity nobody maintains, the same trade\n * that settled the retention schedule and the processor register. A capability is the unit the\n * application already declares, there are at most four, and an operator whose single `AI_LLM` capability\n * backs two features with different consequences declares the STRONGER one, which is the safe direction.\n */\nexport const ApplicationAiUsePostureSchema = z.partialRecord(z.enum(EngineCapability), AiUsePostureSchema);\nexport type ApplicationAiUsePosture = z.infer<typeof ApplicationAiUsePostureSchema>;\n\n/**\n * The AI capabilities a document must ask about.\n *\n * Named here rather than derived from a prefix: `AI_` is a spelling, and a capability added tomorrow\n * whose name happens to start with it would silently join the set — while one that processes personal\n * data under a different name would silently stay out.\n */\nexport const AI_ENGINE_CAPABILITIES: readonly EngineCapability[] = Object.freeze([\n EngineCapability.AI_LLM,\n EngineCapability.AI_EMBEDDINGS,\n EngineCapability.AI_DOCUMENT_EXTRACTION,\n EngineCapability.AI_CODING_AGENT,\n /*\n * ADDED 2026-09-12, and its absence was a hole rather than a judgement.\n *\n * Generating an image from a person's prompt, or from their content, is AI processing by any\n * reading a notice has to survive — and because this list is what a document ASKS about, omitting\n * it meant an application offering image generation to its users was asked NOTHING about AI. The\n * omission was silent in the direction that matters: the notice reads complete.\n *\n * It was noticed while adding the surface axis and deliberately not slipped into that change,\n * because widening this vocabulary changes what an application must declare. Measured before\n * landing: Wonder Todos enables the capability and its only provider offering it sits in the\n * COMPANION scope (the brand/logo generator), so the scope resolution keeps it outside the\n * contracted service and its notice is unchanged. An application that binds an image provider to\n * a RUNTIME scope is now asked for a posture, which is the whole point.\n */\n EngineCapability.AI_IMAGE_GENERATION,\n]);\n\n/**\n * The AI capabilities a document about the CONTRACTED SERVICE must ask about.\n *\n * The set above, minus the capabilities that never run while the application serves a user. This is\n * the set a privacy notice, a record of processing and an Article 22 automated-decision statement\n * are about, and the distinction is not cosmetic: `AI_CODING_AGENT` is a build-time tool that writes\n * the application's SOURCE. It decides nothing about a data subject and processes none of their\n * data, so asking an operator to declare its \"posture\" toward people, or listing it as OUTSTANDING\n * in a notice, invents an AI question the service does not raise.\n *\n * That is not hypothetical. Wonder CRM enables `AI_CODING_AGENT` and no other AI capability. Under\n * the unfiltered set the drafter is pushed into the per-capability AI branch — the branch that asks\n * \"whether it DECIDES something about a person\" — for an application whose contracted service\n * performs no AI at all, and whose own declared fact says exactly that.\n *\n * DERIVED rather than listed, and total over the set above, so an AI capability added tomorrow lands\n * on the right side of this line by its DECLARED SURFACE rather than by anyone remembering to add it\n * here. The surface map is itself exhaustive over `EngineCapability`, so there is no default to fall\n * through.\n */\nexport const AI_ENGINE_CAPABILITIES_IN_THE_CONTRACTED_SERVICE: readonly EngineCapability[] = Object.freeze(\n AI_ENGINE_CAPABILITIES.filter((capability) => engineCapabilityReachesRuntimeService(capability)),\n);\n\n/**\n * Enabled AI capabilities with no declared posture — what a document must report as outstanding.\n *\n * assurance-control: WILDO.AI.THIRD_PARTY_COMPONENTS — an enabled AI capability with no declared use is named, never assumed harmless.\n *\n * Takes the ENABLED set as an argument: a capability the application has not enabled raises no\n * question, and reporting it would fill a notice with AI the application does not use.\n */\nexport function undeclaredAiUseCapabilities(\n enabledCapabilities: readonly string[],\n posture: ApplicationAiUsePosture | undefined,\n): readonly EngineCapability[] {\n const enabled = new Set(enabledCapabilities);\n return AI_ENGINE_CAPABILITIES_IN_THE_CONTRACTED_SERVICE.filter(\n (capability) => enabled.has(capability) && posture?.[capability] === undefined,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ai-use-posture.shared.schemas.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/ai-use-posture.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,qCAAqC,EAAE,MAAM,2DAA2D,CAAC;AAClH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6DAA6D,CAAC;AAE/F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAN,IAAY,qBAoBX;AApBD,WAAY,qBAAqB;IAC/B;;;;;;OAMG;IACH,oDAA2B,CAAA;IAC3B;;;;;;;OAOG;IACH,0EAAiD,CAAA;IACjD,+FAA+F;IAC/F,sEAA6C,CAAA;AAC/C,CAAC,EApBW,qBAAqB,KAArB,qBAAqB,QAoBhC;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,YAAY,CAAC;IACZ,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC;IAC1C;;;;;;OAMG;IACH,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC;;;;;;;OAOG;IACH,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC;KACD,WAAW,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;IAChC,IAAI,OAAO,CAAC,WAAW,KAAK,qBAAqB,CAAC,WAAW,EAAE,CAAC;QAC9D,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;YAC5C,OAAO,CAAC,QAAQ,CAAC;gBACf,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,wBAAwB,CAAC;gBAChC,OAAO,EAAE,wEAAwE;aAClF,CAAC,CAAC;QACL,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,CAAC,QAAQ,CAAC;YACf,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,wBAAwB,CAAC;YAChC,OAAO,EAAE,KAAK,OAAO,CAAC,WAAW,0EAA0E;SAC5G,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAGL;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,CAAC;AAG3G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAgC,MAAM,CAAC,MAAM,CAAC;IAC/E,gBAAgB,CAAC,MAAM;IACvB,gBAAgB,CAAC,aAAa;IAC9B,gBAAgB,CAAC,sBAAsB;IACvC,gBAAgB,CAAC,eAAe;IAChC;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,mBAAmB;CACrC,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,gDAAgD,GAAgC,MAAM,CAAC,MAAM,CACxG,sBAAsB,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,qCAAqC,CAAC,UAAU,CAAC,CAAC,CACjG,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CACzC,mBAAsC,EACtC,OAA4C;IAE5C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC7C,OAAO,gDAAgD,CAAC,MAAM,CAC5D,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC,UAAU,CAAC,KAAK,SAAS,CAC/E,CAAC;AACJ,CAAC","sourcesContent":["import { z } from \"zod\";\n\nimport { engineCapabilityReachesRuntimeService } from '../../external-providers/engine-capability-surface.shared';\nimport { EngineCapability } from \"../../external-providers/engine-capabilities.shared.schemas\";\n\n/**\n * **Whether an AI use DECIDES something about a person, and who reviews it if so.**\n *\n * ## What the capability already says, and what it cannot\n *\n * `AI_LLM`, `AI_EMBEDDINGS`, `AI_DOCUMENT_EXTRACTION` and `AI_CODING_AGENT` establish that AI is in use\n * and for what FUNCTION. They cannot establish the two things that carry legal weight (issue #92):\n * whether any of it produces a decision with a legal or similarly significant effect on a person, and\n * whether a human reviews such a decision.\n *\n * Neither is inferable from a capability being enabled — the same `AI_LLM` backs a summarisation\n * feature that decides nothing and a screening feature that decides a great deal.\n *\n * ## Why silence here is worse than silence elsewhere\n *\n * Automated decision-making with significant effects attracts specific obligations: information about\n * the logic involved, and a right to obtain human intervention. A notice that describes AI use and says\n * nothing about consequence does not read as \"unknown\" — it reads as \"nothing significant happens\n * here\", which **silently claims the exemption**. That is why the posture is declared rather than\n * defaulted, and why an undeclared capability is reported as undeclared rather than assumed harmless.\n */\nexport enum AiDecisionConsequence {\n /**\n * The AI produces no decision about a person — it summarises, drafts, classifies content, or assists\n * a task whose outcome affects nobody's rights.\n *\n * A real and common answer, and the one that must be DECLARED rather than assumed: it is exactly the\n * claim a silent notice makes for free.\n */\n NO_DECISION = \"NO_DECISION\",\n /**\n * The AI informs a decision a HUMAN takes. The human is the decision-maker and can disregard it.\n *\n * Distinct from {@link NO_DECISION} because a person is affected, and distinct from\n * {@link DECIDES_AUTONOMOUSLY} because the obligation attaches to solely-automated decisions. Where\n * the human merely rubber-stamps, this is the wrong answer — the review must be capable of changing\n * the outcome.\n */\n ASSISTS_HUMAN_DECISION = \"ASSISTS_HUMAN_DECISION\",\n /** The AI's output IS the decision, with no human able to change it before it takes effect. */\n DECIDES_AUTONOMOUSLY = \"DECIDES_AUTONOMOUSLY\",\n}\n\n/** One AI capability's declared posture. */\nexport const AiUsePostureSchema = z\n .strictObject({\n consequence: z.enum(AiDecisionConsequence),\n /**\n * What the AI is used FOR, in the operator's words.\n *\n * Required, and it is what makes the posture checkable: \"summarising a contact's interaction\n * history\" and \"scoring a lead's creditworthiness\" are the same capability and different postures,\n * so a consequence with no stated use cannot be reviewed by anyone.\n */\n purpose: z.string().trim().min(1),\n /**\n * How a person obtains human intervention — REQUIRED unless the posture is\n * {@link AiDecisionConsequence.NO_DECISION}.\n *\n * The pairing is enforced below rather than left to a reviewer: an application declaring that AI\n * decides something about a person, and saying nothing about review, has described the obligation\n * without answering it.\n */\n humanReviewArrangement: z.string().trim().min(1).nullable(),\n })\n .superRefine((posture, context) => {\n if (posture.consequence === AiDecisionConsequence.NO_DECISION) {\n if (posture.humanReviewArrangement !== null) {\n context.addIssue({\n code: \"custom\",\n path: [\"humanReviewArrangement\"],\n message: \"a use that decides nothing has no human-review arrangement to describe\",\n });\n }\n return;\n }\n if (posture.humanReviewArrangement === null) {\n context.addIssue({\n code: \"custom\",\n path: [\"humanReviewArrangement\"],\n message: `a ${posture.consequence} use affects a person, so it must say how human intervention is obtained`,\n });\n }\n });\nexport type AiUsePosture = z.infer<typeof AiUsePostureSchema>;\n\n/**\n * The application's declared AI postures, keyed by the capability they describe.\n *\n * Keyed by CAPABILITY rather than by feature, deliberately. The issue suggested \"an AI use\", and a\n * feature-level posture is more precise — and it is a granularity nobody maintains, the same trade\n * that settled the retention schedule and the processor register. A capability is the unit the\n * application already declares, there are at most four, and an operator whose single `AI_LLM` capability\n * backs two features with different consequences declares the STRONGER one, which is the safe direction.\n */\nexport const ApplicationAiUsePostureSchema = z.partialRecord(z.enum(EngineCapability), AiUsePostureSchema);\nexport type ApplicationAiUsePosture = z.infer<typeof ApplicationAiUsePostureSchema>;\n\n/**\n * The AI capabilities a document must ask about.\n *\n * Named here rather than derived from a prefix: `AI_` is a spelling, and a capability added tomorrow\n * whose name happens to start with it would silently join the set — while one that processes personal\n * data under a different name would silently stay out.\n */\nexport const AI_ENGINE_CAPABILITIES: readonly EngineCapability[] = Object.freeze([\n EngineCapability.AI_LLM,\n EngineCapability.AI_EMBEDDINGS,\n EngineCapability.AI_DOCUMENT_EXTRACTION,\n EngineCapability.AI_CODING_AGENT,\n /*\n * ADDED 2026-09-12, and its absence was a hole rather than a judgement.\n *\n * Generating an image from a person's prompt, or from their content, is AI processing by any\n * reading a notice has to survive — and because this list is what a document ASKS about, omitting\n * it meant an application offering image generation to its users was asked NOTHING about AI. The\n * omission was silent in the direction that matters: the notice reads complete.\n *\n * It was noticed while adding the surface axis and deliberately not slipped into that change,\n * because widening this vocabulary changes what an application must declare. Measured before\n * landing: Wonder Todos enables the capability and its only provider offering it sits in the\n * COMPANION scope (the brand/logo generator), so the scope resolution keeps it outside the\n * contracted service and its notice is unchanged. An application that binds an image provider to\n * a RUNTIME scope is now asked for a posture, which is the whole point.\n */\n EngineCapability.AI_IMAGE_GENERATION,\n]);\n\n/**\n * The AI capabilities a document about the CONTRACTED SERVICE must ask about.\n *\n * The set above, minus the capabilities that never run while the application serves a user. This is\n * the set a privacy notice, a record of processing and an Article 22 automated-decision statement\n * are about, and the distinction is not cosmetic: `AI_CODING_AGENT` is a build-time tool that writes\n * the application's SOURCE. It decides nothing about a data subject and processes none of their\n * data, so asking an operator to declare its \"posture\" toward people, or listing it as OUTSTANDING\n * in a notice, invents an AI question the service does not raise.\n *\n * That is not hypothetical. Wonder CRM enables `AI_CODING_AGENT` and no other AI capability. Under\n * the unfiltered set the drafter is pushed into the per-capability AI branch — the branch that asks\n * \"whether it DECIDES something about a person\" — for an application whose contracted service\n * performs no AI at all, and whose own declared fact says exactly that.\n *\n * DERIVED rather than listed, and total over the set above, so an AI capability added tomorrow lands\n * on the right side of this line by its DECLARED SURFACE rather than by anyone remembering to add it\n * here. The surface map is itself exhaustive over `EngineCapability`, so there is no default to fall\n * through.\n */\nexport const AI_ENGINE_CAPABILITIES_IN_THE_CONTRACTED_SERVICE: readonly EngineCapability[] = Object.freeze(\n AI_ENGINE_CAPABILITIES.filter((capability) => engineCapabilityReachesRuntimeService(capability)),\n);\n\n/**\n * Enabled AI capabilities with no declared posture — what a document must report as outstanding.\n *\n * assurance-control: WILDO.AI.THIRD_PARTY_COMPONENTS — an enabled AI capability with no declared use is named, never assumed harmless.\n *\n * Takes the ENABLED set as an argument: a capability the application has not enabled raises no\n * question, and reporting it would fill a notice with AI the application does not use.\n */\nexport function undeclaredAiUseCapabilities(\n enabledCapabilities: readonly string[],\n posture: ApplicationAiUsePosture | undefined,\n): readonly EngineCapability[] {\n const enabled = new Set(enabledCapabilities);\n return AI_ENGINE_CAPABILITIES_IN_THE_CONTRACTED_SERVICE.filter(\n (capability) => enabled.has(capability) && posture?.[capability] === undefined,\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-consent-purposes.shared.utils.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"capability-consent-purposes.shared.utils.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/capability-consent-purposes.shared.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,uCAAuC,EAAE,MAAM,0CAA0C,CAAC;AAExG;;;;;;GAMG;AACH,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,uCAAuC,CAAA;KAAE,EAAE,CAAC;CACpG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wCAAwC,CACtD,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC,GAC7E,cAAc,EAAE,CASlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-consent-purposes.shared.utils.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"capability-consent-purposes.shared.utils.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/capability-consent-purposes.shared.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAkB,MAAM,2BAA2B,CAAC;AAc7E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,wCAAwC,CACtD,sBAA8E;IAE9E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,aAAa,IAAI,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,EAAE,CAAC;QAClE,KAAK,MAAM,SAAS,IAAI,aAAa,CAAC,UAAU,EAAE,CAAC;YACjD,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC;YAC/C,IAAI,OAAO,KAAK,SAAS;gBAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACrE,CAAC","sourcesContent":["import { CONSENT_PURPOSES, ConsentPurpose } from './consent-purposes.shared';\nimport type { ResourceOperationConsentGateDeclaration } from './consent-gate-vocabulary.shared.schemas';\n\n/**\n * The narrow slice of a resolved resource configuration this derivation reads: every operation, each\n * possibly carrying a `consentGate`. Structural, so `ResourcesRegistry['resourceConfigurations']`\n * values satisfy it without a cast at the call site — the operation record is a discriminated union\n * with no shared `consentGate` member (mirroring how `assertServiceConsentRequirementMet` reads the\n * same field off `executionContext.operation`), so each element is narrowed the same way here.\n */\nexport interface CapabilityConsentGateSubject {\n readonly operations: readonly { readonly consentGate?: ResourceOperationConsentGateDeclaration }[];\n}\n\n/**\n * Every `ConsentPurpose` declared by at least one operation across every resource in the registry\n * (#1462, following #1258 Step 3).\n *\n * Total over the REGISTRY, not over one application's own resources: an engine capability could\n * declare a `consentGate` as validly as an app-authored one, and the person facing a refusal from\n * either needs the same PROMPT surface to grant it from — there is no reader this derivation exists\n * to protect from engine noise the way `collectApplicationResourcesWithNoPersonalDataDeclaration`\n * protects a startup log from ~85 engine resources that never answer a question nobody asked them.\n * This is a SET, not a per-resource report: only the union of what was declared is useful downstream.\n *\n * Pure and import-light on purpose, mirroring `applicationAskedConsentPurposes` in the same\n * directory: the one call site that matters (`ResourcesRegistryBackendService.initialize()`) hands\n * this the live registry and the result travels onward as plain data\n * (`compliance.capabilityDeclaredConsentPurposes`), never as a reason to import registry types where\n * they do not otherwise belong.\n */\nexport function collectCapabilityDeclaredConsentPurposes(\n resourceConfigurations: Readonly<Record<string, CapabilityConsentGateSubject>>,\n): ConsentPurpose[] {\n const declared = new Set<ConsentPurpose>();\n for (const configuration of Object.values(resourceConfigurations)) {\n for (const operation of configuration.operations) {\n const purpose = operation.consentGate?.purpose;\n if (purpose !== undefined) declared.add(purpose);\n }\n }\n return CONSENT_PURPOSES.filter((purpose) => declared.has(purpose));\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-storage.shared.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"client-storage.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/client-storage.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,sHAAsH;AACtH,oBAAY,sBAAsB;IAChC,MAAM,WAAW;IACjB,aAAa,kBAAkB;IAC/B,eAAe,oBAAoB;CACpC;AAED;;;;;;GAMG;AACH,oBAAY,sBAAsB;IAChC,sGAAsG;IACtG,kBAAkB,uBAAuB;IACzC,qGAAqG;IACrG,aAAa,kBAAkB;CAChC;AAED,qEAAqE;AACrE,eAAO,MAAM,wBAAwB;IACnC,kGAAkG;;;IAGlG,mGAAmG;;;IAGnG;;;;;;;OAOG;;IAEH;;;;;;OAMG;;kBAEH,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,6BAA6B,EAAE,SAAS,kBAAkB,EAyBrE,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,uCAAuC;IA5ElD,kGAAkG;;;IAGlG,mGAAmG;;;IAGnG;;;;;;;OAOG;;IAEH;;;;;;OAMG;;oBA0DJ,CAAC;AACF,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uCAAuC,CAAC,CAAC;AAExG;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,SAAS,EAAE,iCAAiC,GAAG,SAAS,GACvD,SAAS,MAAM,EAAE,CAEnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-storage.shared.schemas.js","sourceRoot":"","sources":["../../../../../src/compliance/privacy/client-storage.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { WEBSITE_VISITOR_CONSENT_STORAGE_KEY } from \"./consent-purposes.shared\";\n\n/**\n * **What the application stores in a visitor's browser, and what gates it.**\n *\n * ## What a cookie notice actually is\n *\n * An itemised table: which cookies and client-side storage keys are set, what each is for, how long it\n * persists, and which are strictly necessary versus consent-gated. Nothing in the framework declared\n * any of it (issue #91).\n *\n * The consent POSTURE was already real and enforced — `consentedPurposes` plus the capability\n * flags make `ConsentPurpose.ANALYTICS` a boundary the runtime honours rather than a stated intention, which is a\n * stronger position than most cookie notices, which describe consent they do not enforce. What could\n * not be produced was the table.\n *\n * ## The engine sets cookies of its own, and that is why this has an ORIGIN split\n *\n * Every generated application sets at least one cookie it never declared, because the framework sets\n * it: {@link ENGINE_CLIENT_STORAGE_ENTRIES}. Asking only the application would produce a cookie table\n * that omits the session cookie — the same shape as the engine-versus-application finding in the\n * resource declarations, and the same remedy: report the two origins separately, and let the framework\n * answer for its own.\n *\n * ## Lifetimes the framework will not invent\n *\n * The engine's cookies take their `maxAge` from the application's session configuration, so the\n * framework declares the NAME, the purpose and the necessity, and describes the lifetime by where it\n * comes from. A fixed number here would be a published commitment nothing enforces — the same rule\n * that governs the retention schedule.\n */\n\n/** Where a value is stored in the browser. Cookies and web storage carry different expectations and different law. */\nexport enum ClientStorageMechanism {\n COOKIE = \"COOKIE\",\n LOCAL_STORAGE = \"LOCAL_STORAGE\",\n SESSION_STORAGE = \"SESSION_STORAGE\",\n}\n\n/**\n * Whether the entry may be set before consent.\n *\n * The distinction a cookie banner exists to implement, and the one a notice is read for. Two values on\n * purpose: an entry is either required for a service the visitor asked for, or it is not and needs\n * consent. A middle category would be a place to put everything nobody wanted to decide.\n */\nexport enum ClientStorageNecessity {\n /** Required to deliver a service the visitor explicitly requested — signing in, keeping a session. */\n STRICTLY_NECESSARY = \"STRICTLY_NECESSARY\",\n /** Set only after the visitor consents. Analytics, personalisation, anything measuring behaviour. */\n CONSENT_GATED = \"CONSENT_GATED\",\n}\n\n/** One cookie or storage key, as a notice's table would print it. */\nexport const ClientStorageEntrySchema = z.strictObject({\n /** The exact key or cookie name a visitor would see in their browser. Not a description of it. */\n name: z.string().trim().min(1),\n mechanism: z.enum(ClientStorageMechanism),\n /** What it is FOR, in a sentence a visitor can read. \"Session management\", not \"auth token v2\". */\n purpose: z.string().trim().min(1),\n necessity: z.enum(ClientStorageNecessity),\n /**\n * How long it persists, as a notice would state it — \"the browser session\", \"30 days\", or where the\n * value comes from when the application configures it.\n *\n * Free text rather than a duration, because the honest answer is often a reference rather than a\n * number, and a number the application does not actually enforce is worse than a description of the\n * mechanism that does.\n */\n lifetime: z.string().trim().min(1),\n /**\n * WHEN it is set, for an entry that is not set on every visit — `null` when it always is.\n *\n * Required-and-nullable rather than optional: \"set on every visit\" and \"nobody recorded when\" are\n * different answers, and a cookie table that implies the first while meaning the second overstates\n * what a visitor's browser holds.\n */\n setWhen: z.string().trim().min(1).nullable(),\n});\nexport type ClientStorageEntry = z.infer<typeof ClientStorageEntrySchema>;\n\n/**\n * The client storage the FRAMEWORK sets, which no application authored and every application inherits.\n *\n * All are `STRICTLY_NECESSARY`. The two cookies carry session state for a service the visitor asked for\n * and are `httpOnly`, so no script can read them. The website consent record (#534) is web storage and\n * is necessary for a different reason: remembering a refusal is what makes the refusal hold, and a\n * consent record that itself needed consent could never be kept.\n *\n * Their lifetimes are the application's to configure, so they are described by their SOURCE. Their\n * `setWhen` is stated because neither is unconditional: an application whose visitors never sign in\n * sets no refresh cookie, and one that does not use anonymous sessions sets no anonymous cookie. A\n * table claiming both are always present would overstate what a visitor's browser holds.\n */\nexport const ENGINE_CLIENT_STORAGE_ENTRIES: readonly ClientStorageEntry[] = Object.freeze([\n Object.freeze({\n name: \"__wildo_refresh\",\n mechanism: ClientStorageMechanism.COOKIE,\n purpose: \"Keeps a signed-in session alive so a visitor is not asked to authenticate on every request.\",\n necessity: ClientStorageNecessity.STRICTLY_NECESSARY,\n lifetime: \"The application's configured refresh-token expiry.\",\n setWhen: \"Set when a visitor signs in, and cleared when they sign out.\",\n }),\n Object.freeze({\n name: \"__wildo_anon_session\",\n mechanism: ClientStorageMechanism.COOKIE,\n purpose: \"Gives a visitor who has not signed in a continuous session, so work in progress survives a page load.\",\n necessity: ClientStorageNecessity.STRICTLY_NECESSARY,\n lifetime: \"The application's configured anonymous-session lifetime.\",\n setWhen: \"Set only where the application admits anonymous visitors.\",\n }),\n Object.freeze({\n name: WEBSITE_VISITOR_CONSENT_STORAGE_KEY,\n mechanism: ClientStorageMechanism.LOCAL_STORAGE,\n purpose: \"Remembers which optional purposes a website visitor agreed to, so they are not asked on every page and nothing optional starts without it.\",\n necessity: ClientStorageNecessity.STRICTLY_NECESSARY,\n lifetime: \"Until the visitor changes their choice or clears the site's storage.\",\n setWhen: \"Set on the marketing website when a visitor makes a consent choice, and only where the site runs a consent-based provider.\",\n }),\n]);\n\n/**\n * The application's own client storage, per FRONTEND SURFACE.\n *\n * Per surface rather than application-wide, and that is the issue's own point: a public marketing site\n * and the authenticated application set different things, and one merged list would be wrong for both —\n * it would show a visitor to the marketing site cookies only the app sets.\n *\n * Partial: a surface with no entry has not been inventoried, which the derivation reports. An empty\n * ARRAY is the different, positive answer — this surface sets nothing of its own beyond the engine's.\n */\nexport const ApplicationClientStorageInventorySchema = z.record(\n z.string().trim().min(1),\n z.array(ClientStorageEntrySchema),\n);\nexport type ApplicationClientStorageInventory = z.infer<typeof ApplicationClientStorageInventorySchema>;\n\n/**\n * Frontend surfaces with no inventory at all — the gap, per surface.\n *\n * Takes the surface list as an argument so the same function serves the companion (which reads the\n * declared services) and a test. Order follows the surfaces given, so the answer reads like the\n * application it describes.\n */\nexport function uninventoriedClientStorageSurfaces(\n frontendSurfaceKeys: readonly string[],\n inventory: ApplicationClientStorageInventory | undefined,\n): readonly string[] {\n return frontendSurfaceKeys.filter((surfaceKey) => inventory?.[surfaceKey] === undefined);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client-storage.shared.schemas.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/client-storage.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { WEBSITE_VISITOR_CONSENT_STORAGE_KEY } from \"./consent-purposes.shared\";\n\n/**\n * **What the application stores in a visitor's browser, and what gates it.**\n *\n * ## What a cookie notice actually is\n *\n * An itemised table: which cookies and client-side storage keys are set, what each is for, how long it\n * persists, and which are strictly necessary versus consent-gated. Nothing in the framework declared\n * any of it (issue #91).\n *\n * The consent POSTURE was already real and enforced — `consentedPurposes` plus the capability\n * flags make `ConsentPurpose.ANALYTICS` a boundary the runtime honours rather than a stated intention, which is a\n * stronger position than most cookie notices, which describe consent they do not enforce. What could\n * not be produced was the table.\n *\n * ## The engine sets cookies of its own, and that is why this has an ORIGIN split\n *\n * Every generated application sets at least one cookie it never declared, because the framework sets\n * it: {@link ENGINE_CLIENT_STORAGE_ENTRIES}. Asking only the application would produce a cookie table\n * that omits the session cookie — the same shape as the engine-versus-application finding in the\n * resource declarations, and the same remedy: report the two origins separately, and let the framework\n * answer for its own.\n *\n * ## Lifetimes the framework will not invent\n *\n * The engine's cookies take their `maxAge` from the application's session configuration, so the\n * framework declares the NAME, the purpose and the necessity, and describes the lifetime by where it\n * comes from. A fixed number here would be a published commitment nothing enforces — the same rule\n * that governs the retention schedule.\n */\n\n/** Where a value is stored in the browser. Cookies and web storage carry different expectations and different law. */\nexport enum ClientStorageMechanism {\n COOKIE = \"COOKIE\",\n LOCAL_STORAGE = \"LOCAL_STORAGE\",\n SESSION_STORAGE = \"SESSION_STORAGE\",\n}\n\n/**\n * Whether the entry may be set before consent.\n *\n * The distinction a cookie banner exists to implement, and the one a notice is read for. Two values on\n * purpose: an entry is either required for a service the visitor asked for, or it is not and needs\n * consent. A middle category would be a place to put everything nobody wanted to decide.\n */\nexport enum ClientStorageNecessity {\n /** Required to deliver a service the visitor explicitly requested — signing in, keeping a session. */\n STRICTLY_NECESSARY = \"STRICTLY_NECESSARY\",\n /** Set only after the visitor consents. Analytics, personalisation, anything measuring behaviour. */\n CONSENT_GATED = \"CONSENT_GATED\",\n}\n\n/** One cookie or storage key, as a notice's table would print it. */\nexport const ClientStorageEntrySchema = z.strictObject({\n /** The exact key or cookie name a visitor would see in their browser. Not a description of it. */\n name: z.string().trim().min(1),\n mechanism: z.enum(ClientStorageMechanism),\n /** What it is FOR, in a sentence a visitor can read. \"Session management\", not \"auth token v2\". */\n purpose: z.string().trim().min(1),\n necessity: z.enum(ClientStorageNecessity),\n /**\n * How long it persists, as a notice would state it — \"the browser session\", \"30 days\", or where the\n * value comes from when the application configures it.\n *\n * Free text rather than a duration, because the honest answer is often a reference rather than a\n * number, and a number the application does not actually enforce is worse than a description of the\n * mechanism that does.\n */\n lifetime: z.string().trim().min(1),\n /**\n * WHEN it is set, for an entry that is not set on every visit — `null` when it always is.\n *\n * Required-and-nullable rather than optional: \"set on every visit\" and \"nobody recorded when\" are\n * different answers, and a cookie table that implies the first while meaning the second overstates\n * what a visitor's browser holds.\n */\n setWhen: z.string().trim().min(1).nullable(),\n});\nexport type ClientStorageEntry = z.infer<typeof ClientStorageEntrySchema>;\n\n/**\n * The client storage the FRAMEWORK sets, which no application authored and every application inherits.\n *\n * All are `STRICTLY_NECESSARY`. The two cookies carry session state for a service the visitor asked for\n * and are `httpOnly`, so no script can read them. The website consent record (#534) is web storage and\n * is necessary for a different reason: remembering a refusal is what makes the refusal hold, and a\n * consent record that itself needed consent could never be kept.\n *\n * Their lifetimes are the application's to configure, so they are described by their SOURCE. Their\n * `setWhen` is stated because neither is unconditional: an application whose visitors never sign in\n * sets no refresh cookie, and one that does not use anonymous sessions sets no anonymous cookie. A\n * table claiming both are always present would overstate what a visitor's browser holds.\n */\nexport const ENGINE_CLIENT_STORAGE_ENTRIES: readonly ClientStorageEntry[] = Object.freeze([\n Object.freeze({\n name: \"__wildo_refresh\",\n mechanism: ClientStorageMechanism.COOKIE,\n purpose: \"Keeps a signed-in session alive so a visitor is not asked to authenticate on every request.\",\n necessity: ClientStorageNecessity.STRICTLY_NECESSARY,\n lifetime: \"The application's configured refresh-token expiry.\",\n setWhen: \"Set when a visitor signs in, and cleared when they sign out.\",\n }),\n Object.freeze({\n name: \"__wildo_anon_session\",\n mechanism: ClientStorageMechanism.COOKIE,\n purpose: \"Gives a visitor who has not signed in a continuous session, so work in progress survives a page load.\",\n necessity: ClientStorageNecessity.STRICTLY_NECESSARY,\n lifetime: \"The application's configured anonymous-session lifetime.\",\n setWhen: \"Set only where the application admits anonymous visitors.\",\n }),\n Object.freeze({\n name: WEBSITE_VISITOR_CONSENT_STORAGE_KEY,\n mechanism: ClientStorageMechanism.LOCAL_STORAGE,\n purpose: \"Remembers which optional purposes a website visitor agreed to, so they are not asked on every page and nothing optional starts without it.\",\n necessity: ClientStorageNecessity.STRICTLY_NECESSARY,\n lifetime: \"Until the visitor changes their choice or clears the site's storage.\",\n setWhen: \"Set on the marketing website when a visitor makes a consent choice, and only where the site runs a consent-based provider.\",\n }),\n]);\n\n/**\n * The application's own client storage, per FRONTEND SURFACE.\n *\n * Per surface rather than application-wide, and that is the issue's own point: a public marketing site\n * and the authenticated application set different things, and one merged list would be wrong for both —\n * it would show a visitor to the marketing site cookies only the app sets.\n *\n * Partial: a surface with no entry has not been inventoried, which the derivation reports. An empty\n * ARRAY is the different, positive answer — this surface sets nothing of its own beyond the engine's.\n */\nexport const ApplicationClientStorageInventorySchema = z.record(\n z.string().trim().min(1),\n z.array(ClientStorageEntrySchema),\n);\nexport type ApplicationClientStorageInventory = z.infer<typeof ApplicationClientStorageInventorySchema>;\n\n/**\n * Frontend surfaces with no inventory at all — the gap, per surface.\n *\n * Takes the surface list as an argument so the same function serves the companion (which reads the\n * declared services) and a test. Order follows the surfaces given, so the answer reads like the\n * application it describes.\n */\nexport function uninventoriedClientStorageSurfaces(\n frontendSurfaceKeys: readonly string[],\n inventory: ApplicationClientStorageInventory | undefined,\n): readonly string[] {\n return frontendSurfaceKeys.filter((surfaceKey) => inventory?.[surfaceKey] === undefined);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-gate-vocabulary.shared.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"consent-gate-vocabulary.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/consent-gate-vocabulary.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,oBAAY,iBAAiB;IAC3B,kIAAkI;IAClI,OAAO,YAAY;IACnB,sFAAsF;IACtF,MAAM,WAAW;IACjB,+JAA+J;IAC/J,aAAa,iBAAiB;IAC9B,wHAAwH;IACxH,MAAM,UAAU;IAChB,wKAAwK;IACxK,SAAS,aAAa;IACtB,sKAAsK;IACtK,MAAM,WAAW;CAClB;AAED;;;;;;;GAOG;AACH,oBAAY,kBAAkB;IAC5B,qHAAqH;IACrH,MAAM,WAAW;IACjB;;;;OAIG;IACH,mBAAmB,uBAAuB;IAC1C;;;;;;OAMG;IACH,gBAAgB,oBAAoB;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kCAAkC,2BAA2B,CAAC;AAC3E,eAAO,MAAM,mCAAmC,sCAAsC,CAAC;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,uCAAuC;IACtD,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,mGAAmG;IACnG,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IACpF,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CACrC;AAED,0GAA0G;AAC1G,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;CACtC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,QAAQ,CAAC,WAAW,EAAE,uCAAuC,GAAG,SAAS,CAAC;IAC1E,QAAQ,CAAC,uBAAuB,EAAE,SAAS,cAAc,EAAE,CAAC;CAC7D,GAAG,yBAAyB,GAAG,SAAS,CAMxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-gate-vocabulary.shared.schemas.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"consent-gate-vocabulary.shared.schemas.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/consent-gate-vocabulary.shared.schemas.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,CAAN,IAAY,iBAaX;AAbD,WAAY,iBAAiB;IAC3B,kIAAkI;IAClI,wCAAmB,CAAA;IACnB,sFAAsF;IACtF,sCAAiB,CAAA;IACjB,+JAA+J;IAC/J,mDAA8B,CAAA;IAC9B,wHAAwH;IACxH,qCAAgB,CAAA;IAChB,wKAAwK;IACxK,2CAAsB,CAAA;IACtB,sKAAsK;IACtK,sCAAiB,CAAA;AACnB,CAAC,EAbW,iBAAiB,KAAjB,iBAAiB,QAa5B;AAED;;;;;;;GAOG;AACH,MAAM,CAAN,IAAY,kBAiBX;AAjBD,WAAY,kBAAkB;IAC5B,qHAAqH;IACrH,uCAAiB,CAAA;IACjB;;;;OAIG;IACH,gEAA0C,CAAA;IAC1C;;;;;;OAMG;IACH,0DAAoC,CAAA;AACtC,CAAC,EAjBW,kBAAkB,KAAlB,kBAAkB,QAiB7B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG,iBAAiB,CAAC,MAAM,CAAC;AAC3E,MAAM,CAAC,MAAM,mCAAmC,GAAG,kBAAkB,CAAC,gBAAgB,CAAC;AA2CvF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAIzC;IACC,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAC9B,IAAI,CAAC,WAAW;QAAE,OAAO,SAAS,CAAC;IACnC,IAAI,KAAK,CAAC,uBAAuB,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAClF,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAClE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,IAAI,kBAAkB,CAAC,mBAAmB,EAAE,CAAC;AAClH,CAAC","sourcesContent":["import { ConsentPurpose } from './consent-purposes.shared';\n\n/**\n * WHEN a person is put the question of a consent-gated purpose (#1258 Step 3).\n *\n * `compliance.serviceConsentRequirement` collapsed this axis to one member — the check runs on\n * every user-initiated operation, forever — and that is correct for exactly the case it exists for\n * (the whole application rests on the purpose). Most declared purposes do not: an operation that\n * merely USES a purpose when it is granted needs to ask once, not on every call.\n *\n * A closed vocabulary rather than a boolean or a duration, because each member is a different KIND\n * of trigger — some are moments in a lifecycle, one is a standing check — and a single \"how often\"\n * field could not tell a reader which.\n */\nexport enum ConsentGateTiming {\n /** Before there is an account — the marketing website's own visitor prompt. Not backend-enforced: no request exists to refuse. */\n VISITOR = 'visitor',\n /** At the moment an account is created, alongside document acceptance. Asked once. */\n SIGNUP = 'signup',\n /** The first time a signed-in person's session reaches the application, via the guidance/onboarding engine (D7). Asked once per person, not per capability. */\n FIRST_SESSION = 'firstSession',\n /** The first time THIS capability is reached, by the surface that declares it. Asked once per person per capability. */\n ON_USE = 'onUse',\n /** Re-asked when the declaration this purpose rests on changes materially — mirrors governed-document re-acceptance (Step 2), never a silent re-prompt of everybody. */\n ON_CHANGE = 'onChange',\n /** Checked on every user-initiated operation, application-wide. The ONLY member `serviceConsentRequirement` uses — see {@link SERVICE_CONSENT_REQUIREMENT_TIMING}. */\n ALWAYS = 'always',\n}\n\n/**\n * WHAT a missing consent-gated purpose costs the person right now (#1258 Step 3).\n *\n * A closed vocabulary rather than a boolean \"blocking\", because a missing purpose has three\n * genuinely different consequences and conflating any two of them either over-blocks (today's\n * `serviceConsentRequirement`, applied per capability, would lock a person out of a to-do list over\n * analytics) or under-informs (silently disabling a feature with no explanation).\n */\nexport enum ConsentGateRefusal {\n /** Nothing is withheld. The purpose is surfaced to the person as a decision they have not made, and nothing more. */\n INFORM = 'inform',\n /**\n * The DECLARING operation refuses, with a typed error the caller can branch on, and nothing else.\n * The default when a declaration names a purpose and no refusal (D2) — a declaration that only\n * says WHAT is asked must not silently become a claim about the whole product.\n */\n WITHHOLD_CAPABILITY = 'withholdCapability',\n /**\n * The whole application is withheld until the purpose is granted. Reserved for the application-wide\n * requirement (`serviceConsentRequirement`) — see {@link SERVICE_CONSENT_REQUIREMENT_REFUSAL}. An\n * operation-level declaration may not choose this member (its type excludes it): a single capability\n * asking for the whole product to be withheld is exactly the collapse D2 exists to prevent, and the\n * one place that genuinely means it already has its own field.\n */\n WITHHOLD_SERVICE = 'withholdService',\n}\n\n/**\n * `compliance.serviceConsentRequirement` is the ONE cell of the ⟨timing, refusal⟩ grid this framework\n * enforces unconditionally (D1): {@link ConsentGateTiming.ALWAYS} × {@link ConsentGateRefusal.WITHHOLD_SERVICE},\n * applied to the whole application rather than to one capability.\n *\n * It needs no `timing` / `refusal` field of its own — the cell is fixed by what the field IS — and\n * these two constants exist only so the mapping is STATED rather than merely true: a reader who has\n * just read {@link ConsentGateTiming} and {@link ConsentGateRefusal} can find, in one place, which\n * cell the field they already know about occupies. The runtime behaviour is unchanged; see\n * `assertServiceConsentRequirementMet` in `@wildo-ai/saas-backend-lib`, which evaluates BOTH this\n * cell and any operation's own {@link ResourceOperationConsentGateDeclaration} through the same\n * chokepoint, so the two axes cannot disagree about a purpose both name.\n */\nexport const SERVICE_CONSENT_REQUIREMENT_TIMING = ConsentGateTiming.ALWAYS;\nexport const SERVICE_CONSENT_REQUIREMENT_REFUSAL = ConsentGateRefusal.WITHHOLD_SERVICE;\n\n/**\n * What a resource OPERATION declares about the purpose its processing rests on (#1258 Step 3).\n *\n * \"A capability declares the purpose it rests on — on the resource operation first\": this is that\n * declaration. It lives beside `recordsUsage` and `userNotifications` on the operation config — an\n * authored consequence of the operation, expressed where the operation is expressed — and is read by\n * the SAME evaluator `serviceConsentRequirement` goes through, so a purpose required at BOTH levels is\n * governed once rather than twice (`consentGateCapabilityOwed`).\n *\n * `refusal` excludes {@link ConsentGateRefusal.WITHHOLD_SERVICE} by TYPE, not by convention — see that\n * member's own doc for why. `timing` is advisory to the backend (which enforces regardless of when a\n * frontend surface asked) and load-bearing for the frontend surface that decides WHEN to ask.\n *\n * **The prompt surface reads this field (#1462).** `applicationAskedConsentPurposes` unions\n * `requiredPurposes`, `analytics.*` and `compliance.capabilityDeclaredConsentPurposes` — the set the\n * engine derives, once at boot, from every operation's own `consentGate` across the whole registry\n * (`collectCapabilityDeclaredConsentPurposes`, called by `ResourcesRegistryBackendService.initialize()`\n * the moment the registry is built). So declaring one here is enough: no second declaration site, and\n * the application-tier gate offers it the same way it already offers ANALYTICS.\n *\n * What this does NOT yet do: distinguish `timing`. `ON_USE` / `FIRST_SESSION` are declared members of\n * {@link ConsentGateTiming} with no dedicated prompt surface to honour them — every declared purpose\n * is offered by the one generic prompt that exists today, regardless of which timing member it names.\n * That is a real, tracked gap (`#1462`'s two folded-in follow-ups), and it is strictly better than the\n * alternative it replaced: refusing a capability with nowhere at all to grant what it asks for.\n */\nexport interface ResourceOperationConsentGateDeclaration {\n /** The purpose this operation's processing rests on. */\n readonly purpose: ConsentPurpose;\n /** What a missing grant costs. Defaults to {@link ConsentGateRefusal.WITHHOLD_CAPABILITY} (D2). */\n readonly refusal?: Exclude<ConsentGateRefusal, ConsentGateRefusal.WITHHOLD_SERVICE>;\n /** When the person is asked. Defaults to {@link ConsentGateTiming.ON_USE}. */\n readonly timing?: ConsentGateTiming;\n}\n\n/** One purpose this principal owes, and what it currently costs them, for ONE operation's declaration. */\nexport interface ConsentGateCapabilityOwed {\n readonly purpose: ConsentPurpose;\n readonly refusal: ConsentGateRefusal;\n}\n\n/**\n * What an operation's OWN {@link ResourceOperationConsentGateDeclaration} still owes, given what the\n * person has granted and what the application already requires application-wide.\n *\n * Pure, so the merge rule between the two independent sources of a required purpose — the\n * application-wide requirement and a capability's own declaration — is written once and pinned\n * without a running backend. `undefined` in every case where nothing is owed:\n *\n * - the operation declares nothing;\n * - the declared purpose is already granted;\n * - the declared purpose is ALSO in the application-wide required set — that purpose is already\n * governed by `serviceConsentRequirement`'s WITHHOLD_SERVICE cell, so re-declaring it here would\n * evaluate the same fact twice and could, on a future edit, disagree with itself.\n */\nexport function consentGateCapabilityOwed(input: {\n readonly granted: readonly ConsentPurpose[];\n readonly declaration: ResourceOperationConsentGateDeclaration | undefined;\n readonly serviceRequiredPurposes: readonly ConsentPurpose[];\n}): ConsentGateCapabilityOwed | undefined {\n const { declaration } = input;\n if (!declaration) return undefined;\n if (input.serviceRequiredPurposes.includes(declaration.purpose)) return undefined;\n if (input.granted.includes(declaration.purpose)) return undefined;\n return { purpose: declaration.purpose, refusal: declaration.refusal ?? ConsentGateRefusal.WITHHOLD_CAPABILITY };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-purposes.shared.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"consent-purposes.shared.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/consent-purposes.shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,oBAAY,cAAc;IACxB,6EAA6E;IAC7E,SAAS,cAAc;IACvB,mFAAmF;IACnF,SAAS,cAAc;CACxB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,4BAA4B,CAAC;AAE7E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,6BAA6B,oCAAoC,CAAC;AAE/E;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,+BAA+B,QAAQ,CAAC;AAErD,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAAiD,CAAC;AAExG;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAC9C,QAAQ,EAAE,SAAS,cAAc,EAAE,GAClC,cAAc,EAAE,CAGlB;AAED,uDAAuD;AACvD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAC9C,QAAQ,EAAE,SAAS,cAAc,EAAE,GAClC,OAAO,CAET;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE;IACrD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAC;IAC3C,0IAA0I;IAC1I,QAAQ,CAAC,0BAA0B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzD,GAAG,cAAc,EAAE,CAQnB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,cAAc,EAAE,CAGlG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-purposes.shared.js","sourceRoot":"","sources":["../../../../../src/compliance/privacy/consent-purposes.shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAN,IAAY,cAKX;AALD,WAAY,cAAc;IACxB,6EAA6E;IAC7E,yCAAuB,CAAA;IACvB,mFAAmF;IACnF,yCAAuB,CAAA;AACzB,CAAC,EALW,cAAc,KAAd,cAAc,QAKzB;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,yBAAyB,CAAC;AAE7E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,iCAAiC,CAAC;AAE/E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,CAAC;AAErD,uFAAuF;AACvF,MAAM,CAAC,MAAM,gBAAgB,GAA8B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;AAExG;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAA8C,EAC9C,QAAmC;IAEnC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC1C,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACtG,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,yBAAyB,CACvC,OAA8C,EAC9C,QAAmC;IAEnC,OAAO,sBAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,+BAA+B,CAAC,KAM/C;IACC,MAAM,QAAQ,GAAG,wBAAwB,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAClE,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACtF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAiB,CAAC,GAAG,QAAQ,EAAE,GAAG,kBAAkB,CAAC,CAAC,CAAC;IAC5E,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC;QAC7D,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAuC;IAC9E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IACtC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC","sourcesContent":["/**\n * Consent purposes — the optional processing a person may independently agree to.\n *\n * ## A SET, not a ladder (decided by Paul, 2026-09-09 — #534 / #453)\n *\n * This replaces `DataProcessingConsent` (`NONE · BASIC · ANALYTICS · MARKETING · FULL`), which was an\n * ORDERED level. The order was a claim nobody decided and the law does not make: agreeing to\n * marketing is not \"more than\" agreeing to analytics, and a ladder made consenting to one imply\n * consenting to the ones \"below\" it. The only thing that ever enforced the order was a module-private\n * `CONSENT_ORDER` inside the frontend analytics provider.\n *\n * So each member is a PURPOSE, granted or not on its own, and a person's consent is the set of\n * purposes they granted. The old members map without loss of meaning:\n *\n * - `NONE` → the empty set.\n * - `BASIC` → not a purpose at all. It stood for processing the service needs in order to exist,\n * which is never consent-based (it rests on contract or legitimate interest), so it has no member.\n * - `FULL` → every member.\n *\n * ## Why this file imports nothing\n *\n * It is carved onto `@wildo-ai/saas-models/public-runtime` (K-2), because the visitor-tier\n * `WebsiteConsentGate` in the browser bundle reads the same vocabulary the application stores. One\n * vocabulary, one file: the original privacy schema imports it from here.\n *\n * Adding a member is a product decision with legal weight — every surface that asks a person for\n * consent renders the whole set, and every application's consent-gated processing must name which\n * member it rests on.\n */\nexport enum ConsentPurpose {\n /** Measuring how the service is used — product analytics, usage tracking. */\n ANALYTICS = 'analytics',\n /** Contacting the person or tailoring outreach to them for promotional reasons. */\n MARKETING = 'marketing',\n}\n\n/**\n * The browser storage key under which a Wildo marketing website keeps a VISITOR's consent decision.\n *\n * The visitor tier has no account to store a decision on, so it lives in the visitor's own browser, on\n * the website's origin — which is also why it does not follow them into the signed-in application, whose\n * decision is `privacy.consentedPurposes` on the person's preferences. Named once here so the website's\n * storage adapter and the cookie table (`ENGINE_CLIENT_STORAGE_ENTRIES`) cannot name different keys.\n */\nexport const WEBSITE_VISITOR_CONSENT_STORAGE_KEY = '__wildo_website_consent';\n\n/**\n * The route a VISITOR's consent decision is recorded through — `ANONYMOUS_USERS.record_consent`.\n *\n * Named here for the same reason as the storage key above: the marketing website must not depend on\n * `saas-models`' resource layer (bundle discipline keeps it to `public-runtime` atoms), so without a\n * shared constant the website would hard-code a path string and the engine would build one, with\n * nothing joining them. `/inbound-contacts` is hard-coded that way today, which is the drift this\n * avoids.\n *\n * It is not asserted by hand: `consent-purposes.shared.test.ts` derives it from the operation's own\n * identifier through `ResourcesConfigNamingUtils.toKebabCase` — the same transform the URL builder\n * uses — so renaming the resource or the operation reddens rather than 404s at runtime.\n */\nexport const ANONYMOUS_CONSENT_RECORD_PATH = '/anonymous-users/record-consent';\n\n/**\n * The HTTP METHOD that route answers — `PUT`, not `POST`.\n *\n * ## Why this constant had to exist\n *\n * The sibling above named the PATH and stopped there, and its own note predicted the consequence of a\n * drift precisely: *\"the failure is a 404 at runtime, on a public path nobody monitors.\"* That is what\n * happened, to the half it did not cover. `RECORD_CONSENT` declares\n * `resourceOperationLike: UPDATE_MANY`, and `getDefaultHttpVerbForOperation` maps every UPDATE verb to\n * `PUT` — but nothing said so where a client could read it, so two independent clients assumed POST and\n * both 404'd: the marketing website's recorder, whose failure is deliberately (and correctly) silent,\n * and the application's pre-auth recorder written against it.\n *\n * A path without its method is half an address. Naming both here is what lets a client be right by\n * reading rather than by guessing, and `consent-purposes.shared.test.ts` derives this from the built\n * operation's own `httpVerb` — the value the router registers — so changing the operation's shape\n * reddens instead of silently moving the door.\n */\nexport const ANONYMOUS_CONSENT_RECORD_METHOD = 'PUT';\n\n/** Every purpose, in declaration order — the order a consent surface lists them in. */\nexport const CONSENT_PURPOSES: readonly ConsentPurpose[] = Object.freeze(Object.values(ConsentPurpose));\n\n/**\n * The purposes in `required` that `granted` does not contain. Empty when every required purpose was\n * granted — including when nothing is required.\n *\n * Membership, never rank: there is no purpose whose grant satisfies another.\n */\nexport function missingConsentPurposes(\n granted: readonly ConsentPurpose[] | undefined,\n required: readonly ConsentPurpose[],\n): ConsentPurpose[] {\n const grantedSet = new Set(granted ?? []);\n return CONSENT_PURPOSES.filter((purpose) => required.includes(purpose) && !grantedSet.has(purpose));\n}\n\n/** Whether every purpose in `required` was granted. */\nexport function hasGrantedConsentPurposes(\n granted: readonly ConsentPurpose[] | undefined,\n required: readonly ConsentPurpose[],\n): boolean {\n return missingConsentPurposes(granted, required).length === 0;\n}\n\n/**\n * Every purpose THIS APPLICATION would put to a person — what its own consent surface asks.\n *\n * Two readers needed this and would otherwise have derived it twice: the application's consent gate,\n * deciding what to render, and the anonymous-consent carry, deciding whether a visitor was shown\n * enough for their decision to count as complete. Two derivations of \"what do we ask\" drift, and the\n * drift is invisible — the gate would prompt for a purpose the carry had already recorded as\n * decided, or the reverse.\n *\n * Takes PRIMITIVES rather than the config objects, so this file keeps the import-free property that\n * lets it be carved onto `public-runtime` for the website bundle.\n *\n * Total over what the configuration STATES A USE FOR, never over the enum: asking for a purpose\n * nothing processes collects a consent that means nothing. A required purpose is asked by\n * definition; ANALYTICS is asked when analytics runs and rests on consent; and — since #1462 — a\n * purpose at least one resource operation's `consentGate` names is asked too, because a capability\n * that may refuse over a purpose is a capability that must have somewhere to grant it. This function\n * does not, and cannot, distinguish WHEN each purpose should be asked (a required purpose, ANALYTICS\n * and a `consentGate` purpose may each want different `ConsentGateTiming`); it only says WHETHER the\n * one generic prompt surface that exists today should offer it.\n */\nexport function applicationAskedConsentPurposes(input: {\n readonly requiredPurposes?: readonly string[];\n readonly analyticsEnabled: boolean;\n readonly analyticsRequiresConsent: boolean;\n /** Every purpose declared by at least one resource operation's `consentGate` (#1462) — `compliance.capabilityDeclaredConsentPurposes`. */\n readonly capabilityDeclaredPurposes?: readonly string[];\n}): ConsentPurpose[] {\n const required = normalizeConsentPurposes(input.requiredPurposes);\n const capabilityDeclared = normalizeConsentPurposes(input.capabilityDeclaredPurposes);\n const asked = new Set<ConsentPurpose>([...required, ...capabilityDeclared]);\n if (input.analyticsEnabled && input.analyticsRequiresConsent) {\n asked.add(ConsentPurpose.ANALYTICS);\n }\n return CONSENT_PURPOSES.filter((purpose) => asked.has(purpose));\n}\n\n/**\n * A purpose list in its canonical form: de-duplicated, restricted to known members, in declaration\n * order.\n *\n * Stored consent is compared by the audit trail's before/after evidence, so two lists naming the same\n * purposes in a different order must not read as a change of decision.\n */\nexport function normalizeConsentPurposes(purposes: readonly string[] | undefined): ConsentPurpose[] {\n const given = new Set(purposes ?? []);\n return CONSENT_PURPOSES.filter((purpose) => given.has(purpose));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"consent-purposes.shared.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/consent-purposes.shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAN,IAAY,cAKX;AALD,WAAY,cAAc;IACxB,6EAA6E;IAC7E,yCAAuB,CAAA;IACvB,mFAAmF;IACnF,yCAAuB,CAAA;AACzB,CAAC,EALW,cAAc,KAAd,cAAc,QAKzB;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,yBAAyB,CAAC;AAE7E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,iCAAiC,CAAC;AAE/E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,CAAC;AAErD,uFAAuF;AACvF,MAAM,CAAC,MAAM,gBAAgB,GAA8B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;AAExG;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAA8C,EAC9C,QAAmC;IAEnC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC1C,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACtG,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,yBAAyB,CACvC,OAA8C,EAC9C,QAAmC;IAEnC,OAAO,sBAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,+BAA+B,CAAC,KAM/C;IACC,MAAM,QAAQ,GAAG,wBAAwB,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAClE,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACtF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAiB,CAAC,GAAG,QAAQ,EAAE,GAAG,kBAAkB,CAAC,CAAC,CAAC;IAC5E,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC;QAC7D,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAuC;IAC9E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IACtC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC","sourcesContent":["/**\n * Consent purposes — the optional processing a person may independently agree to.\n *\n * ## A SET, not a ladder (decided by Paul, 2026-09-09 — #534 / #453)\n *\n * This replaces `DataProcessingConsent` (`NONE · BASIC · ANALYTICS · MARKETING · FULL`), which was an\n * ORDERED level. The order was a claim nobody decided and the law does not make: agreeing to\n * marketing is not \"more than\" agreeing to analytics, and a ladder made consenting to one imply\n * consenting to the ones \"below\" it. The only thing that ever enforced the order was a module-private\n * `CONSENT_ORDER` inside the frontend analytics provider.\n *\n * So each member is a PURPOSE, granted or not on its own, and a person's consent is the set of\n * purposes they granted. The old members map without loss of meaning:\n *\n * - `NONE` → the empty set.\n * - `BASIC` → not a purpose at all. It stood for processing the service needs in order to exist,\n * which is never consent-based (it rests on contract or legitimate interest), so it has no member.\n * - `FULL` → every member.\n *\n * ## Why this file imports nothing\n *\n * It is carved onto `@wildo-ai/saas-models/public-runtime` (K-2), because the visitor-tier\n * `WebsiteConsentGate` in the browser bundle reads the same vocabulary the application stores. One\n * vocabulary, one file: the original privacy schema imports it from here.\n *\n * Adding a member is a product decision with legal weight — every surface that asks a person for\n * consent renders the whole set, and every application's consent-gated processing must name which\n * member it rests on.\n */\nexport enum ConsentPurpose {\n /** Measuring how the service is used — product analytics, usage tracking. */\n ANALYTICS = 'analytics',\n /** Contacting the person or tailoring outreach to them for promotional reasons. */\n MARKETING = 'marketing',\n}\n\n/**\n * The browser storage key under which a Wildo marketing website keeps a VISITOR's consent decision.\n *\n * The visitor tier has no account to store a decision on, so it lives in the visitor's own browser, on\n * the website's origin — which is also why it does not follow them into the signed-in application, whose\n * decision is `privacy.consentedPurposes` on the person's preferences. Named once here so the website's\n * storage adapter and the cookie table (`ENGINE_CLIENT_STORAGE_ENTRIES`) cannot name different keys.\n */\nexport const WEBSITE_VISITOR_CONSENT_STORAGE_KEY = '__wildo_website_consent';\n\n/**\n * The route a VISITOR's consent decision is recorded through — `ANONYMOUS_USERS.record_consent`.\n *\n * Named here for the same reason as the storage key above: the marketing website must not depend on\n * `saas-models`' resource layer (bundle discipline keeps it to `public-runtime` atoms), so without a\n * shared constant the website would hard-code a path string and the engine would build one, with\n * nothing joining them. `/inbound-contacts` is hard-coded that way today, which is the drift this\n * avoids.\n *\n * It is not asserted by hand: `consent-purposes.shared.test.ts` derives it from the operation's own\n * identifier through `ResourcesConfigNamingUtils.toKebabCase` — the same transform the URL builder\n * uses — so renaming the resource or the operation reddens rather than 404s at runtime.\n */\nexport const ANONYMOUS_CONSENT_RECORD_PATH = '/anonymous-users/record-consent';\n\n/**\n * The HTTP METHOD that route answers — `PUT`, not `POST`.\n *\n * ## Why this constant had to exist\n *\n * The sibling above named the PATH and stopped there, and its own note predicted the consequence of a\n * drift precisely: *\"the failure is a 404 at runtime, on a public path nobody monitors.\"* That is what\n * happened, to the half it did not cover. `RECORD_CONSENT` declares\n * `resourceOperationLike: UPDATE_MANY`, and `getDefaultHttpVerbForOperation` maps every UPDATE verb to\n * `PUT` — but nothing said so where a client could read it, so two independent clients assumed POST and\n * both 404'd: the marketing website's recorder, whose failure is deliberately (and correctly) silent,\n * and the application's pre-auth recorder written against it.\n *\n * A path without its method is half an address. Naming both here is what lets a client be right by\n * reading rather than by guessing, and `consent-purposes.shared.test.ts` derives this from the built\n * operation's own `httpVerb` — the value the router registers — so changing the operation's shape\n * reddens instead of silently moving the door.\n */\nexport const ANONYMOUS_CONSENT_RECORD_METHOD = 'PUT';\n\n/** Every purpose, in declaration order — the order a consent surface lists them in. */\nexport const CONSENT_PURPOSES: readonly ConsentPurpose[] = Object.freeze(Object.values(ConsentPurpose));\n\n/**\n * The purposes in `required` that `granted` does not contain. Empty when every required purpose was\n * granted — including when nothing is required.\n *\n * Membership, never rank: there is no purpose whose grant satisfies another.\n */\nexport function missingConsentPurposes(\n granted: readonly ConsentPurpose[] | undefined,\n required: readonly ConsentPurpose[],\n): ConsentPurpose[] {\n const grantedSet = new Set(granted ?? []);\n return CONSENT_PURPOSES.filter((purpose) => required.includes(purpose) && !grantedSet.has(purpose));\n}\n\n/** Whether every purpose in `required` was granted. */\nexport function hasGrantedConsentPurposes(\n granted: readonly ConsentPurpose[] | undefined,\n required: readonly ConsentPurpose[],\n): boolean {\n return missingConsentPurposes(granted, required).length === 0;\n}\n\n/**\n * Every purpose THIS APPLICATION would put to a person — what its own consent surface asks.\n *\n * Two readers needed this and would otherwise have derived it twice: the application's consent gate,\n * deciding what to render, and the anonymous-consent carry, deciding whether a visitor was shown\n * enough for their decision to count as complete. Two derivations of \"what do we ask\" drift, and the\n * drift is invisible — the gate would prompt for a purpose the carry had already recorded as\n * decided, or the reverse.\n *\n * Takes PRIMITIVES rather than the config objects, so this file keeps the import-free property that\n * lets it be carved onto `public-runtime` for the website bundle.\n *\n * Total over what the configuration STATES A USE FOR, never over the enum: asking for a purpose\n * nothing processes collects a consent that means nothing. A required purpose is asked by\n * definition; ANALYTICS is asked when analytics runs and rests on consent; and — since #1462 — a\n * purpose at least one resource operation's `consentGate` names is asked too, because a capability\n * that may refuse over a purpose is a capability that must have somewhere to grant it. This function\n * does not, and cannot, distinguish WHEN each purpose should be asked (a required purpose, ANALYTICS\n * and a `consentGate` purpose may each want different `ConsentGateTiming`); it only says WHETHER the\n * one generic prompt surface that exists today should offer it.\n */\nexport function applicationAskedConsentPurposes(input: {\n readonly requiredPurposes?: readonly string[];\n readonly analyticsEnabled: boolean;\n readonly analyticsRequiresConsent: boolean;\n /** Every purpose declared by at least one resource operation's `consentGate` (#1462) — `compliance.capabilityDeclaredConsentPurposes`. */\n readonly capabilityDeclaredPurposes?: readonly string[];\n}): ConsentPurpose[] {\n const required = normalizeConsentPurposes(input.requiredPurposes);\n const capabilityDeclared = normalizeConsentPurposes(input.capabilityDeclaredPurposes);\n const asked = new Set<ConsentPurpose>([...required, ...capabilityDeclared]);\n if (input.analyticsEnabled && input.analyticsRequiresConsent) {\n asked.add(ConsentPurpose.ANALYTICS);\n }\n return CONSENT_PURPOSES.filter((purpose) => asked.has(purpose));\n}\n\n/**\n * A purpose list in its canonical form: de-duplicated, restricted to known members, in declaration\n * order.\n *\n * Stored consent is compared by the audit trail's before/after evidence, so two lists naming the same\n * purposes in a different order must not read as a change of decision.\n */\nexport function normalizeConsentPurposes(purposes: readonly string[] | undefined): ConsentPurpose[] {\n const given = new Set(purposes ?? []);\n return CONSENT_PURPOSES.filter((purpose) => given.has(purpose));\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-subject-rights.shared.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"data-subject-rights.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/data-subject-rights.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAC;AAGpG;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,mEAAmE;AACnE,oBAAY,oBAAoB;IAC9B,2DAA2D;IAC3D,OAAO,YAAY;IACnB,uGAAuG;IACvG,OAAO,YAAY;CACpB;AAQD,yDAAyD;AACzD,oBAAY,gBAAgB;IAC1B,2EAA2E;IAC3E,MAAM,WAAW;IACjB,kDAAkD;IAClD,aAAa,kBAAkB;IAC/B,+DAA+D;IAC/D,OAAO,YAAY;IACnB,2CAA2C;IAC3C,WAAW,gBAAgB;IAC3B,0HAA0H;IAC1H,WAAW,gBAAgB;IAC3B,2FAA2F;IAC3F,SAAS,cAAc;IACvB,wFAAwF;IACxF,gBAAgB,qBAAqB;IACrC,+HAA+H;IAC/H,eAAe,oBAAoB;IACnC,kHAAkH;IAClH,sBAAsB,2BAA2B;CAClD;AAED,uGAAuG;AACvG,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wGAAwG;IACxG,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,sGAAsG;AACtG,wBAAgB,sBAAsB,CAAC,gBAAgB,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAEjG;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,oBAAoB,EAC5B,WAAW,EAAE,SAAS;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;CAAE,EAAE,GAChF,SAAS,0BAA0B,EAAE,CAiBvC;AAeD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAO9E;AAED,uEAAuE;AACvE,oBAAY,uBAAuB;IACjC,kFAAkF;IAClF,QAAQ,aAAa;IACrB;;;;OAIG;IACH,mBAAmB,wBAAwB;CAC5C;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,sBAAsB,GAAG,uBAAuB,GAAG,SAAS,CAS5G"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LawfulBasis, OperatorProcessingRole } from './operator-compliance-identity.shared.schemas.js';
|
|
2
|
-
import { jurisdictionReachCovers } from './
|
|
2
|
+
import { jurisdictionReachCovers } from './jurisdiction-containment.shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* **Which data-subject rights a privacy notice must state, derived from where the application operates and
|
|
5
5
|
* the lawful bases it declares.**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-subject-rights.shared.schemas.js","sourceRoot":"","sources":["../../../../../src/compliance/privacy/data-subject-rights.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { LawfulBasis, OperatorProcessingRole } from './operator-compliance-identity.shared.schemas';\nimport { jurisdictionReachCovers } from './operating-jurisdictions.shared.schemas';\n\n/**\n * **Which data-subject rights a privacy notice must state, derived from where the application operates and\n * the lawful bases it declares.**\n *\n * A notice must tell a person which rights they have (GDPR Art. 13(2)(b)–(d)). Which ones apply is not the\n * operator's choice: the law attaches them, several of them conditionally on the lawful basis of the\n * processing. So nobody is asked to type this list. It is a function of two declarations the application\n * already makes — `operatingJurisdictions` and `operatorComplianceIdentity.lawfulBases` — and of the law\n * of the regime a jurisdiction falls under, which is written down here once.\n *\n * spec-cite: GDPR Art. 13(2)(b)–(d), Art. 15–18, Art. 20(1), Art. 21(1), Art. 7(3), Art. 77(1).\n * spec-cite: UK GDPR Art. 7(3), 15–18, 20, 21 (legislation.gov.uk, read 2026-09-25); Data Protection Act 2018\n * s.164A and s.165(2) as amended by the Data (Use and Access) Act 2025 s.103, in force 19 June 2026.\n *\n * ## Only the regimes written here are known, and an unknown one is named rather than guessed\n *\n * Two regimes: the EU GDPR, reaching every EU member state through {@link jurisdictionReachCovers}, and the\n * United Kingdom's. They are written separately although the rights match article for article, because the\n * complaint route does not: from 19 June 2026 UK GDPR Art. 77 is omitted, a person may complain to the\n * controller itself (DPA 2018 s.164A — acknowledged within 30 days) and to the Information Commissioner\n * (s.165(2)). A notice that borrowed the EU wording would name a route UK law no longer has. A declared\n * jurisdiction outside every known regime gets NO rights list and the caller names it as owed. Adding a\n * regime is a deliberate edit to {@link DATA_PROTECTION_REGIME_REACH}, {@link rightsUnderRegime} and\n * {@link complaintRouteUnderRegime}, with its own citations.\n */\n\n/** A data-protection regime whose rights this module can state. */\nexport enum DataProtectionRegime {\n /** Regulation (EU) 2016/679, for every EU member state. */\n EU_GDPR = 'EU_GDPR',\n /** The UK GDPR with the Data Protection Act 2018, as amended by the Data (Use and Access) Act 2025. */\n UK_GDPR = 'UK_GDPR',\n}\n\n/** The jurisdiction each regime reaches, in the `operatingJurisdictions` slug vocabulary. */\nconst DATA_PROTECTION_REGIME_REACH: Readonly<Record<DataProtectionRegime, string>> = {\n [DataProtectionRegime.EU_GDPR]: 'eu',\n [DataProtectionRegime.UK_GDPR]: 'gb',\n};\n\n/** A right a data subject holds against a controller. */\nexport enum DataSubjectRight {\n /** Art. 15 — access to their data and information about its processing. */\n ACCESS = 'ACCESS',\n /** Art. 16 — rectification of inaccurate data. */\n RECTIFICATION = 'RECTIFICATION',\n /** Art. 17 — erasure, subject to the Art. 17(3) exceptions. */\n ERASURE = 'ERASURE',\n /** Art. 18 — restriction of processing. */\n RESTRICTION = 'RESTRICTION',\n /** Art. 20 — portability of data the subject provided, where processing rests on consent or contract and is automated. */\n PORTABILITY = 'PORTABILITY',\n /** Art. 21(1) — objection to processing resting on public task or legitimate interests. */\n OBJECTION = 'OBJECTION',\n /** Art. 7(3) — withdrawal of consent at any time, where processing rests on consent. */\n WITHDRAW_CONSENT = 'WITHDRAW_CONSENT',\n /** A complaint to the supervisory authority — GDPR Art. 77(1); in the UK, the Information Commissioner (DPA 2018 s.165(2)). */\n LODGE_COMPLAINT = 'LODGE_COMPLAINT',\n /** UK only — a complaint to the controller itself, which must acknowledge it within 30 days (DPA 2018 s.164A). */\n COMPLAIN_TO_CONTROLLER = 'COMPLAIN_TO_CONTROLLER',\n}\n\n/** One right as it applies to this application: the provision, and the declared purposes it covers. */\nexport interface ApplicableDataSubjectRight {\n readonly right: DataSubjectRight;\n readonly provision: string;\n /** The declared processing purposes the right attaches to. Every purpose for an unconditional right. */\n readonly purposes: readonly string[];\n}\n\n/** The regime a declared jurisdiction falls under, or `undefined` when no known regime reaches it. */\nexport function dataProtectionRegimeOf(jurisdictionSlug: string): DataProtectionRegime | undefined {\n return Object.values(DataProtectionRegime).find((regime) => jurisdictionReachCovers(DATA_PROTECTION_REGIME_REACH[regime], jurisdictionSlug));\n}\n\n/**\n * The rights a regime grants for the declared purposes and their bases.\n *\n * A conditional right is listed only when at least one declared purpose meets its condition, and then only\n * for those purposes: stating a right to object to processing that rests on contract would tell a person\n * they may stop the service they signed up for. The complaint route is always listed — Art. 13(2)(d) requires\n * it whatever the basis.\n */\nexport function rightsUnderRegime(\n regime: DataProtectionRegime,\n lawfulBases: readonly { readonly purpose: string; readonly basis: LawfulBasis }[],\n): readonly ApplicableDataSubjectRight[] {\n const every = lawfulBases.map((entry) => entry.purpose);\n const where = (bases: readonly LawfulBasis[]): string[] => lawfulBases.filter((entry) => bases.includes(entry.basis)).map((entry) => entry.purpose);\n // The UK kept the GDPR's rights articles, so one table serves both regimes; only the statute's name and the\n // complaint provisions differ.\n const law = regime === DataProtectionRegime.EU_GDPR ? 'GDPR' : 'UK GDPR';\n const rights: ApplicableDataSubjectRight[] = [\n { right: DataSubjectRight.ACCESS, provision: `${law} Art. 15`, purposes: every },\n { right: DataSubjectRight.RECTIFICATION, provision: `${law} Art. 16`, purposes: every },\n { right: DataSubjectRight.ERASURE, provision: `${law} Art. 17`, purposes: every },\n { right: DataSubjectRight.RESTRICTION, provision: `${law} Art. 18`, purposes: every },\n { right: DataSubjectRight.PORTABILITY, provision: `${law} Art. 20(1)`, purposes: where([LawfulBasis.CONSENT, LawfulBasis.CONTRACT]) },\n { right: DataSubjectRight.OBJECTION, provision: `${law} Art. 21(1)`, purposes: where([LawfulBasis.PUBLIC_TASK, LawfulBasis.LEGITIMATE_INTERESTS]) },\n { right: DataSubjectRight.WITHDRAW_CONSENT, provision: `${law} Art. 7(3)`, purposes: where([LawfulBasis.CONSENT]) },\n ...complaintRights(regime, every),\n ];\n return rights.filter((entry) => entry.purposes.length > 0);\n}\n\n/** The complaint rights a regime grants — where it differs from its neighbour, which is why it is its own switch. */\nfunction complaintRights(regime: DataProtectionRegime, every: string[]): ApplicableDataSubjectRight[] {\n switch (regime) {\n case DataProtectionRegime.EU_GDPR:\n return [{ right: DataSubjectRight.LODGE_COMPLAINT, provision: 'GDPR Art. 77(1)', purposes: every }];\n case DataProtectionRegime.UK_GDPR:\n return [\n { right: DataSubjectRight.COMPLAIN_TO_CONTROLLER, provision: 'Data Protection Act 2018 s.164A', purposes: every },\n { right: DataSubjectRight.LODGE_COMPLAINT, provision: 'Data Protection Act 2018 s.165(2)', purposes: every },\n ];\n }\n}\n\n/**\n * Where a person may complain under a regime, as a notice states it.\n *\n * The regime fixes the route; the operator chooses nothing here, which is why no authority is NAMED. Under\n * the GDPR a person may complain to the authority of their own member state (Art. 77(1)) whichever authority\n * leads for the operator, so naming only the operator's lead authority would understate the route.\n */\nexport function complaintRouteUnderRegime(regime: DataProtectionRegime): string {\n switch (regime) {\n case DataProtectionRegime.EU_GDPR:\n return 'a supervisory authority, in particular in the member state of habitual residence, place of work or place of the alleged infringement (GDPR Art. 77(1))';\n case DataProtectionRegime.UK_GDPR:\n return 'the operator itself, which must acknowledge the complaint within 30 days and tell you its outcome (Data Protection Act 2018 s.164A), and the Information Commissioner (s.165(2))';\n }\n}\n\n/** Who answers a data-subject request about one population of data. */\nexport enum SubjectRequestResponder {\n /** The operator is the controller of this data and answers the request itself. */\n OPERATOR = 'OPERATOR',\n /**\n * The operator is a PROCESSOR here: the customer that controls the data answers, and the operator forwards the\n * request and assists (GDPR Art. 28(3)(e)). A notice saying the operator will answer would promise a decision\n * the operator has no authority to make over its customer's records.\n */\n CUSTOMER_CONTROLLER = 'CUSTOMER_CONTROLLER',\n}\n\n/**\n * Who answers, for a role the operator holds over a population. `undefined` for a joint controllership, whose\n * arrangement decides it and is not declared anywhere a function can read.\n */\nexport function subjectRequestResponderFor(role: OperatorProcessingRole): SubjectRequestResponder | undefined {\n switch (role) {\n case OperatorProcessingRole.CONTROLLER:\n return SubjectRequestResponder.OPERATOR;\n case OperatorProcessingRole.PROCESSOR:\n return SubjectRequestResponder.CUSTOMER_CONTROLLER;\n case OperatorProcessingRole.JOINT_CONTROLLER:\n return undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"data-subject-rights.shared.schemas.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/data-subject-rights.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { LawfulBasis, OperatorProcessingRole } from './operator-compliance-identity.shared.schemas';\nimport { jurisdictionReachCovers } from './jurisdiction-containment.shared';\n\n/**\n * **Which data-subject rights a privacy notice must state, derived from where the application operates and\n * the lawful bases it declares.**\n *\n * A notice must tell a person which rights they have (GDPR Art. 13(2)(b)–(d)). Which ones apply is not the\n * operator's choice: the law attaches them, several of them conditionally on the lawful basis of the\n * processing. So nobody is asked to type this list. It is a function of two declarations the application\n * already makes — `operatingJurisdictions` and `operatorComplianceIdentity.lawfulBases` — and of the law\n * of the regime a jurisdiction falls under, which is written down here once.\n *\n * spec-cite: GDPR Art. 13(2)(b)–(d), Art. 15–18, Art. 20(1), Art. 21(1), Art. 7(3), Art. 77(1).\n * spec-cite: UK GDPR Art. 7(3), 15–18, 20, 21 (legislation.gov.uk, read 2026-09-25); Data Protection Act 2018\n * s.164A and s.165(2) as amended by the Data (Use and Access) Act 2025 s.103, in force 19 June 2026.\n *\n * ## Only the regimes written here are known, and an unknown one is named rather than guessed\n *\n * Two regimes: the EU GDPR, reaching every EU member state through {@link jurisdictionReachCovers}, and the\n * United Kingdom's. They are written separately although the rights match article for article, because the\n * complaint route does not: from 19 June 2026 UK GDPR Art. 77 is omitted, a person may complain to the\n * controller itself (DPA 2018 s.164A — acknowledged within 30 days) and to the Information Commissioner\n * (s.165(2)). A notice that borrowed the EU wording would name a route UK law no longer has. A declared\n * jurisdiction outside every known regime gets NO rights list and the caller names it as owed. Adding a\n * regime is a deliberate edit to {@link DATA_PROTECTION_REGIME_REACH}, {@link rightsUnderRegime} and\n * {@link complaintRouteUnderRegime}, with its own citations.\n */\n\n/** A data-protection regime whose rights this module can state. */\nexport enum DataProtectionRegime {\n /** Regulation (EU) 2016/679, for every EU member state. */\n EU_GDPR = 'EU_GDPR',\n /** The UK GDPR with the Data Protection Act 2018, as amended by the Data (Use and Access) Act 2025. */\n UK_GDPR = 'UK_GDPR',\n}\n\n/** The jurisdiction each regime reaches, in the `operatingJurisdictions` slug vocabulary. */\nconst DATA_PROTECTION_REGIME_REACH: Readonly<Record<DataProtectionRegime, string>> = {\n [DataProtectionRegime.EU_GDPR]: 'eu',\n [DataProtectionRegime.UK_GDPR]: 'gb',\n};\n\n/** A right a data subject holds against a controller. */\nexport enum DataSubjectRight {\n /** Art. 15 — access to their data and information about its processing. */\n ACCESS = 'ACCESS',\n /** Art. 16 — rectification of inaccurate data. */\n RECTIFICATION = 'RECTIFICATION',\n /** Art. 17 — erasure, subject to the Art. 17(3) exceptions. */\n ERASURE = 'ERASURE',\n /** Art. 18 — restriction of processing. */\n RESTRICTION = 'RESTRICTION',\n /** Art. 20 — portability of data the subject provided, where processing rests on consent or contract and is automated. */\n PORTABILITY = 'PORTABILITY',\n /** Art. 21(1) — objection to processing resting on public task or legitimate interests. */\n OBJECTION = 'OBJECTION',\n /** Art. 7(3) — withdrawal of consent at any time, where processing rests on consent. */\n WITHDRAW_CONSENT = 'WITHDRAW_CONSENT',\n /** A complaint to the supervisory authority — GDPR Art. 77(1); in the UK, the Information Commissioner (DPA 2018 s.165(2)). */\n LODGE_COMPLAINT = 'LODGE_COMPLAINT',\n /** UK only — a complaint to the controller itself, which must acknowledge it within 30 days (DPA 2018 s.164A). */\n COMPLAIN_TO_CONTROLLER = 'COMPLAIN_TO_CONTROLLER',\n}\n\n/** One right as it applies to this application: the provision, and the declared purposes it covers. */\nexport interface ApplicableDataSubjectRight {\n readonly right: DataSubjectRight;\n readonly provision: string;\n /** The declared processing purposes the right attaches to. Every purpose for an unconditional right. */\n readonly purposes: readonly string[];\n}\n\n/** The regime a declared jurisdiction falls under, or `undefined` when no known regime reaches it. */\nexport function dataProtectionRegimeOf(jurisdictionSlug: string): DataProtectionRegime | undefined {\n return Object.values(DataProtectionRegime).find((regime) => jurisdictionReachCovers(DATA_PROTECTION_REGIME_REACH[regime], jurisdictionSlug));\n}\n\n/**\n * The rights a regime grants for the declared purposes and their bases.\n *\n * A conditional right is listed only when at least one declared purpose meets its condition, and then only\n * for those purposes: stating a right to object to processing that rests on contract would tell a person\n * they may stop the service they signed up for. The complaint route is always listed — Art. 13(2)(d) requires\n * it whatever the basis.\n */\nexport function rightsUnderRegime(\n regime: DataProtectionRegime,\n lawfulBases: readonly { readonly purpose: string; readonly basis: LawfulBasis }[],\n): readonly ApplicableDataSubjectRight[] {\n const every = lawfulBases.map((entry) => entry.purpose);\n const where = (bases: readonly LawfulBasis[]): string[] => lawfulBases.filter((entry) => bases.includes(entry.basis)).map((entry) => entry.purpose);\n // The UK kept the GDPR's rights articles, so one table serves both regimes; only the statute's name and the\n // complaint provisions differ.\n const law = regime === DataProtectionRegime.EU_GDPR ? 'GDPR' : 'UK GDPR';\n const rights: ApplicableDataSubjectRight[] = [\n { right: DataSubjectRight.ACCESS, provision: `${law} Art. 15`, purposes: every },\n { right: DataSubjectRight.RECTIFICATION, provision: `${law} Art. 16`, purposes: every },\n { right: DataSubjectRight.ERASURE, provision: `${law} Art. 17`, purposes: every },\n { right: DataSubjectRight.RESTRICTION, provision: `${law} Art. 18`, purposes: every },\n { right: DataSubjectRight.PORTABILITY, provision: `${law} Art. 20(1)`, purposes: where([LawfulBasis.CONSENT, LawfulBasis.CONTRACT]) },\n { right: DataSubjectRight.OBJECTION, provision: `${law} Art. 21(1)`, purposes: where([LawfulBasis.PUBLIC_TASK, LawfulBasis.LEGITIMATE_INTERESTS]) },\n { right: DataSubjectRight.WITHDRAW_CONSENT, provision: `${law} Art. 7(3)`, purposes: where([LawfulBasis.CONSENT]) },\n ...complaintRights(regime, every),\n ];\n return rights.filter((entry) => entry.purposes.length > 0);\n}\n\n/** The complaint rights a regime grants — where it differs from its neighbour, which is why it is its own switch. */\nfunction complaintRights(regime: DataProtectionRegime, every: string[]): ApplicableDataSubjectRight[] {\n switch (regime) {\n case DataProtectionRegime.EU_GDPR:\n return [{ right: DataSubjectRight.LODGE_COMPLAINT, provision: 'GDPR Art. 77(1)', purposes: every }];\n case DataProtectionRegime.UK_GDPR:\n return [\n { right: DataSubjectRight.COMPLAIN_TO_CONTROLLER, provision: 'Data Protection Act 2018 s.164A', purposes: every },\n { right: DataSubjectRight.LODGE_COMPLAINT, provision: 'Data Protection Act 2018 s.165(2)', purposes: every },\n ];\n }\n}\n\n/**\n * Where a person may complain under a regime, as a notice states it.\n *\n * The regime fixes the route; the operator chooses nothing here, which is why no authority is NAMED. Under\n * the GDPR a person may complain to the authority of their own member state (Art. 77(1)) whichever authority\n * leads for the operator, so naming only the operator's lead authority would understate the route.\n */\nexport function complaintRouteUnderRegime(regime: DataProtectionRegime): string {\n switch (regime) {\n case DataProtectionRegime.EU_GDPR:\n return 'a supervisory authority, in particular in the member state of habitual residence, place of work or place of the alleged infringement (GDPR Art. 77(1))';\n case DataProtectionRegime.UK_GDPR:\n return 'the operator itself, which must acknowledge the complaint within 30 days and tell you its outcome (Data Protection Act 2018 s.164A), and the Information Commissioner (s.165(2))';\n }\n}\n\n/** Who answers a data-subject request about one population of data. */\nexport enum SubjectRequestResponder {\n /** The operator is the controller of this data and answers the request itself. */\n OPERATOR = 'OPERATOR',\n /**\n * The operator is a PROCESSOR here: the customer that controls the data answers, and the operator forwards the\n * request and assists (GDPR Art. 28(3)(e)). A notice saying the operator will answer would promise a decision\n * the operator has no authority to make over its customer's records.\n */\n CUSTOMER_CONTROLLER = 'CUSTOMER_CONTROLLER',\n}\n\n/**\n * Who answers, for a role the operator holds over a population. `undefined` for a joint controllership, whose\n * arrangement decides it and is not declared anywhere a function can read.\n */\nexport function subjectRequestResponderFor(role: OperatorProcessingRole): SubjectRequestResponder | undefined {\n switch (role) {\n case OperatorProcessingRole.CONTROLLER:\n return SubjectRequestResponder.OPERATOR;\n case OperatorProcessingRole.PROCESSOR:\n return SubjectRequestResponder.CUSTOMER_CONTROLLER;\n case OperatorProcessingRole.JOINT_CONTROLLER:\n return undefined;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonalization-scrub.shared.utils.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"impersonalization-scrub.shared.utils.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/impersonalization-scrub.shared.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,qDAAa,CAAC;AAEtD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,CAAC,CAAC,UAAU,GAAG,MAAM,CAE/E;AAED;;;;;;;;;;GAUG;AACH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAoEpG;AAED,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAM9E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iCAAiC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,SAAS,MAAM,EAAE,CAS7F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA8C9F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonalization-scrub.shared.utils.js","sourceRoot":"","sources":["../../../../../src/compliance/privacy/impersonalization-scrub.shared.utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { getDataCategories, getImpersonalizeMaskValue, getImpersonalizeTreatment, getMergedObjectOrUnionShape } from '@wildo-ai/zod-decorators';\nimport { RedactionType } from './redaction.shared.schemas';\nimport { FIELD_IDENTIFIER_TO_PRIMARY_SCOPE, ResourcePrimaryScope } from '../../resources/resources.shared.schemas';\n\n/**\n * The DEFAULT mask applied for `RedactionType.MASK`.\n *\n * It is an UNCONSTRAINED string, so a field whose schema constrains its shape — `z.email()`,\n * `z.uuid()`, `.min(n)` — cannot hold it. Such a field declares its own value via\n * `.impersonalizeWith(MASK, { maskValue })`; see {@link resolveImpersonalizeMaskValue}.\n */\nexport const IMPERSONALIZE_MASK_CONSTANT = '••••••••';\n\n/**\n * The value a `MASK` treatment actually writes for one field: the field's own override when it\n * declares one, the framework constant otherwise.\n *\n * ONE authority, deliberately. The boot guard `safeParse`s exactly this value against the field's\n * schema and the scrub writer `$set`s exactly this value — so a guard that passes at boot cannot be\n * followed by a write the update DTO rejects inside the erasure transaction. Splitting the two\n * would reintroduce precisely the failure mode the boot guard exists to eliminate.\n */\nexport function resolveImpersonalizeMaskValue(fieldSchema: z.ZodTypeAny): string {\n return getImpersonalizeMaskValue(fieldSchema) ?? IMPERSONALIZE_MASK_CONSTANT;\n}\n\n/**\n * The impersonalization NEVER-SCRUB FLOOR: the org/app SCOPE FKs + `createdByUserId`. Nulling these\n * would orphan the retained row from its tenant (a cross-tenant / security regression) or lose its\n * audit provenance, so they stay protected even if an author accidentally puts a treatment on them.\n *\n * The PERSON-LINK (`userId` / `anonymousUserId` — the USER_SELF / ANONYMOUS scopes) is DELIBERATELY NOT\n * floor-protected: D1 allows SEVERING the person-link while keeping org/app scope (the mirror, opposite\n * direction, of the anon→user transposition). So a `userId` that carries an explicit\n * `.impersonalizeWith('remove')` IS severable — this is how \"erase the subject's link, keep the scoped\n * record\" is expressed.\n */\n/**\n * The value a `RESET` field becomes: its OWN schema default.\n *\n * Resolved by asking the schema, never by an authored constant. `parse(undefined)` is exactly the\n * question \"what is this field when nobody has set it\", answered by Zod's own semantics — so the\n * default lives in ONE place and a later change to it moves the scrub with it. An authored copy would\n * drift, and a scrub writing a stale default is a row that looks reset and is not.\n *\n * Refuses a field with NO default rather than inventing one. `RESET` on such a field is an authoring\n * error — `undefined` would either fail the re-parse or leave the value untouched depending on the\n * writer, and both are worse than a loud refusal at config time. REMOVE is what that field wants.\n *\n * The result must still SATISFY the schema, which is the whole failure this treatment exists to\n * prevent: a patch writing a value the schema rejects surfaces as a read error long after the erasure\n * reported success. `parse` gives that for free — a default that does not validate cannot be returned.\n */\nexport function resolveImpersonalizeResetValue(fieldSchema: z.ZodTypeAny, fieldName: string): unknown {\n const parsed = fieldSchema.safeParse(undefined);\n if (!parsed.success) {\n throw new Error(\n `[impersonalize] RESET treatment on '${fieldName}' requires the field to declare a .default(), and it does not. ` +\n `RESET means \"return this field to what it is when nobody has set it\", which has no answer here. ` +\n `Use REMOVE for a field that may be absent, or add the default the treatment is asking for.`,\n );\n }\n\n /*\n * A CLOCK-READ default is refused, and this is the sharp edge of the whole treatment.\n *\n * `.default(() => new Date())` means \"compute a fresh value at write time\". Applied to\n * `lastActiveAt` — a real field, declared USAGE personal data — RESET wrote the ERASURE's own\n * timestamp, recording an erased person as last active at the moment they were erased. Measured\n * before this guard: the value landed within a millisecond of `now`. That is worse than leaving the\n * field alone. It does not fail to remove information, it FABRICATES it, and the fabricated value is\n * exactly the kind a reader would trust.\n *\n * ## Why this is a heuristic, and why the obvious checks do not work\n *\n * Zod 4 exposes `defaultValue` as a GETTER returning the resolved value, so a literal and a thunk are\n * statically indistinguishable — measured, both report `typeof object`. And resolving twice does not\n * separate them either: two `new Date()` reads microseconds apart stringify identically, so a\n * difference-based check silently passes the exact case it exists for. That version was written,\n * tested, and failed to fire.\n *\n * What IS distinguishable is the value's relationship to the clock. A default resolving to a Date\n * near `now` can only have come from reading the clock — whether from a thunk, or from a literal\n * `.default(new Date())` evaluated at module load, which is equally wrong and equally invisible.\n *\n * A deliberate sentinel is never \"recently\". `new Date(0)` is 1970; an explicit epoch or a fixed\n * historical date is years away. So the bound below admits every deliberate choice and refuses every\n * clock read, and it is stated as a bound rather than pretending to be exact.\n */\n /*\n * `.optional()` PARSES `undefined` successfully, so the check above passes it and the resolver would\n * return `undefined` — which is not a scrub. The patch would `$set` an undefined, which either\n * no-ops or is rejected downstream by the canonicalizer, and either way the personal data survives\n * an erasure that reported success.\n *\n * The distinction the two checks draw together: \"has no default at all\" and \"is optional so its\n * default IS undefined\" are different authoring mistakes, and both mean RESET has no value to write.\n * REMOVE is what an optional field wants — it writes an explicit null, which is a scrub.\n */\n if (parsed.data === undefined) {\n throw new Error(\n `[impersonalize] RESET treatment on '${fieldName}' resolves to \\`undefined\\` — the field is optional rather ` +\n `than defaulted, so \"what it is when nobody has set it\" is nothing at all. Writing that is not a scrub: the ` +\n `patch would set undefined and the personal data would survive. Use REMOVE, which writes an explicit null, ` +\n `or give the field the .default() RESET is asking for.`,\n );\n }\n\n const RESET_CLOCK_READ_WINDOW_MS = 24 * 60 * 60 * 1000;\n if (parsed.data instanceof Date && Math.abs(Date.now() - parsed.data.getTime()) < RESET_CLOCK_READ_WINDOW_MS) {\n throw new Error(\n `[impersonalize] RESET treatment on '${fieldName}' resolves to a timestamp within a day of NOW, which means ` +\n `the default reads the clock (typically \\`.default(() => new Date())\\`, or a literal \\`new Date()\\` evaluated ` +\n `at module load). Erasure would then write a value generated BY the erasure — a field like 'lastActiveAt' ` +\n `would record the erased person as active at the moment they were erased, fabricating information rather ` +\n `than removing it. Give the field a STATIC neutral default such as new Date(0), which asserts \"no recorded ` +\n `value\", or make it nullable and use REMOVE, which asserts \"unknown\". Those are different claims about an ` +\n `erased person, so choose deliberately.`,\n );\n }\n return parsed.data;\n}\n\nexport function isImpersonalizeNeverScrubFloorField(fieldName: string): boolean {\n if (fieldName === 'createdByUserId') return true;\n const scope = FIELD_IDENTIFIER_TO_PRIMARY_SCOPE[fieldName];\n return scope === ResourcePrimaryScope.ORGANIZATIONS\n || scope === ResourcePrimaryScope.APPLICATION;\n // USER_SELF / ANONYMOUS (person-link) fall through → severable per D1.\n}\n\n/**\n * The fields whose declarations say this resource holds personal data — the evidence against a\n * `RETAIN_ONLY` claim.\n *\n * ## Why this exists\n *\n * `RETAIN_ONLY` asserts a resource holds NO personal data of its own, and the factory could check that\n * in only one direction: it refuses the mode when a field carries an impersonalize TREATMENT. It could\n * not see personal data that nobody had given a treatment to. So the cheap answer for most resources\n * was also the one that failed silently when wrong — a governed document stating that erasure leaves\n * nothing behind, about rows holding a person's data. The opposite mode never had this hole:\n * `RETAIN_AND_IMPERSONALIZE` is refused when nothing would be scrubbed.\n *\n * `.dataCategories()` is the declaration this reads, so the check catches a CONTRADICTION — a resource\n * that says both \"this field is personal data\" and \"this resource holds none\". It cannot catch an\n * OMISSION, where nothing was ever classified; that is a coverage question and belongs to the category\n * inventory, not here. Saying so matters: a clean result is not a proof that a resource holds nothing.\n *\n * ## Read the RESOLVED shape, never the source text\n *\n * `getMergedObjectOrUnionShape` is used deliberately, for the same reason the scrub builder below uses\n * it. A text-shaped read of a named schema misses both shapes that occur here in practice: a schema\n * that `.extend()`s a base carries its categories on the BASE, and one file commonly declares several\n * schemas so a range scan closes on a nested object. A census built that way reported `users` as\n * holding no personal data, while `users.email` carries `CONTACT_DETAILS` — understating personal data,\n * which is the dangerous direction for a check whose whole job is to refuse a false negative claim.\n *\n * The never-scrub floor is excluded on the same terms as the scrub patch: a scope FK or\n * `createdByUserId` links a row to a person without being personal data the row holds, and every mode\n * preserves it — so its presence is no evidence against `RETAIN_ONLY`.\n */\nexport function collectDeclaredPersonalDataFields(mainSchema: z.ZodTypeAny): readonly string[] {\n const shape = getMergedObjectOrUnionShape(mainSchema);\n const declared: string[] = [];\n for (const [fieldName, fieldSchema] of Object.entries(shape)) {\n if (isImpersonalizeNeverScrubFloorField(fieldName)) continue;\n const categories = getDataCategories(fieldSchema as z.ZodTypeAny);\n if (categories !== undefined && categories.length > 0) declared.push(fieldName);\n }\n return declared;\n}\n\n/**\n * Synthesize the field-scrub `$set` patch for an impersonalize-in-place write, from a resource's\n * per-field `.impersonalizeWith()` treatments. Returns ONLY the scrubbed FIELDS — the impersonalize\n * writer appends the `retentionStatus` / `impersonalizedAt` markers.\n *\n * M4 is the FIRST + ONLY exhaustive consumer of `RedactionType` (zero appliers existed before), so the\n * `default` arm is load-bearing: it keeps the enum ADDITIVELY safe — a future member (e.g. a reserved\n * `TOKENIZE`) fails LOUD here rather than being silently skipped.\n *\n * v1 scope: KEEP / REMOVE / MASK are expressible in a single STATIC `$set` (batch `updateManyAsSystem`).\n * A per-field `maskValue` stays inside that scope — it changes WHICH constant a field is set to, not\n * that the write is one static `$set` shared by every row in the batch.\n * - `HASH` is value-dependent (each row hashes its own value) → NOT expressible in a static `$set`; it\n * THROWS in v1 (add a per-doc / aggregation-pipeline scrub path later — additive).\n * - `ENCRYPT` is reversible → forbidden for impersonalization (D6: v1 impersonalization is IRREVERSIBLE);\n * `ENCRYPT` remains a flow-actors-only redaction option.\n */\nexport function buildImpersonalizeScrubPatch(mainSchema: z.ZodTypeAny): Record<string, unknown> {\n // UNION-AWARE on purpose. `getZodObjectShape` returns `{}` for a discriminated union, which would\n // make the scrub a SILENT NO-OP the day polymorphic resources become retention-governed (rows would\n // flip to RETAINED with every personal field intact). This mirrors the union-aware shape read used\n // by `deriveTrustedSystemWritePreservedFields`, so the two never disagree about what a resource's\n // fields are.\n const shape = getMergedObjectOrUnionShape(mainSchema);\n const patch: Record<string, unknown> = {};\n\n for (const [fieldName, fieldSchema] of Object.entries(shape)) {\n const treatment = getImpersonalizeTreatment(fieldSchema as z.ZodTypeAny);\n if (treatment === undefined) continue; // no `.impersonalizeWith()` → leave the field untouched\n\n // Never-scrub floor: even an explicit treatment cannot null a scope FK / createdByUserId.\n if (isImpersonalizeNeverScrubFloorField(fieldName)) continue;\n\n switch (treatment as RedactionType) {\n case RedactionType.KEEP:\n continue; // explicit never-scrub\n case RedactionType.REMOVE:\n patch[fieldName] = null;\n break;\n case RedactionType.MASK:\n patch[fieldName] = resolveImpersonalizeMaskValue(fieldSchema as z.ZodTypeAny);\n break;\n case RedactionType.RESET:\n patch[fieldName] = resolveImpersonalizeResetValue(fieldSchema as z.ZodTypeAny, fieldName);\n break;\n case RedactionType.HASH:\n throw new Error(\n `[impersonalize] HASH treatment on '${fieldName}' is value-dependent and not supported in v1 ` +\n `(a static $set cannot hash per-row) — use REMOVE/MASK/KEEP, or add the per-doc/pipeline scrub path.`,\n );\n case RedactionType.ENCRYPT:\n throw new Error(\n `[impersonalize] ENCRYPT treatment on '${fieldName}' is reversible — forbidden for impersonalization ` +\n `(D6: v1 impersonalization is irreversible). ENCRYPT stays a flow-actors-only redaction option.`,\n );\n default:\n // Exhaustive guard: an unknown / future RedactionType member MUST fail LOUD, never be silently\n // skipped — this is exactly what keeps RedactionType additively safe (deep-review B-F2).\n throw new Error(`[impersonalize] unsupported impersonalize treatment '${treatment}' on '${fieldName}'.`);\n }\n }\n\n return patch;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"impersonalization-scrub.shared.utils.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/impersonalization-scrub.shared.utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { getDataCategories, getImpersonalizeMaskValue, getImpersonalizeTreatment, getMergedObjectOrUnionShape } from '@wildo-ai/zod-decorators';\nimport { RedactionType } from './redaction.shared.schemas';\nimport { FIELD_IDENTIFIER_TO_PRIMARY_SCOPE, ResourcePrimaryScope } from '../../resources/resources.shared.schemas';\n\n/**\n * The DEFAULT mask applied for `RedactionType.MASK`.\n *\n * It is an UNCONSTRAINED string, so a field whose schema constrains its shape — `z.email()`,\n * `z.uuid()`, `.min(n)` — cannot hold it. Such a field declares its own value via\n * `.impersonalizeWith(MASK, { maskValue })`; see {@link resolveImpersonalizeMaskValue}.\n */\nexport const IMPERSONALIZE_MASK_CONSTANT = '••••••••';\n\n/**\n * The value a `MASK` treatment actually writes for one field: the field's own override when it\n * declares one, the framework constant otherwise.\n *\n * ONE authority, deliberately. The boot guard `safeParse`s exactly this value against the field's\n * schema and the scrub writer `$set`s exactly this value — so a guard that passes at boot cannot be\n * followed by a write the update DTO rejects inside the erasure transaction. Splitting the two\n * would reintroduce precisely the failure mode the boot guard exists to eliminate.\n */\nexport function resolveImpersonalizeMaskValue(fieldSchema: z.ZodTypeAny): string {\n return getImpersonalizeMaskValue(fieldSchema) ?? IMPERSONALIZE_MASK_CONSTANT;\n}\n\n/**\n * The impersonalization NEVER-SCRUB FLOOR: the org/app SCOPE FKs + `createdByUserId`. Nulling these\n * would orphan the retained row from its tenant (a cross-tenant / security regression) or lose its\n * audit provenance, so they stay protected even if an author accidentally puts a treatment on them.\n *\n * The PERSON-LINK (`userId` / `anonymousUserId` — the USER_SELF / ANONYMOUS scopes) is DELIBERATELY NOT\n * floor-protected: D1 allows SEVERING the person-link while keeping org/app scope (the mirror, opposite\n * direction, of the anon→user transposition). So a `userId` that carries an explicit\n * `.impersonalizeWith('remove')` IS severable — this is how \"erase the subject's link, keep the scoped\n * record\" is expressed.\n */\n/**\n * The value a `RESET` field becomes: its OWN schema default.\n *\n * Resolved by asking the schema, never by an authored constant. `parse(undefined)` is exactly the\n * question \"what is this field when nobody has set it\", answered by Zod's own semantics — so the\n * default lives in ONE place and a later change to it moves the scrub with it. An authored copy would\n * drift, and a scrub writing a stale default is a row that looks reset and is not.\n *\n * Refuses a field with NO default rather than inventing one. `RESET` on such a field is an authoring\n * error — `undefined` would either fail the re-parse or leave the value untouched depending on the\n * writer, and both are worse than a loud refusal at config time. REMOVE is what that field wants.\n *\n * The result must still SATISFY the schema, which is the whole failure this treatment exists to\n * prevent: a patch writing a value the schema rejects surfaces as a read error long after the erasure\n * reported success. `parse` gives that for free — a default that does not validate cannot be returned.\n */\nexport function resolveImpersonalizeResetValue(fieldSchema: z.ZodTypeAny, fieldName: string): unknown {\n const parsed = fieldSchema.safeParse(undefined);\n if (!parsed.success) {\n throw new Error(\n `[impersonalize] RESET treatment on '${fieldName}' requires the field to declare a .default(), and it does not. ` +\n `RESET means \"return this field to what it is when nobody has set it\", which has no answer here. ` +\n `Use REMOVE for a field that may be absent, or add the default the treatment is asking for.`,\n );\n }\n\n /*\n * A CLOCK-READ default is refused, and this is the sharp edge of the whole treatment.\n *\n * `.default(() => new Date())` means \"compute a fresh value at write time\". Applied to\n * `lastActiveAt` — a real field, declared USAGE personal data — RESET wrote the ERASURE's own\n * timestamp, recording an erased person as last active at the moment they were erased. Measured\n * before this guard: the value landed within a millisecond of `now`. That is worse than leaving the\n * field alone. It does not fail to remove information, it FABRICATES it, and the fabricated value is\n * exactly the kind a reader would trust.\n *\n * ## Why this is a heuristic, and why the obvious checks do not work\n *\n * Zod 4 exposes `defaultValue` as a GETTER returning the resolved value, so a literal and a thunk are\n * statically indistinguishable — measured, both report `typeof object`. And resolving twice does not\n * separate them either: two `new Date()` reads microseconds apart stringify identically, so a\n * difference-based check silently passes the exact case it exists for. That version was written,\n * tested, and failed to fire.\n *\n * What IS distinguishable is the value's relationship to the clock. A default resolving to a Date\n * near `now` can only have come from reading the clock — whether from a thunk, or from a literal\n * `.default(new Date())` evaluated at module load, which is equally wrong and equally invisible.\n *\n * A deliberate sentinel is never \"recently\". `new Date(0)` is 1970; an explicit epoch or a fixed\n * historical date is years away. So the bound below admits every deliberate choice and refuses every\n * clock read, and it is stated as a bound rather than pretending to be exact.\n */\n /*\n * `.optional()` PARSES `undefined` successfully, so the check above passes it and the resolver would\n * return `undefined` — which is not a scrub. The patch would `$set` an undefined, which either\n * no-ops or is rejected downstream by the canonicalizer, and either way the personal data survives\n * an erasure that reported success.\n *\n * The distinction the two checks draw together: \"has no default at all\" and \"is optional so its\n * default IS undefined\" are different authoring mistakes, and both mean RESET has no value to write.\n * REMOVE is what an optional field wants — it writes an explicit null, which is a scrub.\n */\n if (parsed.data === undefined) {\n throw new Error(\n `[impersonalize] RESET treatment on '${fieldName}' resolves to \\`undefined\\` — the field is optional rather ` +\n `than defaulted, so \"what it is when nobody has set it\" is nothing at all. Writing that is not a scrub: the ` +\n `patch would set undefined and the personal data would survive. Use REMOVE, which writes an explicit null, ` +\n `or give the field the .default() RESET is asking for.`,\n );\n }\n\n const RESET_CLOCK_READ_WINDOW_MS = 24 * 60 * 60 * 1000;\n if (parsed.data instanceof Date && Math.abs(Date.now() - parsed.data.getTime()) < RESET_CLOCK_READ_WINDOW_MS) {\n throw new Error(\n `[impersonalize] RESET treatment on '${fieldName}' resolves to a timestamp within a day of NOW, which means ` +\n `the default reads the clock (typically \\`.default(() => new Date())\\`, or a literal \\`new Date()\\` evaluated ` +\n `at module load). Erasure would then write a value generated BY the erasure — a field like 'lastActiveAt' ` +\n `would record the erased person as active at the moment they were erased, fabricating information rather ` +\n `than removing it. Give the field a STATIC neutral default such as new Date(0), which asserts \"no recorded ` +\n `value\", or make it nullable and use REMOVE, which asserts \"unknown\". Those are different claims about an ` +\n `erased person, so choose deliberately.`,\n );\n }\n return parsed.data;\n}\n\nexport function isImpersonalizeNeverScrubFloorField(fieldName: string): boolean {\n if (fieldName === 'createdByUserId') return true;\n const scope = FIELD_IDENTIFIER_TO_PRIMARY_SCOPE[fieldName];\n return scope === ResourcePrimaryScope.ORGANIZATIONS\n || scope === ResourcePrimaryScope.APPLICATION;\n // USER_SELF / ANONYMOUS (person-link) fall through → severable per D1.\n}\n\n/**\n * The fields whose declarations say this resource holds personal data — the evidence against a\n * `RETAIN_ONLY` claim.\n *\n * ## Why this exists\n *\n * `RETAIN_ONLY` asserts a resource holds NO personal data of its own, and the factory could check that\n * in only one direction: it refuses the mode when a field carries an impersonalize TREATMENT. It could\n * not see personal data that nobody had given a treatment to. So the cheap answer for most resources\n * was also the one that failed silently when wrong — a governed document stating that erasure leaves\n * nothing behind, about rows holding a person's data. The opposite mode never had this hole:\n * `RETAIN_AND_IMPERSONALIZE` is refused when nothing would be scrubbed.\n *\n * `.dataCategories()` is the declaration this reads, so the check catches a CONTRADICTION — a resource\n * that says both \"this field is personal data\" and \"this resource holds none\". It cannot catch an\n * OMISSION, where nothing was ever classified; that is a coverage question and belongs to the category\n * inventory, not here. Saying so matters: a clean result is not a proof that a resource holds nothing.\n *\n * ## Read the RESOLVED shape, never the source text\n *\n * `getMergedObjectOrUnionShape` is used deliberately, for the same reason the scrub builder below uses\n * it. A text-shaped read of a named schema misses both shapes that occur here in practice: a schema\n * that `.extend()`s a base carries its categories on the BASE, and one file commonly declares several\n * schemas so a range scan closes on a nested object. A census built that way reported `users` as\n * holding no personal data, while `users.email` carries `CONTACT_DETAILS` — understating personal data,\n * which is the dangerous direction for a check whose whole job is to refuse a false negative claim.\n *\n * The never-scrub floor is excluded on the same terms as the scrub patch: a scope FK or\n * `createdByUserId` links a row to a person without being personal data the row holds, and every mode\n * preserves it — so its presence is no evidence against `RETAIN_ONLY`.\n */\nexport function collectDeclaredPersonalDataFields(mainSchema: z.ZodTypeAny): readonly string[] {\n const shape = getMergedObjectOrUnionShape(mainSchema);\n const declared: string[] = [];\n for (const [fieldName, fieldSchema] of Object.entries(shape)) {\n if (isImpersonalizeNeverScrubFloorField(fieldName)) continue;\n const categories = getDataCategories(fieldSchema as z.ZodTypeAny);\n if (categories !== undefined && categories.length > 0) declared.push(fieldName);\n }\n return declared;\n}\n\n/**\n * Synthesize the field-scrub `$set` patch for an impersonalize-in-place write, from a resource's\n * per-field `.impersonalizeWith()` treatments. Returns ONLY the scrubbed FIELDS — the impersonalize\n * writer appends the `retentionStatus` / `impersonalizedAt` markers.\n *\n * M4 is the FIRST + ONLY exhaustive consumer of `RedactionType` (zero appliers existed before), so the\n * `default` arm is load-bearing: it keeps the enum ADDITIVELY safe — a future member (e.g. a reserved\n * `TOKENIZE`) fails LOUD here rather than being silently skipped.\n *\n * v1 scope: KEEP / REMOVE / MASK are expressible in a single STATIC `$set` (batch `updateManyAsSystem`).\n * A per-field `maskValue` stays inside that scope — it changes WHICH constant a field is set to, not\n * that the write is one static `$set` shared by every row in the batch.\n * - `HASH` is value-dependent (each row hashes its own value) → NOT expressible in a static `$set`; it\n * THROWS in v1 (add a per-doc / aggregation-pipeline scrub path later — additive).\n * - `ENCRYPT` is reversible → forbidden for impersonalization (D6: v1 impersonalization is IRREVERSIBLE);\n * `ENCRYPT` remains a flow-actors-only redaction option.\n */\nexport function buildImpersonalizeScrubPatch(mainSchema: z.ZodTypeAny): Record<string, unknown> {\n // UNION-AWARE on purpose. `getZodObjectShape` returns `{}` for a discriminated union, which would\n // make the scrub a SILENT NO-OP the day polymorphic resources become retention-governed (rows would\n // flip to RETAINED with every personal field intact). This mirrors the union-aware shape read used\n // by `deriveTrustedSystemWritePreservedFields`, so the two never disagree about what a resource's\n // fields are.\n const shape = getMergedObjectOrUnionShape(mainSchema);\n const patch: Record<string, unknown> = {};\n\n for (const [fieldName, fieldSchema] of Object.entries(shape)) {\n const treatment = getImpersonalizeTreatment(fieldSchema as z.ZodTypeAny);\n if (treatment === undefined) continue; // no `.impersonalizeWith()` → leave the field untouched\n\n // Never-scrub floor: even an explicit treatment cannot null a scope FK / createdByUserId.\n if (isImpersonalizeNeverScrubFloorField(fieldName)) continue;\n\n switch (treatment as RedactionType) {\n case RedactionType.KEEP:\n continue; // explicit never-scrub\n case RedactionType.REMOVE:\n patch[fieldName] = null;\n break;\n case RedactionType.MASK:\n patch[fieldName] = resolveImpersonalizeMaskValue(fieldSchema as z.ZodTypeAny);\n break;\n case RedactionType.RESET:\n patch[fieldName] = resolveImpersonalizeResetValue(fieldSchema as z.ZodTypeAny, fieldName);\n break;\n case RedactionType.HASH:\n throw new Error(\n `[impersonalize] HASH treatment on '${fieldName}' is value-dependent and not supported in v1 ` +\n `(a static $set cannot hash per-row) — use REMOVE/MASK/KEEP, or add the per-doc/pipeline scrub path.`,\n );\n case RedactionType.ENCRYPT:\n throw new Error(\n `[impersonalize] ENCRYPT treatment on '${fieldName}' is reversible — forbidden for impersonalization ` +\n `(D6: v1 impersonalization is irreversible). ENCRYPT stays a flow-actors-only redaction option.`,\n );\n default:\n // Exhaustive guard: an unknown / future RedactionType member MUST fail LOUD, never be silently\n // skipped — this is exactly what keeps RedactionType additively safe (deep-review B-F2).\n throw new Error(`[impersonalize] unsupported impersonalize treatment '${treatment}' on '${fieldName}'.`);\n }\n }\n\n return patch;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonalization.shared.schemas.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"impersonalization.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/impersonalization.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,oBAAY,eAAe;IACzB,sDAAsD;IACtD,MAAM,WAAW;IACjB;;;;;;;;;;;;;OAaG;IACH,QAAQ,aAAa;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,eAAe,CAC3C,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AACH,oBAAY,oBAAoB;IAC9B;;;;;;OAMG;IACH,WAAW,gBAAgB;IAC3B;;;;;;OAMG;IACH,wBAAwB,6BAA6B;CACtD;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,oBAAoB,CAChD,CAAC;AAE/B,8HAA8H;AAC9H;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,oBAAY,wBAAwB;IAClC,oGAAoG;IACpG,gBAAgB,qBAAqB;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,wBAAwB,CACpD,CAAC;AACnC,4EAA4E;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,oBAAY,uBAAuB;IACjC;;;;;;;;;;;;;;;;;;OAkBG;IACH,YAAY,iBAAiB;IAC7B;;;;;;;;;OASG;IACH,cAAc,mBAAmB;IACjC;;;;;;;;;;OAUG;IACH,gBAAgB,qBAAqB;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,uBAAuB,CACnD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonalization.shared.schemas.js","sourceRoot":"","sources":["../../../../../src/compliance/privacy/impersonalization.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAN,IAAY,eAkBX;AAlBD,WAAY,eAAe;IACzB,sDAAsD;IACtD,oCAAiB,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,wCAAqB,CAAA;AACvB,CAAC,EAlBW,eAAe,KAAf,eAAe,QAkB1B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAChC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAN,IAAY,oBAiBX;AAjBD,WAAY,oBAAoB;IAC9B;;;;;;OAMG;IACH,mDAA2B,CAAA;IAC3B;;;;;;OAMG;IACH,6EAAqD,CAAA;AACvD,CAAC,EAjBW,oBAAoB,KAApB,oBAAoB,QAiB/B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACrC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAE/B,8HAA8H;AAC9H;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAN,IAAY,wBAGX;AAHD,WAAY,wBAAwB;IAClC,oGAAoG;IACpG,iEAAqC,CAAA;AACvC,CAAC,EAHW,wBAAwB,KAAxB,wBAAwB,QAGnC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,8BAA8B,GACzC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AACnC,4EAA4E;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,CAAN,IAAY,uBA4CX;AA5CD,WAAY,uBAAuB;IACjC;;;;;;;;;;;;;;;;;;OAkBG;IACH,wDAA6B,CAAA;IAC7B;;;;;;;;;OASG;IACH,4DAAiC,CAAA;IACjC;;;;;;;;;;OAUG;IACH,gEAAqC,CAAA;AACvC,CAAC,EA5CW,uBAAuB,KAAvB,uBAAuB,QA4ClC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GACxC,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC","sourcesContent":["import { z } from 'zod';\n\n/**\n * # Impersonalization — per-record retention lifecycle state\n *\n * `impersonalization` = scrubbing the personal data OUT of a stored record while\n * KEEPING the row, so it can be retained for a legal/audit obligation (GDPR\n * Art. 17(3)(b) legal-obligation carve-out; tax/SOX retention). This is the third\n * erasure outcome alongside hard-delete and leave-as-is.\n *\n * ⚠️ **Not** the anonymous-user concept. `isAnonymizable` / `anonymousUserId` /\n * anonymous-session ownership transposition is an unrelated, opposite-direction\n * mechanism (carrying a pre-auth anonymous session's rows forward to a real user).\n * Never conflate the two. See `.claude/plans/retention-impersonalization-architecture.md`.\n *\n * `RetentionStatus` is the per-record marker the resource factory injects (as the\n * `retentionStatus` field) onto any resource that opts into `retentionPolicy`. The\n * INTENDED contract for a `RETAINED` record is **hidden and immutable by default**\n * (behave-as-deleted), reachable only through the audited `seeRetained` see-through path.\n *\n * **LIVE.** The factory injects the marker (defaulting to `ACTIVE`), the visibility/immutability\n * enforcement and the audited see-through read primitive are all wired and runtime-proven. A\n * `RETAINED` record is hidden from every ordinary read, list, count and chart aggregate, and is\n * immutable to ordinary writes. (This block previously said the enforcement was \"wired in a later\n * phase\"; that became false without being revisited.)\n */\nexport enum RetentionStatus {\n /** Live record — normal visibility and mutability. */\n ACTIVE = 'active',\n /**\n * Impersonalized-and-retained — personal fields scrubbed in place, the row kept for a\n * retention obligation: hidden and immutable to normal callers, readable only via the audited\n * `seeRetained` see-through path, disposable only by a privileged system op.\n *\n * ENFORCED, not intended. This said \"enforcement wired in a later phase\" long after the phase\n * landed, which is worth correcting rather than deleting: a reader deciding whether to trust the\n * marker would have concluded the row was still visible. The rule has one semantic authority —\n * `compliance/privacy/retention-hide-predicate.backend` — consumed by both persistence adapters,\n * the aggregation/charts surface and RAG retrieval, and a guard test fails the suite if any site\n * hand-writes the predicate again. That single-authority shape exists because the duplicated\n * version produced two recovered defects: retained rows still counted in every chart, and the\n * Mongo/Postgres compilers silently disagreed about which rows a NULL marker selected.\n */\n RETAINED = 'retained',\n}\n\n/**\n * Zod schema for {@link RetentionStatus}. Explicitly annotated for the\n * `isolatedDeclarations` emit constraint.\n */\nexport const RetentionStatusSchema: z.ZodEnum<typeof RetentionStatus> =\n z.enum(RetentionStatus);\n\n/**\n * # What erasure DOES to a retention-governed row\n *\n * Retention (the row survives, is marked `RETAINED`, becomes hidden + immutable) and\n * impersonalization (its personal FIELDS are scrubbed) are ORTHOGONAL. A record can be legally\n * retainable while holding no personal data of its own — a financial row that merely POINTS at a\n * person is the canonical case: erasing the subject must not destroy the invoice, but there is\n * nothing on the invoice to scrub, because the name and address live on the linked user.\n *\n * Fusing the two axes forced such a resource to either declare a fake scrub (shipping a record\n * stamped \"impersonalized\" that never was) or forgo retention entirely (letting the cascade destroy a\n * legally-required record). Naming the two outcomes separately removes that false choice AND makes\n * the author's claim auditable: \"this resource holds no personal data\" becomes an explicit, reviewable\n * declaration rather than something a compliance reviewer must infer from an absence of treatments.\n */\nexport enum ErasureRetentionMode {\n /**\n * Keep and FREEZE the row; scrub nothing — this resource holds no personal data of its own.\n *\n * Declaring a `.impersonalizeWith()` treatment under this mode is a contradiction and fails at\n * config build: if a field does hold personal data, the resource wants\n * {@link ErasureRetentionMode.RETAIN_AND_IMPERSONALIZE} instead.\n */\n RETAIN_ONLY = 'retain_only',\n /**\n * Keep and freeze the row AND scrub the fields marked with `.impersonalizeWith()`.\n *\n * Requires at least one field that the writer would ACTUALLY scrub (a `KEEP` treatment, or one on a\n * never-scrub floor field such as a scope FK, does not count) — otherwise the row would flip to\n * `RETAINED` with every field intact while claiming to have been impersonalized.\n */\n RETAIN_AND_IMPERSONALIZE = 'retain_and_impersonalize',\n}\n\n/**\n * Zod schema for {@link ErasureRetentionMode}. Explicitly annotated for the\n * `isolatedDeclarations` emit constraint.\n */\nexport const ErasureRetentionModeSchema: z.ZodEnum<typeof ErasureRetentionMode> =\n z.enum(ErasureRetentionMode);\n\n/** @wildo_source:part:start saas.models.privacy.statutory-retention-ground facet:layer:shared facet:audience:app-developer */\n/**\n * **WHY the law lets a row survive an erasure** — the exemption a `retentionPolicy.statutoryRetention`\n * declaration names (#1635).\n *\n * A data subject's right to erasure (GDPR Art. 17(1)) does not apply \"to the extent that processing is\n * necessary … for compliance with a legal obligation which requires processing by Union or Member State\n * law to which the controller is subject\" (Art. 17(3)(b)). Business correspondence and accounting source\n * documents carry exactly such an obligation — HGB §257 and AO §147 in Germany, Code de commerce L123-22 in\n * France — so a subject erasure keeps those rows until the statutory period ends, and RESTRICTS them in the\n * meantime: stored, and processed for nothing else (the Art. 18(2) effect, which BDSG §35(1)/(3) states\n * explicitly as the substitute for erasure).\n *\n * spec-cite: Regulation (EU) 2016/679, Art. 17(3) introductory sentence, (b) and (e), fetched from\n * gdpr-info.eu/art-17-gdpr 2026-09-27; Art. 18(2) and BDSG §35(1)/(3) as fetched and quoted in #1635.\n *\n * ## One member, on purpose\n *\n * Art. 17(3)(e) — \"for the establishment, exercise or defence of legal claims\" — is the other ground an\n * operator reaches for, and it is deliberately NOT a member. It is a property of a CASE, decided when a claim\n * arises and lifted when it ends: that is a legal hold (#1634), not a property of every row of a class. A\n * member here would let a resource declare every row permanently \"needed for legal claims\", which is the\n * standing retention the storage-limitation principle forbids. The remaining grounds of Art. 17(3) (freedom\n * of expression, public health, archiving in the public interest) have no Wildo mechanism behind them; a\n * member without one would be a claim nothing enforces.\n *\n * `z.enum` rather than a literal so a member added later reaches every consumer through this one source.\n */\nexport enum StatutoryRetentionGround {\n /** GDPR Art. 17(3)(b): the rows are kept because a statute requires the controller to keep them. */\n LEGAL_OBLIGATION = 'legal_obligation',\n}\n\n/**\n * Zod schema for {@link StatutoryRetentionGround}. Explicitly annotated for the `isolatedDeclarations`\n * emit constraint.\n */\nexport const StatutoryRetentionGroundSchema: z.ZodEnum<typeof StatutoryRetentionGround> =\n z.enum(StatutoryRetentionGround);\n/** @wildo_source:part:end saas.models.privacy.statutory-retention-ground */\n\n/**\n * **WHOSE SESSION ENDS** when a row of this resource is erased. The second axis of the erasure\n * contract, beside {@link ErasureRetentionMode} (which says what happens to the row).\n *\n * ## This axis is NOT \"is this row about a person?\" — read this before adding a member\n *\n * The two questions look like one and are not, and conflating them cost this vocabulary a member name\n * for months (see the rename note below). Wildo answers them on SEPARATE axes:\n *\n * | question | the axis that answers it |\n * |---|---|\n * | Does this resource hold personal data? | {@link ErasureRetentionMode} — `RETAIN_AND_IMPERSONALIZE` requires at least one field that would actually be scrubbed; `RETAIN_ONLY` means *\"holds no personal data of its own\"*, and a scrub treatment under it fails at config build |\n * | Can a subject-access or portability export answer for it? | `systemAccessPolicy.exportSubject` |\n * | **Whose login session must be revoked?** | **this enum** |\n *\n * A CRM contact, a sales lead, a newsletter subscriber and a patient with no portal account are all\n * **data subjects with no session**. They declare `RETAIN_AND_IMPERSONALIZE` (they hold personal data)\n * and {@link ResourceDataSubjectKind.NO_PRINCIPAL} (there is no session to end) — two independent,\n * truthful answers. Adding a fourth member here for them would make this enum a cross-product of two\n * axes, which is two fields wearing one name.\n *\n * ## Why the third member is `NO_PRINCIPAL` and not `NOT_A_DATA_SUBJECT`\n *\n * It was `NOT_A_DATA_SUBJECT` until 2026-08-28, and the name was the defect. Operationally it always\n * meant *\"revoke nobody\"* — which is exactly right for a CRM contact — while its NAME claimed the row\n * was not about a person, which is false for one. Nothing misbehaved at runtime (the single consumer,\n * `resolveScrubSessionPrincipals`, only ever asked the session question), so the cost landed entirely\n * on readers: a human, and a compliance-document generator, both read the name and would have stated\n * in a published privacy notice that the application holds no personal data in precisely the resource\n * its customers care most about.\n *\n * The industry model this now matches is unambiguous — Intercom deletes \"a user **or lead**\", HubSpot\n * GDPR-deletes a Contact by id or by email, Zendesk \"forgets\" an end-user: an account and a data\n * subject are different objects, and the erasure verb applies to both. Wildo's `eraseSubjectAsSystem`\n * already takes `(resourceType, rowIds)` with no principal, so the capability was never missing.\n *\n * ## Why this must be DECLARED and can never be inferred\n *\n * An erasure of a person must also end that person's session, or a \"deleted\" person keeps browsing on\n * a live token until it expires. The tempting shortcut is to look for a `userId`-shaped foreign key on\n * the erased row and revoke it. **That shortcut is a defect, not an optimisation.** On almost every\n * resource a user foreign key names the OWNER or the ACTOR, not the subject: Wonder Todos' `TODOS` is\n * retention-governed and carries `createdByUserId`, `assignedToUserId` and `escalationContactUserId`,\n * so an inferring implementation would log out the author, the assignee and the escalation contact —\n * three people, none of them the data subject — every time a todo was erased.\n *\n * So the linkage is authored, never guessed, and a resource that can be an erasure subject (i.e. one\n * declaring a `retentionPolicy`) must say which of these it is. Undeclared is refused at config build:\n * nobody has decided yet, and refusing is what forces the decision — the same doctrine the subject\n * EXPORT model applies to an undeclared resource.\n */\nexport enum ResourceDataSubjectKind {\n /**\n * Erasing a row of this resource revokes **no session**, because no login is reachable from it.\n *\n * Two very different populations share this answer, and the enum is deliberately silent about which\n * one a given resource is — {@link ErasureRetentionMode} says that:\n *\n * - **Not a person at all.** A todo, an invoice, a log line. Any user foreign keys it carries name\n * ACTORS — an author, an assignee, an owner, an escalation contact — and revoking their sessions\n * because a record was erased would log out three uninvolved people. Such a resource pairs this\n * with `RETAIN_ONLY`.\n * - **A person with no account.** A CRM contact, a sales lead, a subscriber, a patient with no\n * portal login. Their rows ARE personal data and carry the full weight of Arts 15–17 and 20 —\n * there is simply no session to end. Such a resource pairs this with `RETAIN_AND_IMPERSONALIZE`\n * and per-field `.impersonalizeWith()` treatments, and its subject-rights path is the ordinary\n * administrative one: `eraseSubjectAsSystem(resourceType, rowIds)` and a subject export.\n *\n * The second population is the majority of what a B2B SaaS customer stores about third parties, and\n * it is what most of a privacy notice describes. Do not read this member as \"nothing to disclose\".\n */\n NO_PRINCIPAL = 'no_principal',\n /**\n * Rows of this resource ARE the person, and the row's own id IS the session principal: erasing row\n * `X` ends the session of user `X`. This is `USERS` / `USER_SELF`.\n *\n * Note this makes EXPLICIT a revocation that is otherwise only incidental. Erasing a `USERS` row\n * already logs the user out today — but only as a side effect of the retention row-hide (the auth\n * fronts re-read the user, find the row hidden, and 401) plus the scrub write bumping\n * `authorizationVersion`. Nothing on the erasure path ever WROTE a revocation, so the guarantee\n * lived entirely in the behaviour of two unrelated mechanisms.\n */\n SELF_PRINCIPAL = 'self_principal',\n /**\n * Rows of this resource are a person whose login lives in a DIFFERENT `USERS` row — a Patient, an\n * Employee, a Member record that a human signs in as. `sessionPrincipalField` names the field\n * holding that user's id.\n *\n * The named field must carry no `.impersonalizeWith()` treatment. Not because the revocation would\n * break — the principal is resolved BEFORE the scrub, so a scrubbed field is still readable when it\n * matters — but because declaring one field to be BOTH the link to a person and personal data to\n * destroy is self-contradictory, and it leaves the retained row with no way to say whose session was\n * ended. Enforced at config build.\n */\n LINKED_PRINCIPAL = 'linked_principal',\n}\n\n/**\n * Zod schema for {@link ResourceDataSubjectKind}. Explicitly annotated for the\n * `isolatedDeclarations` emit constraint.\n */\nexport const ResourceDataSubjectKindSchema: z.ZodEnum<typeof ResourceDataSubjectKind> =\n z.enum(ResourceDataSubjectKind);\n"]}
|
|
1
|
+
{"version":3,"file":"impersonalization.shared.schemas.js","sourceRoot":"","sources":["../../../../src/compliance/privacy/impersonalization.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAN,IAAY,eAkBX;AAlBD,WAAY,eAAe;IACzB,sDAAsD;IACtD,oCAAiB,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,wCAAqB,CAAA;AACvB,CAAC,EAlBW,eAAe,KAAf,eAAe,QAkB1B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAChC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAN,IAAY,oBAiBX;AAjBD,WAAY,oBAAoB;IAC9B;;;;;;OAMG;IACH,mDAA2B,CAAA;IAC3B;;;;;;OAMG;IACH,6EAAqD,CAAA;AACvD,CAAC,EAjBW,oBAAoB,KAApB,oBAAoB,QAiB/B;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACrC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAE/B,8HAA8H;AAC9H;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAN,IAAY,wBAGX;AAHD,WAAY,wBAAwB;IAClC,oGAAoG;IACpG,iEAAqC,CAAA;AACvC,CAAC,EAHW,wBAAwB,KAAxB,wBAAwB,QAGnC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,8BAA8B,GACzC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AACnC,4EAA4E;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,CAAN,IAAY,uBA4CX;AA5CD,WAAY,uBAAuB;IACjC;;;;;;;;;;;;;;;;;;OAkBG;IACH,wDAA6B,CAAA;IAC7B;;;;;;;;;OASG;IACH,4DAAiC,CAAA;IACjC;;;;;;;;;;OAUG;IACH,gEAAqC,CAAA;AACvC,CAAC,EA5CW,uBAAuB,KAAvB,uBAAuB,QA4ClC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GACxC,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC","sourcesContent":["import { z } from 'zod';\n\n/**\n * # Impersonalization — per-record retention lifecycle state\n *\n * `impersonalization` = scrubbing the personal data OUT of a stored record while\n * KEEPING the row, so it can be retained for a legal/audit obligation (GDPR\n * Art. 17(3)(b) legal-obligation carve-out; tax/SOX retention). This is the third\n * erasure outcome alongside hard-delete and leave-as-is.\n *\n * ⚠️ **Not** the anonymous-user concept. `isAnonymizable` / `anonymousUserId` /\n * anonymous-session ownership transposition is an unrelated, opposite-direction\n * mechanism (carrying a pre-auth anonymous session's rows forward to a real user).\n * Never conflate the two. See `.claude/plans/retention-impersonalization-architecture.md`.\n *\n * `RetentionStatus` is the per-record marker the resource factory injects (as the\n * `retentionStatus` field) onto any resource that opts into `retentionPolicy`. The\n * INTENDED contract for a `RETAINED` record is **hidden and immutable by default**\n * (behave-as-deleted), reachable only through the audited `seeRetained` see-through path.\n *\n * **LIVE.** The factory injects the marker (defaulting to `ACTIVE`), the visibility/immutability\n * enforcement and the audited see-through read primitive are all wired and runtime-proven. A\n * `RETAINED` record is hidden from every ordinary read, list, count and chart aggregate, and is\n * immutable to ordinary writes. (This block previously said the enforcement was \"wired in a later\n * phase\"; that became false without being revisited.)\n */\nexport enum RetentionStatus {\n /** Live record — normal visibility and mutability. */\n ACTIVE = 'active',\n /**\n * Impersonalized-and-retained — personal fields scrubbed in place, the row kept for a\n * retention obligation: hidden and immutable to normal callers, readable only via the audited\n * `seeRetained` see-through path, disposable only by a privileged system op.\n *\n * ENFORCED, not intended. This said \"enforcement wired in a later phase\" long after the phase\n * landed, which is worth correcting rather than deleting: a reader deciding whether to trust the\n * marker would have concluded the row was still visible. The rule has one semantic authority —\n * `compliance/privacy/retention-hide-predicate.backend` — consumed by both persistence adapters,\n * the aggregation/charts surface and RAG retrieval, and a guard test fails the suite if any site\n * hand-writes the predicate again. That single-authority shape exists because the duplicated\n * version produced two recovered defects: retained rows still counted in every chart, and the\n * Mongo/Postgres compilers silently disagreed about which rows a NULL marker selected.\n */\n RETAINED = 'retained',\n}\n\n/**\n * Zod schema for {@link RetentionStatus}. Explicitly annotated for the\n * `isolatedDeclarations` emit constraint.\n */\nexport const RetentionStatusSchema: z.ZodEnum<typeof RetentionStatus> =\n z.enum(RetentionStatus);\n\n/**\n * # What erasure DOES to a retention-governed row\n *\n * Retention (the row survives, is marked `RETAINED`, becomes hidden + immutable) and\n * impersonalization (its personal FIELDS are scrubbed) are ORTHOGONAL. A record can be legally\n * retainable while holding no personal data of its own — a financial row that merely POINTS at a\n * person is the canonical case: erasing the subject must not destroy the invoice, but there is\n * nothing on the invoice to scrub, because the name and address live on the linked user.\n *\n * Fusing the two axes forced such a resource to either declare a fake scrub (shipping a record\n * stamped \"impersonalized\" that never was) or forgo retention entirely (letting the cascade destroy a\n * legally-required record). Naming the two outcomes separately removes that false choice AND makes\n * the author's claim auditable: \"this resource holds no personal data\" becomes an explicit, reviewable\n * declaration rather than something a compliance reviewer must infer from an absence of treatments.\n */\nexport enum ErasureRetentionMode {\n /**\n * Keep and FREEZE the row; scrub nothing — this resource holds no personal data of its own.\n *\n * Declaring a `.impersonalizeWith()` treatment under this mode is a contradiction and fails at\n * config build: if a field does hold personal data, the resource wants\n * {@link ErasureRetentionMode.RETAIN_AND_IMPERSONALIZE} instead.\n */\n RETAIN_ONLY = 'retain_only',\n /**\n * Keep and freeze the row AND scrub the fields marked with `.impersonalizeWith()`.\n *\n * Requires at least one field that the writer would ACTUALLY scrub (a `KEEP` treatment, or one on a\n * never-scrub floor field such as a scope FK, does not count) — otherwise the row would flip to\n * `RETAINED` with every field intact while claiming to have been impersonalized.\n */\n RETAIN_AND_IMPERSONALIZE = 'retain_and_impersonalize',\n}\n\n/**\n * Zod schema for {@link ErasureRetentionMode}. Explicitly annotated for the\n * `isolatedDeclarations` emit constraint.\n */\nexport const ErasureRetentionModeSchema: z.ZodEnum<typeof ErasureRetentionMode> =\n z.enum(ErasureRetentionMode);\n\n/** @wildo_source:part:start saas.models.privacy.statutory-retention-ground facet:layer:shared facet:audience:app-developer */\n/**\n * **WHY the law lets a row survive an erasure** — the exemption a `retentionPolicy.statutoryRetention`\n * declaration names (#1635).\n *\n * A data subject's right to erasure (GDPR Art. 17(1)) does not apply \"to the extent that processing is\n * necessary … for compliance with a legal obligation which requires processing by Union or Member State\n * law to which the controller is subject\" (Art. 17(3)(b)). Business correspondence and accounting source\n * documents carry exactly such an obligation — HGB §257 and AO §147 in Germany, Code de commerce L123-22 in\n * France — so a subject erasure keeps those rows until the statutory period ends, and RESTRICTS them in the\n * meantime: stored, and processed for nothing else (the Art. 18(2) effect, which BDSG §35(1)/(3) states\n * explicitly as the substitute for erasure).\n *\n * spec-cite: Regulation (EU) 2016/679, Art. 17(3) introductory sentence, (b) and (e), fetched from\n * gdpr-info.eu/art-17-gdpr 2026-09-27; Art. 18(2) and BDSG §35(1)/(3) as fetched and quoted in #1635.\n *\n * ## One member, on purpose\n *\n * Art. 17(3)(e) — \"for the establishment, exercise or defence of legal claims\" — is the other ground an\n * operator reaches for, and it is deliberately NOT a member. It is a property of a CASE, decided when a claim\n * arises and lifted when it ends: that is a legal hold (#1634), not a property of every row of a class. A\n * member here would let a resource declare every row permanently \"needed for legal claims\", which is the\n * standing retention the storage-limitation principle forbids. The remaining grounds of Art. 17(3) (freedom\n * of expression, public health, archiving in the public interest) have no Wildo mechanism behind them; a\n * member without one would be a claim nothing enforces.\n *\n * `z.enum` rather than a literal so a member added later reaches every consumer through this one source.\n */\nexport enum StatutoryRetentionGround {\n /** GDPR Art. 17(3)(b): the rows are kept because a statute requires the controller to keep them. */\n LEGAL_OBLIGATION = 'legal_obligation',\n}\n\n/**\n * Zod schema for {@link StatutoryRetentionGround}. Explicitly annotated for the `isolatedDeclarations`\n * emit constraint.\n */\nexport const StatutoryRetentionGroundSchema: z.ZodEnum<typeof StatutoryRetentionGround> =\n z.enum(StatutoryRetentionGround);\n/** @wildo_source:part:end saas.models.privacy.statutory-retention-ground */\n\n/**\n * **WHOSE SESSION ENDS** when a row of this resource is erased. The second axis of the erasure\n * contract, beside {@link ErasureRetentionMode} (which says what happens to the row).\n *\n * ## This axis is NOT \"is this row about a person?\" — read this before adding a member\n *\n * The two questions look like one and are not, and conflating them cost this vocabulary a member name\n * for months (see the rename note below). Wildo answers them on SEPARATE axes:\n *\n * | question | the axis that answers it |\n * |---|---|\n * | Does this resource hold personal data? | {@link ErasureRetentionMode} — `RETAIN_AND_IMPERSONALIZE` requires at least one field that would actually be scrubbed; `RETAIN_ONLY` means *\"holds no personal data of its own\"*, and a scrub treatment under it fails at config build |\n * | Can a subject-access or portability export answer for it? | `systemAccessPolicy.exportSubject` |\n * | **Whose login session must be revoked?** | **this enum** |\n *\n * A CRM contact, a sales lead, a newsletter subscriber and a patient with no portal account are all\n * **data subjects with no session**. They declare `RETAIN_AND_IMPERSONALIZE` (they hold personal data)\n * and {@link ResourceDataSubjectKind.NO_PRINCIPAL} (there is no session to end) — two independent,\n * truthful answers. Adding a fourth member here for them would make this enum a cross-product of two\n * axes, which is two fields wearing one name.\n *\n * ## Why the third member is `NO_PRINCIPAL` and not `NOT_A_DATA_SUBJECT`\n *\n * It was `NOT_A_DATA_SUBJECT` until 2026-08-28, and the name was the defect. Operationally it always\n * meant *\"revoke nobody\"* — which is exactly right for a CRM contact — while its NAME claimed the row\n * was not about a person, which is false for one. Nothing misbehaved at runtime (the single consumer,\n * `resolveScrubSessionPrincipals`, only ever asked the session question), so the cost landed entirely\n * on readers: a human, and a compliance-document generator, both read the name and would have stated\n * in a published privacy notice that the application holds no personal data in precisely the resource\n * its customers care most about.\n *\n * The industry model this now matches is unambiguous — Intercom deletes \"a user **or lead**\", HubSpot\n * GDPR-deletes a Contact by id or by email, Zendesk \"forgets\" an end-user: an account and a data\n * subject are different objects, and the erasure verb applies to both. Wildo's `eraseSubjectAsSystem`\n * already takes `(resourceType, rowIds)` with no principal, so the capability was never missing.\n *\n * ## Why this must be DECLARED and can never be inferred\n *\n * An erasure of a person must also end that person's session, or a \"deleted\" person keeps browsing on\n * a live token until it expires. The tempting shortcut is to look for a `userId`-shaped foreign key on\n * the erased row and revoke it. **That shortcut is a defect, not an optimisation.** On almost every\n * resource a user foreign key names the OWNER or the ACTOR, not the subject: Wonder Todos' `TODOS` is\n * retention-governed and carries `createdByUserId`, `assignedToUserId` and `escalationContactUserId`,\n * so an inferring implementation would log out the author, the assignee and the escalation contact —\n * three people, none of them the data subject — every time a todo was erased.\n *\n * So the linkage is authored, never guessed, and a resource that can be an erasure subject (i.e. one\n * declaring a `retentionPolicy`) must say which of these it is. Undeclared is refused at config build:\n * nobody has decided yet, and refusing is what forces the decision — the same doctrine the subject\n * EXPORT model applies to an undeclared resource.\n */\nexport enum ResourceDataSubjectKind {\n /**\n * Erasing a row of this resource revokes **no session**, because no login is reachable from it.\n *\n * Two very different populations share this answer, and the enum is deliberately silent about which\n * one a given resource is — {@link ErasureRetentionMode} says that:\n *\n * - **Not a person at all.** A todo, an invoice, a log line. Any user foreign keys it carries name\n * ACTORS — an author, an assignee, an owner, an escalation contact — and revoking their sessions\n * because a record was erased would log out three uninvolved people. Such a resource pairs this\n * with `RETAIN_ONLY`.\n * - **A person with no account.** A CRM contact, a sales lead, a subscriber, a patient with no\n * portal login. Their rows ARE personal data and carry the full weight of Arts 15–17 and 20 —\n * there is simply no session to end. Such a resource pairs this with `RETAIN_AND_IMPERSONALIZE`\n * and per-field `.impersonalizeWith()` treatments, and its subject-rights path is the ordinary\n * administrative one: `eraseSubjectAsSystem(resourceType, rowIds)` and a subject export.\n *\n * The second population is the majority of what a B2B SaaS customer stores about third parties, and\n * it is what most of a privacy notice describes. Do not read this member as \"nothing to disclose\".\n */\n NO_PRINCIPAL = 'no_principal',\n /**\n * Rows of this resource ARE the person, and the row's own id IS the session principal: erasing row\n * `X` ends the session of user `X`. This is `USERS` / `USER_SELF`.\n *\n * Note this makes EXPLICIT a revocation that is otherwise only incidental. Erasing a `USERS` row\n * already logs the user out today — but only as a side effect of the retention row-hide (the auth\n * fronts re-read the user, find the row hidden, and 401) plus the scrub write bumping\n * `authorizationVersion`. Nothing on the erasure path ever WROTE a revocation, so the guarantee\n * lived entirely in the behaviour of two unrelated mechanisms.\n */\n SELF_PRINCIPAL = 'self_principal',\n /**\n * Rows of this resource are a person whose login lives in a DIFFERENT `USERS` row — a Patient, an\n * Employee, a Member record that a human signs in as. `sessionPrincipalField` names the field\n * holding that user's id.\n *\n * The named field must carry no `.impersonalizeWith()` treatment. Not because the revocation would\n * break — the principal is resolved BEFORE the scrub, so a scrubbed field is still readable when it\n * matters — but because declaring one field to be BOTH the link to a person and personal data to\n * destroy is self-contradictory, and it leaves the retained row with no way to say whose session was\n * ended. Enforced at config build.\n */\n LINKED_PRINCIPAL = 'linked_principal',\n}\n\n/**\n * Zod schema for {@link ResourceDataSubjectKind}. Explicitly annotated for the\n * `isolatedDeclarations` emit constraint.\n */\nexport const ResourceDataSubjectKindSchema: z.ZodEnum<typeof ResourceDataSubjectKind> =\n z.enum(ResourceDataSubjectKind);\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which jurisdictions contain which (#2588 carve). An IMPORT-FREE atom, so the browser-safe
|
|
3
|
+
* `@wildo-ai/saas-models/public-runtime` entrypoint and the zod-backed jurisdiction schemas
|
|
4
|
+
* (`operating-jurisdictions.shared.schemas.ts`, which validates slugs against this table) read the one copy.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Which jurisdictions a broader one contains, so a source addressing the broader one answers for them.
|
|
8
|
+
*
|
|
9
|
+
* Without this, an application declaring `fr` would be reported as uncovered while the GDPR source
|
|
10
|
+
* plainly reaches it — over-warning, which is the failure mode that trains a reader to skim past the
|
|
11
|
+
* warnings that matter. Subdivisions need no table: `us-ca` is contained by `us` by construction, and
|
|
12
|
+
* that rule is applied in code rather than enumerated here.
|
|
13
|
+
*
|
|
14
|
+
* This table has a SECOND duty, so do not read it as coverage-only: its KEYS are the roots that stand
|
|
15
|
+
* for other jurisdictions, and `jurisdictionSlugProblem` (`operating-jurisdictions.shared.schemas.ts`) refuses a suffix on any of them —
|
|
16
|
+
* because a suffix can only be read as a place inside its root, and on an aggregate that reading
|
|
17
|
+
* inverts. Adding a key therefore also closes `<key>-<anything>` as an authorable slug, which is the
|
|
18
|
+
* intended consequence: the places a regime covers each have their own code.
|
|
19
|
+
*
|
|
20
|
+
* ⚠️ EU membership is a legal fact with a review trigger, not a convenience list: it changes when a
|
|
21
|
+
* state accedes or withdraws, and it has done both. Verified against the 27 members as of 2026-09-02.
|
|
22
|
+
* Nothing derives it, so a change is a deliberate edit here.
|
|
23
|
+
*/
|
|
24
|
+
export declare const JURISDICTION_CONTAINMENT: Readonly<Record<string, readonly string[]>>;
|
|
25
|
+
/**
|
|
26
|
+
* Does a source addressing `reach` answer for an application operating in `declared`?
|
|
27
|
+
*
|
|
28
|
+
* Three ways, and the order is deliberate — exact first, because it is the common case and the other
|
|
29
|
+
* two are refinements of it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function jurisdictionReachCovers(reach: string, declared: string): boolean;
|
|
32
|
+
//# sourceMappingURL=jurisdiction-containment.shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jurisdiction-containment.shared.d.ts","sourceRoot":"","sources":["../../../../src/compliance/privacy/jurisdiction-containment.shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAK/E,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAShF"}
|