@wildo-ai/saas-models 1.1.1 → 1.1.3
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/applications/applications-context.schemas.d.ts +16 -10
- package/dist/esm/applications/applications-context.schemas.d.ts.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 +4 -3
- package/dist/esm/applications/applications.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/billing-account.shared.resources-config.schemas.d.ts +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 +36 -0
- 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 +8 -1
- package/dist/esm/billing/billing-account.shared.schemas.js.map +1 -1
- package/dist/esm/billing/billing-configuration.shared.schemas.d.ts +0 -4
- package/dist/esm/billing/billing-configuration.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/billing-configuration.shared.schemas.js +59 -17
- package/dist/esm/billing/billing-configuration.shared.schemas.js.map +1 -1
- package/dist/esm/billing/billing-enums.shared.schemas.d.ts +77 -21
- package/dist/esm/billing/billing-enums.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/billing-enums.shared.schemas.js +85 -23
- package/dist/esm/billing/billing-enums.shared.schemas.js.map +1 -1
- package/dist/esm/billing/billing-types.shared.schemas.d.ts +5 -5
- package/dist/esm/billing/credit-pool.shared.resources-config.schemas.d.ts +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 +39 -0
- package/dist/esm/billing/credit-pool.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/credit-pool.shared.schemas.d.ts +6 -6
- package/dist/esm/billing/credit-pool.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/credit-pool.shared.schemas.js +8 -4
- package/dist/esm/billing/credit-pool.shared.schemas.js.map +1 -1
- package/dist/esm/billing/invoice-ref.shared.resources-config.schemas.d.ts +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 +35 -0
- 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 +8 -3
- package/dist/esm/billing/invoice-ref.shared.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 +7 -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 +52 -11
- package/dist/esm/billing/product-behavior-policy.shared.schemas.js.map +1 -1
- package/dist/esm/billing/product-definition.shared.schemas.d.ts +2 -2
- package/dist/esm/billing/product.shared.resources-config.schemas.d.ts +2 -2
- package/dist/esm/billing/product.shared.schemas.d.ts +2 -2
- package/dist/esm/billing/product.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/product.shared.schemas.js +7 -3
- package/dist/esm/billing/product.shared.schemas.js.map +1 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.d.ts +2 -2
- package/dist/esm/billing/subscription.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.js +54 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/subscription.shared.schemas.d.ts +4 -4
- package/dist/esm/billing/subscription.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/subscription.shared.schemas.js +6 -2
- package/dist/esm/billing/subscription.shared.schemas.js.map +1 -1
- package/dist/esm/billing/usage-record.shared.resources-config.schemas.d.ts +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 +39 -0
- package/dist/esm/billing/usage-record.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/usage-record.shared.schemas.d.ts +11 -7
- package/dist/esm/billing/usage-record.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/usage-record.shared.schemas.js +29 -6
- package/dist/esm/billing/usage-record.shared.schemas.js.map +1 -1
- package/dist/esm/companion/provider-discovery.shared.schemas.d.ts +69 -2
- package/dist/esm/companion/provider-discovery.shared.schemas.d.ts.map +1 -1
- package/dist/esm/companion/provider-discovery.shared.schemas.js +20 -1
- package/dist/esm/companion/provider-discovery.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.d.ts +85 -0
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.js +157 -0
- package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.js.map +1 -0
- 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 +35 -2
- 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 +23 -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 +56 -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 +541 -20
- 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 +605 -23
- 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.map +1 -1
- package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.js +96 -3
- package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.js.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization-scrub.shared.utils.d.ts +49 -0
- package/dist/esm/compliance/privacy/impersonalization-scrub.shared.utils.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization-scrub.shared.utils.js +124 -1
- package/dist/esm/compliance/privacy/impersonalization-scrub.shared.utils.js.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization.shared.schemas.d.ts +11 -3
- package/dist/esm/compliance/privacy/impersonalization.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/impersonalization.shared.schemas.js +11 -3
- package/dist/esm/compliance/privacy/impersonalization.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts +94 -0
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts.map +1 -0
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.js +211 -0
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.js.map +1 -0
- package/dist/esm/compliance/privacy/operator-compliance-identity.shared.schemas.d.ts +67 -12
- 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 +95 -8
- package/dist/esm/compliance/privacy/operator-compliance-identity.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/privacy.shared.schemas.d.ts +17 -0
- package/dist/esm/compliance/privacy/privacy.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/privacy.shared.schemas.js +27 -4
- package/dist/esm/compliance/privacy/privacy.shared.schemas.js.map +1 -1
- package/dist/esm/compliance/privacy/redaction.shared.schemas.d.ts +89 -16
- package/dist/esm/compliance/privacy/redaction.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/redaction.shared.schemas.js +101 -15
- package/dist/esm/compliance/privacy/redaction.shared.schemas.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 +12 -5
- package/dist/esm/compliance/privacy/subject-export.shared.schemas.js.map +1 -1
- package/dist/esm/config/analytics-value-moments.shared.schemas.d.ts +21 -0
- package/dist/esm/config/analytics-value-moments.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/analytics-value-moments.shared.schemas.js +20 -0
- package/dist/esm/config/analytics-value-moments.shared.schemas.js.map +1 -1
- package/dist/esm/config/app-configuration-shared.shared.schemas.d.ts +9 -5
- package/dist/esm/config/app-configuration-shared.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/app-configuration-shared.shared.schemas.js +29 -0
- package/dist/esm/config/app-configuration-shared.shared.schemas.js.map +1 -1
- package/dist/esm/config/auth-config-resolution.shared.utils.d.ts +8 -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 +29 -0
- package/dist/esm/config/auth-config-resolution.shared.utils.js.map +1 -1
- package/dist/esm/config/entity-identity-config.shared.schemas.d.ts +95 -17
- package/dist/esm/config/entity-identity-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/entity-identity-config.shared.schemas.js +86 -8
- package/dist/esm/config/entity-identity-config.shared.schemas.js.map +1 -1
- package/dist/esm/config/frontend/chart-definition.shared.schemas.d.ts +12 -12
- package/dist/esm/config/frontend/navigation.shared.schemas.d.ts +33 -0
- package/dist/esm/config/frontend/navigation.shared.schemas.d.ts.map +1 -1
- package/dist/esm/config/frontend/navigation.shared.schemas.js +32 -0
- package/dist/esm/config/frontend/navigation.shared.schemas.js.map +1 -1
- package/dist/esm/errors/errors.custom-message-ref.shared.definitions.d.ts +40 -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 +40 -1
- package/dist/esm/errors/errors.custom-message-ref.shared.definitions.js.map +1 -1
- package/dist/esm/external-data/external-data-pipeline.shared.schemas.d.ts +57 -11
- 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-providers/engine-capabilities.shared.schemas.d.ts +109 -64
- package/dist/esm/external-providers/engine-capabilities.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/engine-capabilities.shared.schemas.js +200 -19
- 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 +15 -3
- 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 +32 -7
- package/dist/esm/external-providers/engine-capability-resolution-mode.shared.js.map +1 -1
- package/dist/esm/external-providers/frontend-bootstrap.shared.schemas.d.ts +84 -7
- package/dist/esm/external-providers/frontend-bootstrap.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.d.ts +59 -0
- package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.d.ts.map +1 -0
- package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.js +61 -0
- package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.js.map +1 -0
- package/dist/esm/external-providers/frontend-capability-runtime.shared.types.d.ts +97 -0
- package/dist/esm/external-providers/frontend-capability-runtime.shared.types.d.ts.map +1 -0
- package/dist/esm/external-providers/frontend-capability-runtime.shared.types.js +41 -0
- package/dist/esm/external-providers/frontend-capability-runtime.shared.types.js.map +1 -0
- package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.d.ts +148 -2
- 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 +56 -1
- package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-capability.shared.schemas.d.ts +9 -31
- package/dist/esm/external-providers/provider-capability.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-capability.shared.schemas.js +8 -5
- 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 +18 -8
- 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 +9 -4
- package/dist/esm/external-providers/provider-compliance-profile.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.d.ts +338 -0
- package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.d.ts.map +1 -0
- package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.js +332 -0
- package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.js.map +1 -0
- package/dist/esm/external-providers/provider-metadata.shared.schemas.d.ts +178 -9
- package/dist/esm/external-providers/provider-metadata.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-metadata.shared.schemas.js +181 -9
- package/dist/esm/external-providers/provider-metadata.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-protocol.shared.schemas.d.ts +7 -5
- package/dist/esm/external-providers/provider-protocol.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-protocol.shared.schemas.js +7 -5
- package/dist/esm/external-providers/provider-protocol.shared.schemas.js.map +1 -1
- package/dist/esm/external-providers/provider-tier-rule.shared.utils.d.ts +40 -0
- package/dist/esm/external-providers/provider-tier-rule.shared.utils.d.ts.map +1 -0
- package/dist/esm/external-providers/provider-tier-rule.shared.utils.js +80 -0
- package/dist/esm/external-providers/provider-tier-rule.shared.utils.js.map +1 -0
- package/dist/esm/features/core-feature-definitions.shared.d.ts.map +1 -1
- package/dist/esm/features/core-feature-definitions.shared.js +7 -1
- package/dist/esm/features/core-feature-definitions.shared.js.map +1 -1
- package/dist/esm/features/feature-builders.shared.d.ts +32 -0
- package/dist/esm/features/feature-builders.shared.d.ts.map +1 -1
- package/dist/esm/features/feature-builders.shared.js +32 -0
- package/dist/esm/features/feature-builders.shared.js.map +1 -1
- package/dist/esm/features/user-features.shared.resources-config.schemas.d.ts +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 +48 -0
- package/dist/esm/features/user-features.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/files/file-upload-grant.shared.schemas.d.ts +156 -0
- package/dist/esm/files/file-upload-grant.shared.schemas.d.ts.map +1 -0
- package/dist/esm/files/file-upload-grant.shared.schemas.js +175 -0
- package/dist/esm/files/file-upload-grant.shared.schemas.js.map +1 -0
- package/dist/esm/files/files.shared.schemas.d.ts +52 -4
- package/dist/esm/files/files.shared.schemas.d.ts.map +1 -1
- package/dist/esm/files/files.shared.schemas.js +55 -4
- package/dist/esm/files/files.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/a2a-push-delivery-log.shared.resources-config.schemas.d.ts +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 +33 -0
- 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 +6 -2
- 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 +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 +53 -0
- package/dist/esm/flows-actors/a2a-token-budget-state.shared.resources-config.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 +3 -2
- package/dist/esm/flows-actors/actors.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/agents.shared.schemas.d.ts +54 -5
- 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/apps-blueprint/apps-blueprint.shared.schemas.d.ts +6 -6
- package/dist/esm/flows-actors/deliberation.shared.schemas.d.ts +0 -3
- package/dist/esm/flows-actors/deliberation.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/deliberation.shared.schemas.js +0 -5
- package/dist/esm/flows-actors/deliberation.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors-execution.shared.resources-config.schemas.d.ts +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 +43 -0
- 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 +14 -0
- 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 +48 -6
- 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 +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 +41 -0
- 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 +0 -7
- 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 +23 -13
- 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 +19 -0
- 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 +33 -0
- package/dist/esm/flows-actors/flows-actors.commons.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/flows-actors.io.shared.schemas.d.ts +14 -9
- 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 +14 -9
- package/dist/esm/flows-actors/flows-actors.io.shared.schemas.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 +3 -2
- 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 +3 -2
- package/dist/esm/flows-actors/flows.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/mcp-servers.shared.schemas.d.ts +128 -0
- package/dist/esm/flows-actors/mcp-servers.shared.schemas.d.ts.map +1 -0
- package/dist/esm/flows-actors/mcp-servers.shared.schemas.js +142 -0
- package/dist/esm/flows-actors/mcp-servers.shared.schemas.js.map +1 -0
- package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.d.ts +0 -3
- package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.js +1 -4
- package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.d.ts +0 -16
- package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.js +1 -17
- package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/meta-workflows/decisions.meta-workflows.shared.schemas.d.ts +3 -3
- package/dist/esm/flows-actors/meta-workflows/decisions.meta-workflows.shared.schemas.js +3 -3
- package/dist/esm/flows-actors/meta-workflows/decisions.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.d.ts +2 -8
- package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.js +4 -15
- package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/guidance-state.shared.resources-config.schemas.d.ts +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 +51 -0
- 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 +8 -2
- 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 +1 -0
- package/dist/esm/guidance/guidance-state.shared.utils.js.map +1 -1
- package/dist/esm/guidance/lifecycle-state.shared.resources-config.schemas.d.ts +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 +51 -0
- 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 +28 -3
- package/dist/esm/guidance/lifecycle-state.shared.schemas.js.map +1 -1
- package/dist/esm/guidance/progression-state.shared.resources-config.schemas.d.ts +9 -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 +51 -0
- package/dist/esm/guidance/progression-state.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/guidance/progression-state.shared.schemas.d.ts +46 -0
- package/dist/esm/guidance/progression-state.shared.schemas.d.ts.map +1 -1
- package/dist/esm/guidance/progression-state.shared.schemas.js +67 -4
- package/dist/esm/guidance/progression-state.shared.schemas.js.map +1 -1
- package/dist/esm/http-api-binding/http-api-binding.shared.schemas.d.ts +356 -52
- 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 +166 -39
- package/dist/esm/http-api-binding/http-api-binding.shared.schemas.js.map +1 -1
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/notifications/email/email-template-registry.shared.schemas.d.ts +11 -2
- 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 +15 -0
- package/dist/esm/notifications/email/email-template.shared.enums.d.ts.map +1 -1
- package/dist/esm/notifications/email/email-template.shared.enums.js +15 -0
- package/dist/esm/notifications/email/email-template.shared.enums.js.map +1 -1
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-contract.shared.d.ts +70 -0
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-contract.shared.d.ts.map +1 -0
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-contract.shared.js +71 -0
- package/dist/esm/notifications/m2m/m2m-webhook-delivery-contract.shared.js.map +1 -0
- package/dist/esm/notifications/m2m/webhook-config.shared.resources-config.schemas.d.ts +1 -0
- 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 +19 -0
- 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 +30 -0
- package/dist/esm/notifications/m2m/webhook-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/m2m/webhook-config.shared.schemas.js +65 -1
- package/dist/esm/notifications/m2m/webhook-config.shared.schemas.js.map +1 -1
- package/dist/esm/notifications/notification-badges.core.definitions.d.ts +6 -4
- package/dist/esm/notifications/notification-badges.core.definitions.d.ts.map +1 -1
- package/dist/esm/notifications/notification-badges.core.definitions.js +6 -4
- package/dist/esm/notifications/notification-badges.core.definitions.js.map +1 -1
- package/dist/esm/notifications/notification-badges.schemas.d.ts +167 -5
- package/dist/esm/notifications/notification-badges.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/notification-badges.schemas.js +191 -6
- package/dist/esm/notifications/notification-badges.schemas.js.map +1 -1
- package/dist/esm/notifications/notification-badges.shared.resources-config.schemas.d.ts +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 +36 -0
- package/dist/esm/notifications/notification-badges.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/notifications/notifications.shared.schemas.d.ts +107 -0
- package/dist/esm/notifications/notifications.shared.schemas.d.ts.map +1 -1
- package/dist/esm/notifications/notifications.shared.schemas.js +149 -1
- package/dist/esm/notifications/notifications.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-members.shared.resources-config.schemas.d.ts +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 +44 -0
- 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 +15 -4
- package/dist/esm/organizations/organization-members.shared.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 +22 -1
- package/dist/esm/organizations/organization-notifications.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-preferences.shared.schemas.d.ts +26 -0
- package/dist/esm/organizations/organization-preferences.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-preferences.shared.schemas.js +25 -0
- package/dist/esm/organizations/organization-preferences.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-profile.shared.schemas.d.ts +25 -0
- package/dist/esm/organizations/organization-profile.shared.schemas.d.ts.map +1 -1
- package/dist/esm/organizations/organization-profile.shared.schemas.js +42 -17
- package/dist/esm/organizations/organization-profile.shared.schemas.js.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing.shared.d.ts +3 -2
- package/dist/esm/organizations/organization-unit-narrowing.shared.d.ts.map +1 -1
- package/dist/esm/organizations/organization-unit-narrowing.shared.js +9 -2
- package/dist/esm/organizations/organization-unit-narrowing.shared.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 +35 -12
- package/dist/esm/organizations/organizations.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/public-runtime/index.d.ts +49 -2
- package/dist/esm/public-runtime/index.d.ts.map +1 -1
- package/dist/esm/public-runtime/index.js +48 -1
- package/dist/esm/public-runtime/index.js.map +1 -1
- package/dist/esm/queue/jobs.shared.resources-config.schemas.d.ts +6 -5
- package/dist/esm/queue/jobs.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/queue/jobs.shared.resources-config.schemas.js +23 -5
- package/dist/esm/queue/jobs.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/queue/jobs.shared.schemas.d.ts +16 -3
- package/dist/esm/queue/jobs.shared.schemas.d.ts.map +1 -1
- package/dist/esm/queue/jobs.shared.schemas.js +16 -3
- package/dist/esm/queue/jobs.shared.schemas.js.map +1 -1
- package/dist/esm/requests/manual-controllers-routes-documentation.d.ts +137 -0
- package/dist/esm/requests/manual-controllers-routes-documentation.d.ts.map +1 -0
- package/dist/esm/requests/manual-controllers-routes-documentation.js +1201 -0
- package/dist/esm/requests/manual-controllers-routes-documentation.js.map +1 -0
- package/dist/esm/requests/manual-controllers-routes-urls.d.ts +67 -0
- package/dist/esm/requests/manual-controllers-routes-urls.d.ts.map +1 -1
- package/dist/esm/requests/manual-controllers-routes-urls.js +78 -0
- package/dist/esm/requests/manual-controllers-routes-urls.js.map +1 -1
- package/dist/esm/requests/rate-limits.shared.schemas.d.ts +11 -1
- package/dist/esm/requests/rate-limits.shared.schemas.d.ts.map +1 -1
- package/dist/esm/requests/rate-limits.shared.schemas.js +11 -1
- package/dist/esm/requests/rate-limits.shared.schemas.js.map +1 -1
- package/dist/esm/requests/websocket.shared.schemas.d.ts +86 -4
- package/dist/esm/requests/websocket.shared.schemas.d.ts.map +1 -1
- package/dist/esm/requests/websocket.shared.schemas.js +138 -0
- package/dist/esm/requests/websocket.shared.schemas.js.map +1 -1
- package/dist/esm/resources/collection-query-parameters.shared.d.ts +22 -0
- package/dist/esm/resources/collection-query-parameters.shared.d.ts.map +1 -0
- package/dist/esm/resources/collection-query-parameters.shared.js +22 -0
- package/dist/esm/resources/collection-query-parameters.shared.js.map +1 -0
- package/dist/esm/resources/resources-config.shared.factory.d.ts +1 -0
- package/dist/esm/resources/resources-config.shared.factory.d.ts.map +1 -1
- package/dist/esm/resources/resources-config.shared.factory.js +189 -31
- package/dist/esm/resources/resources-config.shared.factory.js.map +1 -1
- package/dist/esm/resources/resources-config.shared.schemas.d.ts +395 -92
- package/dist/esm/resources/resources-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/resources-config.shared.schemas.js +109 -20
- 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 +97 -5
- 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 +15 -0
- package/dist/esm/resources/resources-relationships.shared.factory.js.map +1 -1
- package/dist/esm/resources/resources.shared.core.definitions.d.ts +37 -0
- package/dist/esm/resources/resources.shared.core.definitions.d.ts.map +1 -1
- package/dist/esm/resources/resources.shared.core.definitions.js +51 -0
- package/dist/esm/resources/resources.shared.core.definitions.js.map +1 -1
- package/dist/esm/resources/resources.shared.schemas.d.ts +11 -2
- package/dist/esm/resources/resources.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/resources.shared.schemas.js +34 -3
- package/dist/esm/resources/resources.shared.schemas.js.map +1 -1
- package/dist/esm/resources/utils/field-value-disclosure.utils.d.ts +51 -0
- package/dist/esm/resources/utils/field-value-disclosure.utils.d.ts.map +1 -0
- package/dist/esm/resources/utils/field-value-disclosure.utils.js +53 -0
- package/dist/esm/resources/utils/field-value-disclosure.utils.js.map +1 -0
- 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 +21 -6
- package/dist/esm/resources/utils/resources-config-operations.dtos-builder.utils.js.map +1 -1
- package/dist/esm/resources/utils/resources-summary.utils.d.ts +16 -2
- package/dist/esm/resources/utils/resources-summary.utils.d.ts.map +1 -1
- package/dist/esm/resources/utils/resources-summary.utils.js +19 -5
- package/dist/esm/resources/utils/resources-summary.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 +11 -0
- package/dist/esm/resources/utils/shared-persistence-collection.utils.js.map +1 -1
- package/dist/esm/runtime/domain-module.shared.definitions.d.ts +25 -0
- 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/security/api-keys/api-keys-application.shared.resources-config.schemas.d.ts +1 -0
- 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 +38 -0
- 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 +1 -0
- 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 +38 -0
- package/dist/esm/security/api-keys/api-keys-organization.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.dto.schemas.d.ts +4 -11
- package/dist/esm/security/authentications/authentication.shared.dto.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.dto.schemas.js +0 -1
- package/dist/esm/security/authentications/authentication.shared.dto.schemas.js.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.schemas.d.ts +141 -5
- package/dist/esm/security/authentications/authentication.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.schemas.js +147 -3
- package/dist/esm/security/authentications/authentication.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/consumable-token.shared.schemas.d.ts +17 -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 +16 -0
- package/dist/esm/security/authentications/consumable-token.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/mfa-backup-code-contract.shared.d.ts +28 -0
- package/dist/esm/security/authentications/mfa-backup-code-contract.shared.d.ts.map +1 -0
- package/dist/esm/security/authentications/mfa-backup-code-contract.shared.js +28 -0
- package/dist/esm/security/authentications/mfa-backup-code-contract.shared.js.map +1 -0
- package/dist/esm/security/authentications/registration.shared.dto.schemas.d.ts +1 -0
- package/dist/esm/security/authentications/registration.shared.dto.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/registration.shared.dto.schemas.js +11 -0
- package/dist/esm/security/authentications/registration.shared.dto.schemas.js.map +1 -1
- package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.d.ts +15 -0
- 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 +21 -4
- package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/siem/siem-delivery-reliability-contract.shared.d.ts +21 -0
- package/dist/esm/security/authentications/siem/siem-delivery-reliability-contract.shared.d.ts.map +1 -0
- package/dist/esm/security/authentications/siem/siem-delivery-reliability-contract.shared.js +21 -0
- package/dist/esm/security/authentications/siem/siem-delivery-reliability-contract.shared.js.map +1 -0
- package/dist/esm/security/authentications/sso/sso-config.shared.resources-config.schemas.d.ts +61 -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 +208 -6
- 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 +37 -27
- 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 +134 -12
- package/dist/esm/security/authentications/sso/sso-config.shared.schemas.js.map +1 -1
- package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.d.ts +0 -6
- 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 +17 -8
- package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.d.ts +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 +70 -0
- 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 +45 -8
- 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 +56 -10
- package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.schemas.d.ts +16 -1
- package/dist/esm/security/authorizations/roles.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.schemas.js +16 -1
- package/dist/esm/security/authorizations/roles.shared.schemas.js.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.utils.d.ts +54 -0
- package/dist/esm/security/authorizations/roles.shared.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/roles.shared.utils.js +59 -0
- package/dist/esm/security/authorizations/roles.shared.utils.js.map +1 -1
- package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.d.ts +31 -0
- package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.js +198 -0
- package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.js.map +1 -0
- package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.d.ts +31 -0
- package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.js +191 -0
- package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.js.map +1 -0
- package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.d.ts +250 -0
- package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.js +486 -0
- package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.js.map +1 -0
- package/dist/esm/security/oauth-clients/oauth-clients-application.shared.resources-config.schemas.d.ts +4 -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 +29 -0
- 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 +4 -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 +29 -0
- 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 +67 -0
- 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 +44 -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 +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 +35 -0
- 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 +13 -0
- 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 +31 -4
- package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.js.map +1 -1
- package/dist/esm/users/inbound-contacts.shared.resources-config.schemas.d.ts +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 +34 -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 +7 -4
- package/dist/esm/users/inbound-contacts.shared.schemas.js.map +1 -1
- package/dist/esm/users/user-credentials.shared.resources-config.schemas.d.ts +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 +37 -0
- 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 +17 -2
- 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 +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 +36 -0
- 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 +15 -5
- package/dist/esm/users/user-identity-links.shared.schemas.js.map +1 -1
- package/dist/esm/users/user-preferences.shared.resources-config.schemas.d.ts +5 -5
- 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 +53 -0
- 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 +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 +62 -0
- 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 +5 -5
- 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 +53 -0
- 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 +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 +62 -0
- 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 +33 -3
- 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 +17 -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 +136 -5
- package/dist/esm/users/users.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/users/users.shared.schemas.d.ts +62 -12
- package/dist/esm/users/users.shared.schemas.d.ts.map +1 -1
- package/dist/esm/users/users.shared.schemas.js +79 -23
- package/dist/esm/users/users.shared.schemas.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -6
- package/dist/esm/.builder.pid +0 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getImpersonalizeMaskValue, getImpersonalizeTreatment, getMergedObjectOrUnionShape } from '@wildo-ai/zod-decorators';
|
|
1
|
+
import { getDataCategories, getImpersonalizeMaskValue, getImpersonalizeTreatment, getMergedObjectOrUnionShape } from '@wildo-ai/zod-decorators';
|
|
2
2
|
import { RedactionType } from './redaction.shared.schemas.js';
|
|
3
3
|
import { FIELD_IDENTIFIER_TO_PRIMARY_SCOPE, ResourcePrimaryScope } from '../../resources/resources.shared.schemas.js';
|
|
4
4
|
/**
|
|
@@ -32,6 +32,83 @@ export function resolveImpersonalizeMaskValue(fieldSchema) {
|
|
|
32
32
|
* `.impersonalizeWith('remove')` IS severable — this is how "erase the subject's link, keep the scoped
|
|
33
33
|
* record" is expressed.
|
|
34
34
|
*/
|
|
35
|
+
/**
|
|
36
|
+
* The value a `RESET` field becomes: its OWN schema default.
|
|
37
|
+
*
|
|
38
|
+
* Resolved by asking the schema, never by an authored constant. `parse(undefined)` is exactly the
|
|
39
|
+
* question "what is this field when nobody has set it", answered by Zod's own semantics — so the
|
|
40
|
+
* default lives in ONE place and a later change to it moves the scrub with it. An authored copy would
|
|
41
|
+
* drift, and a scrub writing a stale default is a row that looks reset and is not.
|
|
42
|
+
*
|
|
43
|
+
* Refuses a field with NO default rather than inventing one. `RESET` on such a field is an authoring
|
|
44
|
+
* error — `undefined` would either fail the re-parse or leave the value untouched depending on the
|
|
45
|
+
* writer, and both are worse than a loud refusal at config time. REMOVE is what that field wants.
|
|
46
|
+
*
|
|
47
|
+
* The result must still SATISFY the schema, which is the whole failure this treatment exists to
|
|
48
|
+
* prevent: a patch writing a value the schema rejects surfaces as a read error long after the erasure
|
|
49
|
+
* reported success. `parse` gives that for free — a default that does not validate cannot be returned.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveImpersonalizeResetValue(fieldSchema, fieldName) {
|
|
52
|
+
const parsed = fieldSchema.safeParse(undefined);
|
|
53
|
+
if (!parsed.success) {
|
|
54
|
+
throw new Error(`[impersonalize] RESET treatment on '${fieldName}' requires the field to declare a .default(), and it does not. ` +
|
|
55
|
+
`RESET means "return this field to what it is when nobody has set it", which has no answer here. ` +
|
|
56
|
+
`Use REMOVE for a field that may be absent, or add the default the treatment is asking for.`);
|
|
57
|
+
}
|
|
58
|
+
/*
|
|
59
|
+
* A CLOCK-READ default is refused, and this is the sharp edge of the whole treatment.
|
|
60
|
+
*
|
|
61
|
+
* `.default(() => new Date())` means "compute a fresh value at write time". Applied to
|
|
62
|
+
* `lastActiveAt` — a real field, declared USAGE personal data — RESET wrote the ERASURE's own
|
|
63
|
+
* timestamp, recording an erased person as last active at the moment they were erased. Measured
|
|
64
|
+
* before this guard: the value landed within a millisecond of `now`. That is worse than leaving the
|
|
65
|
+
* field alone. It does not fail to remove information, it FABRICATES it, and the fabricated value is
|
|
66
|
+
* exactly the kind a reader would trust.
|
|
67
|
+
*
|
|
68
|
+
* ## Why this is a heuristic, and why the obvious checks do not work
|
|
69
|
+
*
|
|
70
|
+
* Zod 4 exposes `defaultValue` as a GETTER returning the resolved value, so a literal and a thunk are
|
|
71
|
+
* statically indistinguishable — measured, both report `typeof object`. And resolving twice does not
|
|
72
|
+
* separate them either: two `new Date()` reads microseconds apart stringify identically, so a
|
|
73
|
+
* difference-based check silently passes the exact case it exists for. That version was written,
|
|
74
|
+
* tested, and failed to fire.
|
|
75
|
+
*
|
|
76
|
+
* What IS distinguishable is the value's relationship to the clock. A default resolving to a Date
|
|
77
|
+
* near `now` can only have come from reading the clock — whether from a thunk, or from a literal
|
|
78
|
+
* `.default(new Date())` evaluated at module load, which is equally wrong and equally invisible.
|
|
79
|
+
*
|
|
80
|
+
* A deliberate sentinel is never "recently". `new Date(0)` is 1970; an explicit epoch or a fixed
|
|
81
|
+
* historical date is years away. So the bound below admits every deliberate choice and refuses every
|
|
82
|
+
* clock read, and it is stated as a bound rather than pretending to be exact.
|
|
83
|
+
*/
|
|
84
|
+
/*
|
|
85
|
+
* `.optional()` PARSES `undefined` successfully, so the check above passes it and the resolver would
|
|
86
|
+
* return `undefined` — which is not a scrub. The patch would `$set` an undefined, which either
|
|
87
|
+
* no-ops or is rejected downstream by the canonicalizer, and either way the personal data survives
|
|
88
|
+
* an erasure that reported success.
|
|
89
|
+
*
|
|
90
|
+
* The distinction the two checks draw together: "has no default at all" and "is optional so its
|
|
91
|
+
* default IS undefined" are different authoring mistakes, and both mean RESET has no value to write.
|
|
92
|
+
* REMOVE is what an optional field wants — it writes an explicit null, which is a scrub.
|
|
93
|
+
*/
|
|
94
|
+
if (parsed.data === undefined) {
|
|
95
|
+
throw new Error(`[impersonalize] RESET treatment on '${fieldName}' resolves to \`undefined\` — the field is optional rather ` +
|
|
96
|
+
`than defaulted, so "what it is when nobody has set it" is nothing at all. Writing that is not a scrub: the ` +
|
|
97
|
+
`patch would set undefined and the personal data would survive. Use REMOVE, which writes an explicit null, ` +
|
|
98
|
+
`or give the field the .default() RESET is asking for.`);
|
|
99
|
+
}
|
|
100
|
+
const RESET_CLOCK_READ_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
101
|
+
if (parsed.data instanceof Date && Math.abs(Date.now() - parsed.data.getTime()) < RESET_CLOCK_READ_WINDOW_MS) {
|
|
102
|
+
throw new Error(`[impersonalize] RESET treatment on '${fieldName}' resolves to a timestamp within a day of NOW, which means ` +
|
|
103
|
+
`the default reads the clock (typically \`.default(() => new Date())\`, or a literal \`new Date()\` evaluated ` +
|
|
104
|
+
`at module load). Erasure would then write a value generated BY the erasure — a field like 'lastActiveAt' ` +
|
|
105
|
+
`would record the erased person as active at the moment they were erased, fabricating information rather ` +
|
|
106
|
+
`than removing it. Give the field a STATIC neutral default such as new Date(0), which asserts "no recorded ` +
|
|
107
|
+
`value", or make it nullable and use REMOVE, which asserts "unknown". Those are different claims about an ` +
|
|
108
|
+
`erased person, so choose deliberately.`);
|
|
109
|
+
}
|
|
110
|
+
return parsed.data;
|
|
111
|
+
}
|
|
35
112
|
export function isImpersonalizeNeverScrubFloorField(fieldName) {
|
|
36
113
|
if (fieldName === 'createdByUserId')
|
|
37
114
|
return true;
|
|
@@ -40,6 +117,49 @@ export function isImpersonalizeNeverScrubFloorField(fieldName) {
|
|
|
40
117
|
|| scope === ResourcePrimaryScope.APPLICATION;
|
|
41
118
|
// USER_SELF / ANONYMOUS (person-link) fall through → severable per D1.
|
|
42
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* The fields whose declarations say this resource holds personal data — the evidence against a
|
|
122
|
+
* `RETAIN_ONLY` claim.
|
|
123
|
+
*
|
|
124
|
+
* ## Why this exists
|
|
125
|
+
*
|
|
126
|
+
* `RETAIN_ONLY` asserts a resource holds NO personal data of its own, and the factory could check that
|
|
127
|
+
* in only one direction: it refuses the mode when a field carries an impersonalize TREATMENT. It could
|
|
128
|
+
* not see personal data that nobody had given a treatment to. So the cheap answer for most resources
|
|
129
|
+
* was also the one that failed silently when wrong — a governed document stating that erasure leaves
|
|
130
|
+
* nothing behind, about rows holding a person's data. The opposite mode never had this hole:
|
|
131
|
+
* `RETAIN_AND_IMPERSONALIZE` is refused when nothing would be scrubbed.
|
|
132
|
+
*
|
|
133
|
+
* `.dataCategories()` is the declaration this reads, so the check catches a CONTRADICTION — a resource
|
|
134
|
+
* that says both "this field is personal data" and "this resource holds none". It cannot catch an
|
|
135
|
+
* OMISSION, where nothing was ever classified; that is a coverage question and belongs to the category
|
|
136
|
+
* inventory, not here. Saying so matters: a clean result is not a proof that a resource holds nothing.
|
|
137
|
+
*
|
|
138
|
+
* ## Read the RESOLVED shape, never the source text
|
|
139
|
+
*
|
|
140
|
+
* `getMergedObjectOrUnionShape` is used deliberately, for the same reason the scrub builder below uses
|
|
141
|
+
* it. A text-shaped read of a named schema misses both shapes that occur here in practice: a schema
|
|
142
|
+
* that `.extend()`s a base carries its categories on the BASE, and one file commonly declares several
|
|
143
|
+
* schemas so a range scan closes on a nested object. A census built that way reported `users` as
|
|
144
|
+
* holding no personal data, while `users.email` carries `CONTACT_DETAILS` — understating personal data,
|
|
145
|
+
* which is the dangerous direction for a check whose whole job is to refuse a false negative claim.
|
|
146
|
+
*
|
|
147
|
+
* The never-scrub floor is excluded on the same terms as the scrub patch: a scope FK or
|
|
148
|
+
* `createdByUserId` links a row to a person without being personal data the row holds, and every mode
|
|
149
|
+
* preserves it — so its presence is no evidence against `RETAIN_ONLY`.
|
|
150
|
+
*/
|
|
151
|
+
export function collectDeclaredPersonalDataFields(mainSchema) {
|
|
152
|
+
const shape = getMergedObjectOrUnionShape(mainSchema);
|
|
153
|
+
const declared = [];
|
|
154
|
+
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
155
|
+
if (isImpersonalizeNeverScrubFloorField(fieldName))
|
|
156
|
+
continue;
|
|
157
|
+
const categories = getDataCategories(fieldSchema);
|
|
158
|
+
if (categories !== undefined && categories.length > 0)
|
|
159
|
+
declared.push(fieldName);
|
|
160
|
+
}
|
|
161
|
+
return declared;
|
|
162
|
+
}
|
|
43
163
|
/**
|
|
44
164
|
* Synthesize the field-scrub `$set` patch for an impersonalize-in-place write, from a resource's
|
|
45
165
|
* per-field `.impersonalizeWith()` treatments. Returns ONLY the scrubbed FIELDS — the impersonalize
|
|
@@ -81,6 +201,9 @@ export function buildImpersonalizeScrubPatch(mainSchema) {
|
|
|
81
201
|
case RedactionType.MASK:
|
|
82
202
|
patch[fieldName] = resolveImpersonalizeMaskValue(fieldSchema);
|
|
83
203
|
break;
|
|
204
|
+
case RedactionType.RESET:
|
|
205
|
+
patch[fieldName] = resolveImpersonalizeResetValue(fieldSchema, fieldName);
|
|
206
|
+
break;
|
|
84
207
|
case RedactionType.HASH:
|
|
85
208
|
throw new Error(`[impersonalize] HASH treatment on '${fieldName}' is value-dependent and not supported in v1 ` +
|
|
86
209
|
`(a static $set cannot hash per-row) — use REMOVE/MASK/KEEP, or add the per-doc/pipeline scrub path.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impersonalization-scrub.shared.utils.js","sourceRoot":"","sources":["../../../../../src/compliance/privacy/impersonalization-scrub.shared.utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAC7H,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,iCAAiC,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAEnH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,UAAU,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,UAAU,6BAA6B,CAAC,WAAyB;IACrE,OAAO,yBAAyB,CAAC,WAAW,CAAC,IAAI,2BAA2B,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mCAAmC,CAAC,SAAiB;IACnE,IAAI,SAAS,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,KAAK,GAAG,iCAAiC,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,KAAK,KAAK,oBAAoB,CAAC,aAAa;WAC5C,KAAK,KAAK,oBAAoB,CAAC,WAAW,CAAC;IAClD,uEAAuE;AACzE,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAAwB;IACnE,kGAAkG;IAClG,oGAAoG;IACpG,mGAAmG;IACnG,kGAAkG;IAClG,cAAc;IACd,MAAM,KAAK,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAG,yBAAyB,CAAC,WAA2B,CAAC,CAAC;QACzE,IAAI,SAAS,KAAK,SAAS;YAAE,SAAS,CAAC,wDAAwD;QAE/F,0FAA0F;QAC1F,IAAI,mCAAmC,CAAC,SAAS,CAAC;YAAE,SAAS;QAE7D,QAAQ,SAA0B,EAAE,CAAC;YACnC,KAAK,aAAa,CAAC,IAAI;gBACrB,SAAS,CAAC,uBAAuB;YACnC,KAAK,aAAa,CAAC,MAAM;gBACvB,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;gBACxB,MAAM;YACR,KAAK,aAAa,CAAC,IAAI;gBACrB,KAAK,CAAC,SAAS,CAAC,GAAG,6BAA6B,CAAC,WAA2B,CAAC,CAAC;gBAC9E,MAAM;YACR,KAAK,aAAa,CAAC,IAAI;gBACrB,MAAM,IAAI,KAAK,CACb,sCAAsC,SAAS,+CAA+C;oBAC9F,qGAAqG,CACtG,CAAC;YACJ,KAAK,aAAa,CAAC,OAAO;gBACxB,MAAM,IAAI,KAAK,CACb,yCAAyC,SAAS,oDAAoD;oBACtG,gGAAgG,CACjG,CAAC;YACJ;gBACE,+FAA+F;gBAC/F,yFAAyF;gBACzF,MAAM,IAAI,KAAK,CAAC,wDAAwD,SAAS,SAAS,SAAS,IAAI,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { z } from 'zod';\nimport { 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 */\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 * 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.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":"AACA,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAChJ,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,iCAAiC,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAEnH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,UAAU,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,UAAU,6BAA6B,CAAC,WAAyB;IACrE,OAAO,yBAAyB,CAAC,WAAW,CAAC,IAAI,2BAA2B,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;GAUG;AACH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,8BAA8B,CAAC,WAAyB,EAAE,SAAiB;IACzF,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,uCAAuC,SAAS,iEAAiE;YACjH,kGAAkG;YAClG,4FAA4F,CAC7F,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH;;;;;;;;;OASG;IACH,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,uCAAuC,SAAS,6DAA6D;YAC7G,6GAA6G;YAC7G,4GAA4G;YAC5G,uDAAuD,CACxD,CAAC;IACJ,CAAC;IAED,MAAM,0BAA0B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACvD,IAAI,MAAM,CAAC,IAAI,YAAY,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,0BAA0B,EAAE,CAAC;QAC7G,MAAM,IAAI,KAAK,CACb,uCAAuC,SAAS,6DAA6D;YAC7G,+GAA+G;YAC/G,2GAA2G;YAC3G,0GAA0G;YAC1G,4GAA4G;YAC5G,2GAA2G;YAC3G,wCAAwC,CACzC,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,mCAAmC,CAAC,SAAiB;IACnE,IAAI,SAAS,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,KAAK,GAAG,iCAAiC,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,KAAK,KAAK,oBAAoB,CAAC,aAAa;WAC5C,KAAK,KAAK,oBAAoB,CAAC,WAAW,CAAC;IAClD,uEAAuE;AACzE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,iCAAiC,CAAC,UAAwB;IACxE,MAAM,KAAK,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,IAAI,mCAAmC,CAAC,SAAS,CAAC;YAAE,SAAS;QAC7D,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAA2B,CAAC,CAAC;QAClE,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAAwB;IACnE,kGAAkG;IAClG,oGAAoG;IACpG,mGAAmG;IACnG,kGAAkG;IAClG,cAAc;IACd,MAAM,KAAK,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAG,yBAAyB,CAAC,WAA2B,CAAC,CAAC;QACzE,IAAI,SAAS,KAAK,SAAS;YAAE,SAAS,CAAC,wDAAwD;QAE/F,0FAA0F;QAC1F,IAAI,mCAAmC,CAAC,SAAS,CAAC;YAAE,SAAS;QAE7D,QAAQ,SAA0B,EAAE,CAAC;YACnC,KAAK,aAAa,CAAC,IAAI;gBACrB,SAAS,CAAC,uBAAuB;YACnC,KAAK,aAAa,CAAC,MAAM;gBACvB,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;gBACxB,MAAM;YACR,KAAK,aAAa,CAAC,IAAI;gBACrB,KAAK,CAAC,SAAS,CAAC,GAAG,6BAA6B,CAAC,WAA2B,CAAC,CAAC;gBAC9E,MAAM;YACR,KAAK,aAAa,CAAC,KAAK;gBACtB,KAAK,CAAC,SAAS,CAAC,GAAG,8BAA8B,CAAC,WAA2B,EAAE,SAAS,CAAC,CAAC;gBAC1F,MAAM;YACR,KAAK,aAAa,CAAC,IAAI;gBACrB,MAAM,IAAI,KAAK,CACb,sCAAsC,SAAS,+CAA+C;oBAC9F,qGAAqG,CACtG,CAAC;YACJ,KAAK,aAAa,CAAC,OAAO;gBACxB,MAAM,IAAI,KAAK,CACb,yCAAyC,SAAS,oDAAoD;oBACtG,gGAAgG,CACjG,CAAC;YACJ;gBACE,+FAA+F;gBAC/F,yFAAyF;gBACzF,MAAM,IAAI,KAAK,CAAC,wDAAwD,SAAS,SAAS,SAAS,IAAI,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC","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"]}
|
|
@@ -28,9 +28,17 @@ export declare enum RetentionStatus {
|
|
|
28
28
|
ACTIVE = "active",
|
|
29
29
|
/**
|
|
30
30
|
* Impersonalized-and-retained — personal fields scrubbed in place, the row kept for a
|
|
31
|
-
* retention obligation
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* retention obligation: hidden and immutable to normal callers, readable only via the audited
|
|
32
|
+
* `seeRetained` see-through path, disposable only by a privileged system op.
|
|
33
|
+
*
|
|
34
|
+
* ENFORCED, not intended. This said "enforcement wired in a later phase" long after the phase
|
|
35
|
+
* landed, which is worth correcting rather than deleting: a reader deciding whether to trust the
|
|
36
|
+
* marker would have concluded the row was still visible. The rule has one semantic authority —
|
|
37
|
+
* `compliance/privacy/retention-hide-predicate.backend` — consumed by both persistence adapters,
|
|
38
|
+
* the aggregation/charts surface and RAG retrieval, and a guard test fails the suite if any site
|
|
39
|
+
* hand-writes the predicate again. That single-authority shape exists because the duplicated
|
|
40
|
+
* version produced two recovered defects: retained rows still counted in every chart, and the
|
|
41
|
+
* Mongo/Postgres compilers silently disagreed about which rows a NULL marker selected.
|
|
34
42
|
*/
|
|
35
43
|
RETAINED = "retained"
|
|
36
44
|
}
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|
|
@@ -29,9 +29,17 @@ export var RetentionStatus;
|
|
|
29
29
|
RetentionStatus["ACTIVE"] = "active";
|
|
30
30
|
/**
|
|
31
31
|
* Impersonalized-and-retained — personal fields scrubbed in place, the row kept for a
|
|
32
|
-
* retention obligation
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* retention obligation: hidden and immutable to normal callers, readable only via the audited
|
|
33
|
+
* `seeRetained` see-through path, disposable only by a privileged system op.
|
|
34
|
+
*
|
|
35
|
+
* ENFORCED, not intended. This said "enforcement wired in a later phase" long after the phase
|
|
36
|
+
* landed, which is worth correcting rather than deleting: a reader deciding whether to trust the
|
|
37
|
+
* marker would have concluded the row was still visible. The rule has one semantic authority —
|
|
38
|
+
* `compliance/privacy/retention-hide-predicate.backend` — consumed by both persistence adapters,
|
|
39
|
+
* the aggregation/charts surface and RAG retrieval, and a guard test fails the suite if any site
|
|
40
|
+
* hand-writes the predicate again. That single-authority shape exists because the duplicated
|
|
41
|
+
* version produced two recovered defects: retained rows still counted in every chart, and the
|
|
42
|
+
* Mongo/Postgres compilers silently disagreed about which rows a NULL marker selected.
|
|
35
43
|
*/
|
|
36
44
|
RetentionStatus["RETAINED"] = "retained";
|
|
37
45
|
})(RetentionStatus || (RetentionStatus = {}));
|
|
@@ -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,eAUX;AAVD,WAAY,eAAe;IACzB,sDAAsD;IACtD,oCAAiB,CAAA;IACjB;;;;;OAKG;IACH,wCAAqB,CAAA;AACvB,CAAC,EAVW,eAAe,KAAf,eAAe,QAU1B;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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. Intended semantics (enforcement wired in a later phase): hidden\n * and immutable to normal callers; readable only via the audited see-through path;\n * disposable only by a privileged system op.\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/**\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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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/**\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,94 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* What is wrong with `slug` as a jurisdiction slug, or `null` when nothing is.
|
|
4
|
+
*
|
|
5
|
+
* Exported as a FUNCTION rather than only as a schema because the consumers that matter do not parse
|
|
6
|
+
* — the governed-document publication validator and the `_core` compliance-document candidate
|
|
7
|
+
* validator both emit their own typed issue records, and routing them through a Zod error to recover
|
|
8
|
+
* a message is how two surfaces come to disagree about what a jurisdiction is. One rule, three
|
|
9
|
+
* readers.
|
|
10
|
+
*/
|
|
11
|
+
export declare function jurisdictionSlugProblem(slug: string): string | null;
|
|
12
|
+
export declare const JurisdictionSlugSchema: z.ZodString;
|
|
13
|
+
export type JurisdictionSlug = z.infer<typeof JurisdictionSlugSchema>;
|
|
14
|
+
/**
|
|
15
|
+
* The namespace every jurisdiction REFERENCE carries.
|
|
16
|
+
*
|
|
17
|
+
* A ref is `jurisdiction:<slug>`, and both halves are checked, because checking only the namespace is
|
|
18
|
+
* what let `jurisdiction:united-kingdom` — a value {@link JurisdictionSlugSchema} would refuse
|
|
19
|
+
* outright — sit in a landed application specification beside that same application's configuration
|
|
20
|
+
* declaring `gb`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const JURISDICTION_REF_NAMESPACE = "jurisdiction:";
|
|
23
|
+
/** Which half of a `jurisdiction:<slug>` ref is wrong. The two are separate failures with separate remedies. */
|
|
24
|
+
export declare enum JurisdictionRefProblemScope {
|
|
25
|
+
/** The ref is not in the `jurisdiction:` namespace, so it resolves against a different vocabulary entirely. */
|
|
26
|
+
NAMESPACE = "NAMESPACE",
|
|
27
|
+
/** The namespace is right and the slug is not a jurisdiction. */
|
|
28
|
+
SLUG = "SLUG"
|
|
29
|
+
}
|
|
30
|
+
export interface JurisdictionRefProblem {
|
|
31
|
+
readonly scope: JurisdictionRefProblemScope;
|
|
32
|
+
readonly message: string;
|
|
33
|
+
}
|
|
34
|
+
/** What is wrong with `ref` as a `jurisdiction:<slug>` reference, or `null` when nothing is. */
|
|
35
|
+
export declare function jurisdictionRefProblem(ref: string): JurisdictionRefProblem | null;
|
|
36
|
+
/** `jurisdiction:<slug>`, with the slug held to the same rule as a declared operating jurisdiction. */
|
|
37
|
+
export declare const JurisdictionRefSchema: z.ZodString;
|
|
38
|
+
/**
|
|
39
|
+
* One jurisdiction this application operates in, and why it reaches the product.
|
|
40
|
+
*
|
|
41
|
+
* `basis` is REQUIRED, and it is the half that makes the declaration mean anything — the same
|
|
42
|
+
* argument the sibling schemas make for `assessmentNote` on a legitimate-interests basis and for
|
|
43
|
+
* `gatedProcessing` on a consent gate. "eu" alone does not say whether the operator is established
|
|
44
|
+
* there, sells there, or merely holds data about people there, and those imply different obligations.
|
|
45
|
+
*
|
|
46
|
+
* It is free prose deliberately. Nothing structured exists to key it to, and inventing a closed
|
|
47
|
+
* vocabulary of reasons would be a legal taxonomy nobody reviewed.
|
|
48
|
+
*/
|
|
49
|
+
export declare const OperatingJurisdictionSchema: z.ZodObject<{
|
|
50
|
+
jurisdictionSlug: z.ZodString;
|
|
51
|
+
/** Why this jurisdiction reaches the product — "customers established here", "data subjects resident here". */
|
|
52
|
+
basis: z.ZodString;
|
|
53
|
+
}, z.core.$strict>;
|
|
54
|
+
export type OperatingJurisdiction = z.infer<typeof OperatingJurisdictionSchema>;
|
|
55
|
+
/**
|
|
56
|
+
* The jurisdictions this application operates in.
|
|
57
|
+
*
|
|
58
|
+
* ## Absent is UNDECLARED, and an empty list is not offered
|
|
59
|
+
*
|
|
60
|
+
* The sibling `clientStorage` inventory distinguishes absent ("not inventoried") from an empty array
|
|
61
|
+
* ("this surface sets nothing"), because there both are meaningful. Here only one is: every product
|
|
62
|
+
* operates somewhere, so an empty list would be a claim nobody could mean. `min(1)` therefore refuses
|
|
63
|
+
* it, and the whole declaration stays optional at the configuration level — absence is the honest
|
|
64
|
+
* "nobody has answered", and every consumer must render it as that rather than as "nowhere".
|
|
65
|
+
*/
|
|
66
|
+
export declare const ApplicationOperatingJurisdictionsSchema: z.ZodObject<{
|
|
67
|
+
jurisdictions: z.ZodArray<z.ZodObject<{
|
|
68
|
+
jurisdictionSlug: z.ZodString;
|
|
69
|
+
/** Why this jurisdiction reaches the product — "customers established here", "data subjects resident here". */
|
|
70
|
+
basis: z.ZodString;
|
|
71
|
+
}, z.core.$strict>>;
|
|
72
|
+
}, z.core.$strict>;
|
|
73
|
+
export type ApplicationOperatingJurisdictions = z.infer<typeof ApplicationOperatingJurisdictionsSchema>;
|
|
74
|
+
/**
|
|
75
|
+
* Which jurisdictions a broader one contains, so a source addressing the broader one answers for them.
|
|
76
|
+
*
|
|
77
|
+
* Without this, an application declaring `fr` would be reported as uncovered while the GDPR source
|
|
78
|
+
* plainly reaches it — over-warning, which is the failure mode that trains a reader to skim past the
|
|
79
|
+
* warnings that matter. Subdivisions need no table: `us-ca` is contained by `us` by construction, and
|
|
80
|
+
* that rule is applied in code rather than enumerated here.
|
|
81
|
+
*
|
|
82
|
+
* ⚠️ EU membership is a legal fact with a review trigger, not a convenience list: it changes when a
|
|
83
|
+
* state accedes or withdraws, and it has done both. Verified against the 27 members as of 2026-09-02.
|
|
84
|
+
* Nothing derives it, so a change is a deliberate edit here.
|
|
85
|
+
*/
|
|
86
|
+
export declare const JURISDICTION_CONTAINMENT: Readonly<Record<string, readonly string[]>>;
|
|
87
|
+
/**
|
|
88
|
+
* Does a source addressing `reach` answer for an application operating in `declared`?
|
|
89
|
+
*
|
|
90
|
+
* Three ways, and the order is deliberate — exact first, because it is the common case and the other
|
|
91
|
+
* two are refinements of it.
|
|
92
|
+
*/
|
|
93
|
+
export declare function jurisdictionReachCovers(reach: string, declared: string): boolean;
|
|
94
|
+
//# sourceMappingURL=operating-jurisdictions.shared.schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operating-jurisdictions.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/compliance/privacy/operating-jurisdictions.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAqExB;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAanE;AAED,eAAO,MAAM,sBAAsB,aAQ/B,CAAC;AACL,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,kBAAkB,CAAC;AAE1D,gHAAgH;AAChH,oBAAY,2BAA2B;IACrC,+GAA+G;IAC/G,SAAS,cAAc;IACvB,iEAAiE;IACjE,IAAI,SAAS;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,2BAA2B,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,gGAAgG;AAChG,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CASjF;AAED,uGAAuG;AACvG,eAAO,MAAM,qBAAqB,aAQ9B,CAAC;AAEL;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B;;IAEtC,+GAA+G;;kBAE/G,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uCAAuC;;;QAhBlD,+GAA+G;;;kBAgC7G,CAAC;AACL,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uCAAuC,CAAC,CAAC;AAExG;;;;;;;;;;;GAWG;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,CAOhF"}
|