@wildo-ai/saas-models 1.1.2 → 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 +14 -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-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 +3 -3
- 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 +1 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.js +15 -1
- package/dist/esm/billing/subscription.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/billing/usage-record.shared.schemas.d.ts +7 -3
- package/dist/esm/billing/usage-record.shared.schemas.d.ts.map +1 -1
- package/dist/esm/billing/usage-record.shared.schemas.js +22 -3
- 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-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 +480 -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 +547 -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 +82 -3
- package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.js.map +1 -1
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts +31 -30
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.js +98 -3
- package/dist/esm/compliance/privacy/operating-jurisdictions.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 +82 -29
- package/dist/esm/compliance/privacy/redaction.shared.schemas.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/redaction.shared.schemas.js +95 -29
- 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 +7 -5
- package/dist/esm/config/app-configuration-shared.shared.schemas.d.ts.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/errors/errors.custom-message-ref.shared.definitions.d.ts +28 -0
- 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 +28 -0
- 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 +45 -12
- 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 +103 -58
- package/dist/esm/external-providers/engine-capabilities.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/engine-capabilities.shared.schemas.js +176 -15
- 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 -5
- 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 +83 -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 +5 -28
- package/dist/esm/external-providers/provider-capability.shared.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/provider-capability.shared.schemas.js +4 -2
- 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/files/file-upload-grant.shared.schemas.d.ts +14 -2
- package/dist/esm/files/file-upload-grant.shared.schemas.d.ts.map +1 -1
- package/dist/esm/files/file-upload-grant.shared.schemas.js +44 -5
- package/dist/esm/files/file-upload-grant.shared.schemas.js.map +1 -1
- package/dist/esm/files/files.shared.schemas.d.ts +15 -8
- package/dist/esm/files/files.shared.schemas.d.ts.map +1 -1
- package/dist/esm/files/files.shared.schemas.js +15 -8
- package/dist/esm/files/files.shared.schemas.js.map +1 -1
- package/dist/esm/flows-actors/actors.shared.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/actors.shared.schemas.js +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.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 +40 -3
- package/dist/esm/flows-actors/flows-actors-execution.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.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/progression-state.shared.resources-config.schemas.d.ts +8 -0
- package/dist/esm/guidance/progression-state.shared.resources-config.schemas.d.ts.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 +49 -0
- 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 +320 -50
- 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 +137 -36
- package/dist/esm/http-api-binding/http-api-binding.shared.schemas.js.map +1 -1
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +9 -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/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/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-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 +18 -3
- 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 +6 -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 +27 -4
- package/dist/esm/requests/websocket.shared.schemas.d.ts.map +1 -1
- package/dist/esm/requests/websocket.shared.schemas.js +35 -0
- package/dist/esm/requests/websocket.shared.schemas.js.map +1 -1
- 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 +105 -20
- package/dist/esm/resources/resources-config.shared.factory.js.map +1 -1
- package/dist/esm/resources/resources-config.shared.schemas.d.ts +254 -72
- package/dist/esm/resources/resources-config.shared.schemas.d.ts.map +1 -1
- package/dist/esm/resources/resources-config.shared.schemas.js.map +1 -1
- package/dist/esm/resources/resources-registry.shared.core.definitions.d.ts.map +1 -1
- package/dist/esm/resources/resources-registry.shared.core.definitions.js +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-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 +84 -5
- package/dist/esm/security/authentications/authentication.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/authentication.shared.schemas.js +83 -3
- package/dist/esm/security/authentications/authentication.shared.schemas.js.map +1 -1
- 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/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.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.js +27 -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 +52 -7
- 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 +45 -8
- package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.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 +6 -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 +31 -0
- package/dist/esm/security/oauth-clients/oauth-clients.shared.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 +24 -3
- package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.js.map +1 -1
- package/dist/esm/users/user-preferences.shared.resources-config.schemas.d.ts +4 -4
- package/dist/esm/users/user-self-preferences.shared.resources-config.schemas.d.ts +4 -4
- 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 +43 -12
- package/dist/esm/users/users.shared.schemas.d.ts.map +1 -1
- package/dist/esm/users/users.shared.schemas.js +38 -7
- package/dist/esm/users/users.shared.schemas.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sso-connection.shared.schemas.js","sourceRoot":"","sources":["../../../../../../src/security/authentications/sso/sso-connection.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SSO Connection Schema (Shared) — Polymorphic\n *\n * Individual SSO provider connections with protocol discriminator (OIDC vs SAML).\n * Unified resource — `protocol` field determines which sub-object is populated.\n * Both OIDC and SAML protocol engines consume this shared discriminator.\n * Scope FK (organizationId / applicationId) is injected by the polymorphism engine.\n *\n * @see auth-data-model-audit.md §2B\n */\n\nimport { z } from 'zod';\nimport { AUTH_SCOPE_VARIANTS } from '../authentication.shared.schemas';\nimport { declarePolymorphicSchemas, optOutPolymorphicAutoBusinessKey } from '../../../resources/utils/resource-polymorphism.schemas';\n\n/** Interactive single-sign-on protocols supported by an SSO connection. */\nexport enum SsoProtocol {\n OIDC = 'oidc',\n SAML = 'saml',\n}\n\nexport const SSOTemplateMode = {\n TEMPLATE: 'template',\n DISCOVERY: 'discovery',\n MANUAL: 'manual',\n} as const;\n\nexport const SSOResponseType = {\n CODE: 'code',\n ID_TOKEN: 'id_token',\n TOKEN: 'token',\n} as const;\n\nexport const SSOResponseMode = {\n QUERY: 'query',\n FRAGMENT: 'fragment',\n FORM_POST: 'form_post',\n} as const;\n\nexport const SSOPrompt = {\n NONE: 'none',\n LOGIN: 'login',\n CONSENT: 'consent',\n SELECT_ACCOUNT: 'select_account',\n} as const;\n\nexport const SSOPKCEMethod = {\n S256: 'S256',\n PLAIN: 'plain',\n} as const;\n\nexport const SamlNameIdFormat = {\n UNSPECIFIED: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',\n EMAIL_ADDRESS: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',\n PERSISTENT: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',\n TRANSIENT: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',\n} as const;\n\nexport const SsoConnectionBaseSchema = z.object({\n _id: z.string().min(1).isPrimaryKey().isSummaryField(),\n\n protocol: z.enum(SsoProtocol).isSummaryField(),\n externalProviderId: z.string().min(1).optional(),\n displayName: z.string().min(1).isSummaryField(),\n // `.isAuditEvidence()` — `enabled` is the connection's live/dead switch and `isDefault` decides\n // which IdP silently receives logins. Marked individually rather than on any parent: this\n // schema carries `x509Certificates` under `.isBackendOnly()`, and marking a container records\n // the WHOLE object into rows that replicate to an unerasable ledger.\n // assurance-control: WILDO.IDENTITY.SESSION_ASSURANCE — the live/dead switch and the default IdP\n // decide which identity provider is trusted to authenticate this tenant.\n enabled: z.boolean().default(true).isSummaryField().isAuditEvidence(),\n isDefault: z.boolean().default(false).isAuditEvidence(),\n\n // `.isAuditEvidence()` on the SAML leaves below — they say WHERE this connection federates\n // (`entityId` / `ssoUrl` / `sloUrl`) and HOW strictly it validates the IdP (`signRequests`,\n // `wantAssertionsSigned`, `allowedClockDrift`, `forceAuthn`, `maxAuthAge`, `nameIdFormat`,\n // `allowIdpInitiated`). A silent change here redirects the trust anchor or accepts unsigned/replayed\n // assertions — an authentication-assurance change the field NAME alone cannot evidence — so a\n // reviewer must see the before/after value. Marked per LEAF, never on the `saml` container: the\n // certificate material (`x509Certificates` / `x509CertificatePem`) sits beside these and marking the\n // container would copy key material into an unerasable ledger. The two-level `attributeMapping` /\n // `auditSettings` leaves are deliberately NOT marked — the evidence resolver reaches one level of\n // nesting only, so a marker there would be inert.\n // assurance-control: WILDO.IDENTITY.SESSION_ASSURANCE — the IdP endpoints and signature/replay\n // validation posture decide which provider is trusted to authenticate this tenant and whether its\n // assertions are actually verified.\n saml: z.object({\n entityId: z.string().min(1).isAuditEvidence(),\n ssoUrl: z.url().isAuditEvidence(),\n sloUrl: z.url().optional().isAuditEvidence(),\n /** Frontend input: PEM-encoded certificate(s). Backend transforms to x509Certificates. */\n x509CertificatePem: z.string().min(1).optional(),\n x509Certificates: z.array(z.string()).min(1).isBackendOnly(),\n attributeMapping: z.object({\n email: z.string().default('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'),\n firstName: z.string().default('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'),\n lastName: z.string().default('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'),\n roles: z.string().optional(),\n department: z.string().optional(),\n employeeId: z.string().optional(),\n groups: z.string().optional(),\n }),\n signRequests: z.boolean().default(true).isAuditEvidence(),\n wantAssertionsSigned: z.boolean().default(true).isAuditEvidence(),\n allowedClockDrift: z.number().min(0).max(300).default(30).isAuditEvidence(),\n forceAuthn: z.boolean().default(false).isAuditEvidence(),\n maxAuthAge: z.number().min(0).optional().isAuditEvidence(),\n nameIdFormat: z.enum(SamlNameIdFormat).default(SamlNameIdFormat.EMAIL_ADDRESS).isAuditEvidence(),\n allowIdpInitiated: z.boolean().default(false).isAuditEvidence(),\n auditSettings: z.object({\n logAuthAttempts: z.boolean().default(true),\n logAttributeMapping: z.boolean().default(true),\n retentionDays: z.number().min(1).max(2555).default(90),\n }),\n }).optional(),\n\n // `.isAuditEvidence()` on the OIDC leaves below — like the SAML block, they say WHERE this connection\n // federates (`discoveryUrl` / `issuer` / the four endpoints / `jwksUri` / `endSessionEndpoint` /\n // `clientId`) and HOW strictly it validates tokens (`validateIssuer`, `validateAudience`,\n // `clockTolerance`, `pkceEnabled`, `pkceMethod`), plus what it requests (`scopes` / `customScopes` /\n // `responseType` / `responseMode` / template + auth-request shaping). Turning `validateIssuer` /\n // `validateAudience` / `pkceEnabled` off, or repointing `issuer` / `jwksUri`, silently breaks the\n // token trust chain, so a reviewer must see the before/after. `clientSecret` is NEVER marked (it is\n // a write-only secret); `claimsMapping` / `auditSettings` are two-level and out of the resolver's\n // one-level reach.\n // assurance-control: WILDO.IDENTITY.SESSION_ASSURANCE — the OIDC endpoints, issuer and token-\n // validation posture decide which provider is trusted and whether its tokens are actually verified.\n oidc: z.object({\n templateMode: z.enum(SSOTemplateMode).default(SSOTemplateMode.MANUAL).isAuditEvidence(),\n templateOverrides: z.record(z.string(), z.string()).optional().isAuditEvidence(),\n customScopes: z.array(z.string()).optional().isAuditEvidence(),\n discoveryUrl: z.url().optional().isAuditEvidence(),\n issuer: z.url().optional().isAuditEvidence(),\n authorizationEndpoint: z.url().optional().isAuditEvidence(),\n tokenEndpoint: z.url().optional().isAuditEvidence(),\n userInfoEndpoint: z.url().optional().isAuditEvidence(),\n jwksUri: z.url().optional().isAuditEvidence(),\n endSessionEndpoint: z.url().optional().isAuditEvidence(),\n clientId: z.string().min(1).isAuditEvidence(),\n /**\n * OIDC/OAuth2 client secret issued by the IdP, used by the backend token\n * exchange (`oauth2-connection-resolver` → `exchangeCodeForTokens`) to\n * authenticate this connection at the provider's token endpoint.\n *\n * `.isWriteOnlySecret()` gives it the framework's write-then-masked contract:\n * the operator sets/rotates it (stays in the CREATE/UPDATE request DTO) and it\n * stays in the response DTO so the UI renders a masked placeholder, but the\n * framework redacts it to `••••••••` at the client-serialization boundary only\n * — internal reads (`servicesRegistryHandler.read` during token exchange) keep\n * the real value. Do NOT use `.isBackendOnly()`: that strips the field from\n * every client DTO, so the operator could never supply it.\n *\n * Preservation on UPDATE is NOT automatic here: this is a nested field, and the\n * repository UPDATE is a whole-subdocument `$set` (no deep merge), so a\n * round-tripped mask must be re-injected from the stored record by the SSO\n * connection UPDATE custom-impl (`sso-connection.custom-impl` prefix). The\n * central sentinel-strip only preserves TOP-LEVEL write-only secrets.\n */\n clientSecret: z.string().min(1).isWriteOnlySecret(),\n scopes: z.array(z.string()).default(['openid', 'email', 'profile']).isAuditEvidence(),\n responseType: z.enum(SSOResponseType).default(SSOResponseType.CODE).isAuditEvidence(),\n responseMode: z.enum(SSOResponseMode).optional().isAuditEvidence(),\n claimsMapping: z.object({\n email: z.string().default('email'),\n firstName: z.string().default('given_name'),\n lastName: z.string().default('family_name'),\n roles: z.string().optional(),\n department: z.string().optional(),\n employeeId: z.string().optional(),\n groups: z.string().optional(),\n }),\n validateIssuer: z.boolean().default(true).isAuditEvidence(),\n validateAudience: z.boolean().default(true).isAuditEvidence(),\n clockTolerance: z.number().min(0).max(300).default(30).isAuditEvidence(),\n acrValues: z.array(z.string()).optional().isAuditEvidence(),\n maxAge: z.number().min(0).optional().isAuditEvidence(),\n prompt: z.enum(SSOPrompt).optional().isAuditEvidence(),\n pkceEnabled: z.boolean().default(true).isAuditEvidence(),\n pkceMethod: z.enum(SSOPKCEMethod).default(SSOPKCEMethod.S256).isAuditEvidence(),\n auditSettings: z.object({\n logAuthAttempts: z.boolean().default(true),\n logTokenExchange: z.boolean().default(true),\n logClaimsMapping: z.boolean().default(true),\n retentionDays: z.number().min(1).max(2555).default(90),\n }),\n }).optional(),\n\n autoCreateUsers: z.boolean().default(true),\n autoVerifyEmail: z.boolean().default(true),\n /** W2.8: if true, users authenticating via this SSO connection skip the application-level MFA policy. */\n // `.isAuditEvidence()` — an explicit escape from the application MFA policy for everyone who\n // authenticates through this connection. Flipping it on lowers the assurance level tenant-wide.\n bypassAppMFA: z.boolean().default(false).isAuditEvidence(),\n // `.isAuditEvidence()` on all four — this is the connection's ROLE-GRANT surface. `defaultRole`\n // and the two mappings decide what authority an externally-authenticated identity lands with,\n // and `allowedDomains` decides whose identities the connection will accept at all. A change\n // here is an authorization change; the field NAME alone cannot evidence it.\n // The values are role names and domains — configuration, not personal data.\n // assurance-control: WILDO.ACCESS.PRIVILEGE_EVIDENCE — these decide what authority an\n // externally-authenticated identity lands with, and whose identities are accepted.\n defaultRole: z.string().optional().isAuditEvidence(),\n allowedDomains: z.array(z.string()).default([]).isDBIndexed().isAuditEvidence(),\n roleMapping: z.record(z.string(), z.string()).optional().isAuditEvidence(),\n groupMapping: z.record(z.string(), z.array(z.string())).optional().isAuditEvidence(),\n\n createdAt: z.date().default(() => new Date()).excludeFromCreate().excludeFromUpdate(),\n updatedAt: z.date().default(() => new Date()).excludeFromCreate().excludeFromUpdate(),\n});\n// NOTE: Protocol-config discriminant enforcement (protocol=saml → saml defined, protocol=oidc → oidc defined)\n// is validated at the backend service layer, not via .refine() here.\n// Zod 4 doesn't allow .extend() on refined objects, which breaks the polymorphism engine.\n\n\nexport type SsoConnectionBase = z.infer<typeof SsoConnectionBaseSchema>;\n\nexport const ssoConnectionPolymorphicDeclaration = declarePolymorphicSchemas({\n baseResourceType: 'ssoConnections',\n baseFieldIdentifier: 'ssoConnectionId',\n baseEnumKey: 'SSO_CONNECTIONS',\n baseSchema: SsoConnectionBaseSchema,\n // Many connections per scope (LIST/CREATE/UPDATE/DELETE) — opt out of the\n // polymorphism engine's singleton-per-scope business-key auto-default.\n variants: AUTH_SCOPE_VARIANTS.map(optOutPolymorphicAutoBusinessKey),\n});\n"]}
|
|
1
|
+
{"version":3,"file":"sso-connection.shared.schemas.js","sourceRoot":"","sources":["../../../../../../src/security/authentications/sso/sso-connection.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SSO Connection Schema (Shared) — Polymorphic\n *\n * Individual SSO provider connections with protocol discriminator (OIDC vs SAML).\n * Unified resource — `protocol` field determines which sub-object is populated.\n * Both OIDC and SAML protocol engines consume this shared discriminator.\n * Scope FK (organizationId / applicationId) is injected by the polymorphism engine.\n *\n * @see auth-data-model-audit.md §2B\n */\n\nimport { z } from 'zod';\nimport { AUTH_SCOPE_VARIANTS } from '../authentication.shared.schemas';\nimport { declarePolymorphicSchemas, optOutPolymorphicAutoBusinessKey } from '../../../resources/utils/resource-polymorphism.schemas';\n\n/** Interactive single-sign-on protocols supported by an SSO connection. */\nexport enum SsoProtocol {\n OIDC = 'oidc',\n SAML = 'saml',\n}\n\nexport const SSOTemplateMode = {\n TEMPLATE: 'template',\n DISCOVERY: 'discovery',\n MANUAL: 'manual',\n} as const;\n\nexport const SSOResponseType = {\n CODE: 'code',\n ID_TOKEN: 'id_token',\n TOKEN: 'token',\n} as const;\n\nexport const SSOResponseMode = {\n QUERY: 'query',\n FRAGMENT: 'fragment',\n FORM_POST: 'form_post',\n} as const;\n\nexport const SSOPrompt = {\n NONE: 'none',\n LOGIN: 'login',\n CONSENT: 'consent',\n SELECT_ACCOUNT: 'select_account',\n} as const;\n\nexport const SSOPKCEMethod = {\n S256: 'S256',\n PLAIN: 'plain',\n} as const;\n\nexport const SamlNameIdFormat = {\n UNSPECIFIED: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',\n EMAIL_ADDRESS: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',\n PERSISTENT: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',\n TRANSIENT: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',\n} as const;\n\nexport const SsoConnectionBaseSchema = z.object({\n _id: z.string().min(1).isPrimaryKey().isSummaryField(),\n\n protocol: z.enum(SsoProtocol).isSummaryField(),\n externalProviderId: z.string().min(1).optional(),\n displayName: z.string().min(1).isSummaryField(),\n // `.isAuditEvidence()` — `enabled` is the connection's live/dead switch and `isDefault` decides\n // which IdP silently receives logins. Marked individually rather than on any parent: this\n // schema carries `x509Certificates` under `.isBackendOnly()`, and marking a container records\n // the WHOLE object into rows that replicate to an unerasable ledger.\n // assurance-control: WILDO.IDENTITY.SESSION_ASSURANCE — the live/dead switch and the default IdP\n // decide which identity provider is trusted to authenticate this tenant.\n enabled: z.boolean().default(true).isSummaryField().isAuditEvidence(),\n isDefault: z.boolean().default(false).isAuditEvidence(),\n\n // `.isAuditEvidence()` on the SAML leaves below — they say WHERE this connection federates\n // (`entityId` / `ssoUrl` / `sloUrl`) and HOW strictly it validates the IdP (`signRequests`,\n // `wantAssertionsSigned`, `allowedClockDrift`, `forceAuthn`, `maxAuthAge`, `nameIdFormat`,\n // `allowIdpInitiated`). A silent change here redirects the trust anchor or accepts unsigned/replayed\n // assertions — an authentication-assurance change the field NAME alone cannot evidence — so a\n // reviewer must see the before/after value. Marked per LEAF, never on the `saml` container: the\n // certificate material (`x509Certificates` / `x509CertificatePem`) sits beside these and marking the\n // container would copy key material into an unerasable ledger. The two-level `attributeMapping` /\n // `auditSettings` leaves are deliberately NOT marked — the evidence resolver reaches one level of\n // nesting only, so a marker there would be inert.\n // assurance-control: WILDO.IDENTITY.SESSION_ASSURANCE — the IdP endpoints and signature/replay\n // validation posture decide which provider is trusted to authenticate this tenant and whether its\n // assertions are actually verified.\n saml: z.object({\n entityId: z.string().min(1).isAuditEvidence(),\n ssoUrl: z.url().isAuditEvidence(),\n sloUrl: z.url().optional().isAuditEvidence(),\n /** Frontend input: PEM-encoded certificate(s). Backend transforms to x509Certificates. */\n x509CertificatePem: z.string().min(1).optional(),\n x509Certificates: z.array(z.string()).min(1).isBackendOnly(),\n attributeMapping: z.object({\n email: z.string().default('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'),\n firstName: z.string().default('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'),\n lastName: z.string().default('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'),\n roles: z.string().optional(),\n department: z.string().optional(),\n employeeId: z.string().optional(),\n groups: z.string().optional(),\n }),\n signRequests: z.boolean().default(true).isAuditEvidence(),\n wantAssertionsSigned: z.boolean().default(true).isAuditEvidence(),\n allowedClockDrift: z.number().min(0).max(300).default(30).isAuditEvidence(),\n forceAuthn: z.boolean().default(false).isAuditEvidence(),\n maxAuthAge: z.number().min(0).optional().isAuditEvidence(),\n nameIdFormat: z.enum(SamlNameIdFormat).default(SamlNameIdFormat.EMAIL_ADDRESS).isAuditEvidence(),\n allowIdpInitiated: z.boolean().default(false).isAuditEvidence(),\n auditSettings: z.object({\n logAuthAttempts: z.boolean().default(true),\n logAttributeMapping: z.boolean().default(true),\n retentionDays: z.number().min(1).max(2555).default(90),\n }),\n }).optional(),\n\n // `.isAuditEvidence()` on the OIDC leaves below — like the SAML block, they say WHERE this connection\n // federates (`discoveryUrl` / `issuer` / the four endpoints / `jwksUri` / `endSessionEndpoint` /\n // `clientId`) and HOW strictly it validates tokens (`pkceEnabled`, `pkceMethod`), plus what it\n // requests (`scopes` / `customScopes` / `responseType` / `responseMode` / template + auth-request\n // shaping, including the `acrValues` step-up demand). Turning `pkceEnabled` off, or repointing\n // `issuer` / `jwksUri`, silently breaks the token trust chain, so a reviewer must see the\n // before/after — and so does a change to `acrValues`, which is an authentication-strength\n // requirement placed on the identity provider. `clientSecret` is NEVER marked (it is\n // a write-only secret); `claimsMapping` / `auditSettings` are two-level and out of the resolver's\n // one-level reach.\n // assurance-control: WILDO.IDENTITY.SESSION_ASSURANCE — the OIDC endpoints, issuer and token-\n // validation posture decide which provider is trusted and whether its tokens are actually verified.\n oidc: z.object({\n templateMode: z.enum(SSOTemplateMode).default(SSOTemplateMode.MANUAL).isAuditEvidence(),\n templateOverrides: z.record(z.string(), z.string()).optional().isAuditEvidence(),\n customScopes: z.array(z.string()).optional().isAuditEvidence(),\n discoveryUrl: z.url().optional().isAuditEvidence(),\n issuer: z.url().optional().isAuditEvidence(),\n authorizationEndpoint: z.url().optional().isAuditEvidence(),\n tokenEndpoint: z.url().optional().isAuditEvidence(),\n userInfoEndpoint: z.url().optional().isAuditEvidence(),\n jwksUri: z.url().optional().isAuditEvidence(),\n endSessionEndpoint: z.url().optional().isAuditEvidence(),\n clientId: z.string().min(1).isAuditEvidence(),\n /**\n * OIDC/OAuth2 client secret issued by the IdP, used by the backend token\n * exchange (`oauth2-connection-resolver` → `exchangeCodeForTokens`) to\n * authenticate this connection at the provider's token endpoint.\n *\n * `.isWriteOnlySecret()` gives it the framework's write-then-masked contract:\n * the operator sets/rotates it (stays in the CREATE/UPDATE request DTO) and it\n * stays in the response DTO so the UI renders a masked placeholder, but the\n * framework redacts it to `••••••••` at the client-serialization boundary only\n * — internal reads (`servicesRegistryHandler.read` during token exchange) keep\n * the real value. Do NOT use `.isBackendOnly()`: that strips the field from\n * every client DTO, so the operator could never supply it.\n *\n * Preservation on UPDATE is NOT automatic here: this is a nested field, and the\n * repository UPDATE is a whole-subdocument `$set` (no deep merge), so a\n * round-tripped mask must be re-injected from the stored record by the SSO\n * connection UPDATE custom-impl (`sso-connection.custom-impl` prefix). The\n * central sentinel-strip only preserves TOP-LEVEL write-only secrets.\n */\n clientSecret: z.string().min(1).isWriteOnlySecret(),\n scopes: z.array(z.string()).default(['openid', 'email', 'profile']).isAuditEvidence(),\n responseType: z.enum(SSOResponseType).default(SSOResponseType.CODE).isAuditEvidence(),\n responseMode: z.enum(SSOResponseMode).optional().isAuditEvidence(),\n claimsMapping: z.object({\n email: z.string().default('email'),\n firstName: z.string().default('given_name'),\n lastName: z.string().default('family_name'),\n roles: z.string().optional(),\n department: z.string().optional(),\n employeeId: z.string().optional(),\n groups: z.string().optional(),\n }),\n /*\n * NO `validateIssuer` / `validateAudience` / `clockTolerance`. All three were declared here,\n * persisted and audit-marked, and read by nothing — and they were inert in the SAFE direction,\n * which is why they were removed rather than honoured (#419, decided 2026-09-08).\n *\n * `verifyIdToken` ALWAYS verifies the issuer and the audience and hardcodes a five-minute\n * maximum token age. Honouring the three toggles could therefore only ever LOOSEN a guard that\n * is currently unconditional — an operator could switch off issuer or audience validation and\n * break the token trust chain from a settings screen. A configuration field whose only\n * achievable effect is to weaken a security control should not exist.\n */\n acrValues: z.array(z.string()).optional().isAuditEvidence(),\n maxAge: z.number().min(0).optional().isAuditEvidence(),\n prompt: z.enum(SSOPrompt).optional().isAuditEvidence(),\n pkceEnabled: z.boolean().default(true).isAuditEvidence(),\n pkceMethod: z.enum(SSOPKCEMethod).default(SSOPKCEMethod.S256).isAuditEvidence(),\n auditSettings: z.object({\n logAuthAttempts: z.boolean().default(true),\n logTokenExchange: z.boolean().default(true),\n logClaimsMapping: z.boolean().default(true),\n retentionDays: z.number().min(1).max(2555).default(90),\n }),\n }).optional(),\n\n autoCreateUsers: z.boolean().default(true),\n autoVerifyEmail: z.boolean().default(true),\n /** W2.8: if true, users authenticating via this SSO connection skip the application-level MFA policy. */\n // `.isAuditEvidence()` — an explicit escape from the application MFA policy for everyone who\n // authenticates through this connection. Flipping it on lowers the assurance level tenant-wide.\n bypassAppMFA: z.boolean().default(false).isAuditEvidence(),\n // `.isAuditEvidence()` on all four — this is the connection's ROLE-GRANT surface. `defaultRole`\n // and the two mappings decide what authority an externally-authenticated identity lands with,\n // and `allowedDomains` decides whose identities the connection will accept at all. A change\n // here is an authorization change; the field NAME alone cannot evidence it.\n // The values are role names and domains — configuration, not personal data.\n // assurance-control: WILDO.ACCESS.PRIVILEGE_EVIDENCE — these decide what authority an\n // externally-authenticated identity lands with, and whose identities are accepted.\n defaultRole: z.string().optional().isAuditEvidence(),\n allowedDomains: z.array(z.string()).default([]).isDBIndexed().isAuditEvidence(),\n roleMapping: z.record(z.string(), z.string()).optional().isAuditEvidence(),\n groupMapping: z.record(z.string(), z.array(z.string())).optional().isAuditEvidence(),\n\n createdAt: z.date().default(() => new Date()).excludeFromCreate().excludeFromUpdate(),\n updatedAt: z.date().default(() => new Date()).excludeFromCreate().excludeFromUpdate(),\n});\n// NOTE: Protocol-config discriminant enforcement (protocol=saml → saml defined, protocol=oidc → oidc defined)\n// is validated at the backend service layer, not via .refine() here.\n// Zod 4 doesn't allow .extend() on refined objects, which breaks the polymorphism engine.\n\n\nexport type SsoConnectionBase = z.infer<typeof SsoConnectionBaseSchema>;\n\nexport const ssoConnectionPolymorphicDeclaration = declarePolymorphicSchemas({\n baseResourceType: 'ssoConnections',\n baseFieldIdentifier: 'ssoConnectionId',\n baseEnumKey: 'SSO_CONNECTIONS',\n baseSchema: SsoConnectionBaseSchema,\n // Many connections per scope (LIST/CREATE/UPDATE/DELETE) — opt out of the\n // polymorphism engine's singleton-per-scope business-key auto-default.\n variants: AUTH_SCOPE_VARIANTS.map(optOutPolymorphicAutoBusinessKey),\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-access-grants.shared.resources-config.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.resources-config.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA6B,yBAAyB,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAChJ,OAAO,EAAE,qBAAqB,EAAwD,MAAM,mDAAmD,CAAC;AAChJ,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,0CAA0C,CAAC;AAQlD,KAAK,kCAAkC,GACnC,qBAAqB,CAAC,IAAI,GAC1B,qBAAqB,CAAC,IAAI,GAC1B,qBAAqB,CAAC,KAAK,GAC3B,qBAAqB,CAAC,MAAM,GAE5B,qBAAqB,CAAC,WAAW,CAAC;AAEtC,eAAO,MAAM,+DAA+D,GAAI,wBAAwB,oBAAoB,EAAE;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"platform-access-grants.shared.resources-config.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.resources-config.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA6B,yBAAyB,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAChJ,OAAO,EAAE,qBAAqB,EAAwD,MAAM,mDAAmD,CAAC;AAChJ,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,0CAA0C,CAAC;AAQlD,KAAK,kCAAkC,GACnC,qBAAqB,CAAC,IAAI,GAC1B,qBAAqB,CAAC,IAAI,GAC1B,qBAAqB,CAAC,KAAK,GAC3B,qBAAqB,CAAC,MAAM,GAE5B,qBAAqB,CAAC,WAAW,CAAC;AAEtC,eAAO,MAAM,+DAA+D,GAAI,wBAAwB,oBAAoB,EAAE;;;;;;;;;;;;;kBAuU1H,CAAC"}
|
package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.js
CHANGED
|
@@ -269,6 +269,33 @@ export const platformAccessGrantsResourceConfiguration_InitializationFactory = (
|
|
|
269
269
|
* Revoking is monotonic — it only ever removes authority — so admitting the platform side costs
|
|
270
270
|
* nothing the reversibility test would object to.
|
|
271
271
|
*/
|
|
272
|
+
/**
|
|
273
|
+
* ACTIVE → EXPIRED once the window has elapsed, dispatched by the credential-expiry sweep and
|
|
274
|
+
* by nothing else (#413). INTERNAL_CALL: no route, no frontend affordance, and therefore no
|
|
275
|
+
* `admitsCrossTenantPlatformAdministration` — the tenant-boundary question does not arise for
|
|
276
|
+
* an operation no request can reach.
|
|
277
|
+
*
|
|
278
|
+
* The transition precondition lives in the paired implementation, which permits it only from
|
|
279
|
+
* ACTIVE: a grant the tenant DENIED or REVOKED must keep saying so, and relabelling a
|
|
280
|
+
* terminal grant would rewrite the decision history a customer audit reads.
|
|
281
|
+
*/
|
|
282
|
+
[PlatformAccessGrants_Operations.EXPIRE]: {
|
|
283
|
+
variants: [
|
|
284
|
+
{
|
|
285
|
+
variantType: ResourceOperationVariantType.INTERNAL_CALL,
|
|
286
|
+
isDefault: true,
|
|
287
|
+
roles: [CORE_APP_ROLES.APP_ADMIN_SUPER_ADMIN],
|
|
288
|
+
riskLevel: ResourceOperationRiskLevel.LOW,
|
|
289
|
+
resourceOperationLike: CoreResourceOperation.UPDATE,
|
|
290
|
+
// EMPTY BY CONTRACT, not by omission. The credential-expiry sweep dispatches this verb with `{}`
|
|
291
|
+
// and the paired prefix implementation forces the status transition itself, so there is no field
|
|
292
|
+
// a caller may supply. Declaring nothing is NOT the same as declaring this: an operation without
|
|
293
|
+
// a `requestDto` inherits the resource's ENTIRE update contract, which would let an INTERNAL_CALL
|
|
294
|
+
// that accepts nothing advertise every field — `status` included, the one field this verb owns.
|
|
295
|
+
requestDto: z.object({}),
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
},
|
|
272
299
|
[PlatformAccessGrants_Operations.REVOKE]: {
|
|
273
300
|
variants: [
|
|
274
301
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-access-grants.shared.resources-config.schemas.js","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.resources-config.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAChJ,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,kCAAkC,EAAE,MAAM,mDAAmD,CAAC;AAChJ,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,GAE7B,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,0CAA0C,EAAE,MAAM,iDAAiD,CAAC;AAC7G,OAAO,EAAE,wBAAwB,EAAE,MAAM,iDAAiD,CAAC;AAC3F,OAAO,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAC;AAC3H,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,2DAA2D,CAAC;AAW1H,MAAM,CAAC,MAAM,+DAA+D,GAAG,CAAC,sBAA8C,EAAE,EAAE,CAChI,0CAA0C,CAIxC;IACA,UAAU,EAAE,yBAAyB;IACrC,kBAAkB,EAAE,gBAAgB,CAAC,sBAAsB;IAC3D,uBAAuB,EAAE,kCAAkC,CAAC,gBAAgB,CAAC,sBAAsB,CAAC;IACpG,qBAAqB,EAAE,sBAAsB;IAC7C,gBAAgB,EAAE,IAAI;IAEtB;;;;;;;;OAQG;IACH,kBAAkB,EAAE;QAClB,IAAI,EAAE,wBAAwB,CAAC,OAAO;QACtC,IAAI,EAAE,wBAAwB,CAAC,OAAO;QAEtC;;;;;;;;;;;;;;;WAeG;QACH,aAAa,EAAE,wBAAwB,CAAC,SAAS;KAClD;IAED;;;;;;;;;;;;;;OAcG;IACH,eAAe,EAAE;QACf,IAAI,EAAE,oBAAoB,CAAC,wBAAwB;KACpD;IAED;;;OAGG;IACH,iBAAiB,EAAE,EAAE,IAAI,EAAE,uBAAuB,CAAC,YAAY,EAAE;IAEjE,cAAc,EAAE;QACd,qBAAqB,CAAC,IAAI;QAC1B,qBAAqB,CAAC,IAAI;QAC1B,qBAAqB,CAAC,KAAK;QAC3B,oEAAoE;QACpE,qBAAqB,CAAC,WAAW;QACjC,uFAAuF;QACvF,qBAAqB,CAAC,MAAM;KAC7B;IAED,uBAAuB,EAAE;QAEvB;;;;;;;;WAQG;QAEH,CAAC,qBAAqB,CAAC,WAAW,CAAC,EAAE;YAEnC,QAAQ,EAAE,CAAC;oBAET,WAAW,EAAE,4BAA4B,CAAC,aAAa;oBAEvD,SAAS,EAAE,IAAI;oBAEf,KAAK,EAAE,CAAC,cAAc,CAAC,qBAAqB,CAAC;oBAE7C,SAAS,EAAE,0BAA0B,CAAC,QAAQ;iBAE/C,CAAC;SAEH;QAED,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE;YAC5B,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,SAAS,EAAE,IAAI;oBACf,qFAAqF;oBACrF,uFAAuF;oBACvF,yFAAyF;oBACzF,uFAAuF;oBACvF,mBAAmB;oBACnB,KAAK,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;oBACjC,SAAS,EAAE,0BAA0B,CAAC,GAAG;iBAC1C;aACF;SACF;QAED,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE;YAC5B,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;oBACjC,SAAS,EAAE,0BAA0B,CAAC,GAAG;iBAC1C;aACF;SACF;QAED,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE;YAC7B,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;oBACjC,SAAS,EAAE,0BAA0B,CAAC,GAAG;iBAC1C;aACF;SACF;QAED;;;;;;;;;;;;;WAaG;QACH,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE;YAC9B,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,aAAa;oBACvD,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,EAAE;oBACT,SAAS,EAAE,0BAA0B,CAAC,QAAQ;iBAC/C;aACF;SACF;QAED;;;;;;;;;;;;;;WAcG;QACH,CAAC,+BAA+B,CAAC,cAAc,CAAC,EAAE;YAChD,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,CAAC,cAAc,CAAC,qBAAqB,CAAC;oBAC7C,SAAS,EAAE,0BAA0B,CAAC,QAAQ;oBAC9C,qBAAqB,EAAE,qBAAqB,CAAC,MAAM;oBACnD,uCAAuC,EAAE,IAAI;oBAC7C;;;;;;;;;;;;;;;uBAeG;oBACH,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;wBACnB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;wBAC1C,mFAAmF;wBACnF,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;qBACjE,CAAC;iBACH;aACF;YACD,iBAAiB,EAAE;gBACjB;oBACE,uFAAuF;oBACvF,sFAAsF;oBACtF,iEAAiE;oBACjE,MAAM,EAAE,0BAA0B,CAAC,kBAAkB;oBACrD,OAAO,EAAE,2BAA2B,CAAC,KAAK;iBAC3C;aACF;SACF;QAED;;;;;WAKG;QACH,CAAC,+BAA+B,CAAC,OAAO,CAAC,EAAE;YACzC,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;oBACjC,SAAS,EAAE,0BAA0B,CAAC,IAAI;oBAC1C,qBAAqB,EAAE,qBAAqB,CAAC,MAAM;oBACnD,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;wBACnB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;qBAChD,CAAC;oBACF,0FAA0F;oBAC1F,sEAAsE;oBACtE,gBAAgB,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,KAAK,yBAAyB,CAAC,gBAAgB;iBAC7G;aACF;SACF;QAED,CAAC,+BAA+B,CAAC,IAAI,CAAC,EAAE;YACtC,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;oBACjC,SAAS,EAAE,0BAA0B,CAAC,MAAM;oBAC5C,qBAAqB,EAAE,qBAAqB,CAAC,MAAM;oBACnD,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;wBACnB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;qBAChD,CAAC;oBACF,gBAAgB,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,KAAK,yBAAyB,CAAC,gBAAgB;iBAC7G;aACF;SACF;QAED;;;;;;;WAOG;QACH,CAAC,+BAA+B,CAAC,MAAM,CAAC,EAAE;YACxC,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;oBACjC,SAAS,EAAE,0BAA0B,CAAC,MAAM;oBAC5C,qBAAqB,EAAE,qBAAqB,CAAC,MAAM;oBACnD,uCAAuC,EAAE,IAAI;oBAC7C,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;wBACnB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;qBAChD,CAAC;oBACF,gBAAgB,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CACtC,aAAa,CAAC,MAAM,KAAK,yBAAyB,CAAC,gBAAgB;2BAChE,aAAa,CAAC,MAAM,KAAK,yBAAyB,CAAC,MAAM;iBAC/D;aACF;SACF;KACF;IACD,8FAA8F;IAC9F,kGAAkG;IAClG,+FAA+F;IAC/F,wEAAwE;CACzE,CAAC,CAAC","sourcesContent":["/**\n * Platform Access Grants — resource configuration.\n *\n * The operation set is unusual and the asymmetry is the point: the PLATFORM requests, the TENANT\n * decides. No verb lets one side do the other's job.\n *\n * requestAccess — platform-tier, crosses the tenant boundary\n * approve / deny — the TARGET tenant's own administrators, never platform-tier\n * revoke — either side, because either may end an elevation early\n *\n * See `platform-access-grants.shared.schemas.ts` for why the resource exists at all (rungs 4–5 of\n * the operator-access ladder in `.claude/rules/administrative-continuity-floors.md`) and\n * `.claude/plans/platform-access-grants-jit-elevation.md` for the remaining steps.\n */\n\nimport { z } from 'zod';\nimport { PlatformAccessGrantSchema, PlatformAccessGrantStatus, PlatformAccessGrants_Operations } from './platform-access-grants.shared.schemas';\nimport { CoreResourceOperation, CoreResourceType, coreResourceShared_FieldIdentifier } from '../../resources/resources.shared.core.definitions';\nimport {\n ResourceOperationRiskLevel,\n ResourceOperationVariantType,\n type ResourceRelationship,\n} from '../../resources/resources.shared.schemas';\nimport { createResourceConfiguration_Initialization } from '../../resources/resources-config.shared.factory';\nimport { ResourceSystemAccessMode } from '../../resources/resources-config.shared.schemas';\nimport { CoreUserNotificationTarget, CoreUserNotificationChannel } from '../../notifications/notifications.shared.schemas';\nimport { CORE_APP_ROLES, CORE_ORG_ROLES } from './roles.shared.schemas';\nimport { ErasureRetentionMode, ResourceDataSubjectKind } from '../../compliance/privacy/impersonalization.shared.schemas';\n\n\ntype PlatformAccessGrantsCoreOperations =\n | CoreResourceOperation.READ\n | CoreResourceOperation.LIST\n | CoreResourceOperation.COUNT\n | CoreResourceOperation.DELETE\n // Route-less; `retentionPolicy` requires READ + LIST + UPDATE_MANY.\n | CoreResourceOperation.UPDATE_MANY;\n\nexport const platformAccessGrantsResourceConfiguration_InitializationFactory = (resourcesRelationships: ResourceRelationship[]) =>\n createResourceConfiguration_Initialization<\n typeof PlatformAccessGrants_Operations,\n PlatformAccessGrantsCoreOperations,\n typeof PlatformAccessGrantSchema\n >({\n mainSchema: PlatformAccessGrantSchema,\n resourceIdentifier: CoreResourceType.PLATFORM_ACCESS_GRANTS,\n resourceFieldIdentifier: coreResourceShared_FieldIdentifier[CoreResourceType.PLATFORM_ACCESS_GRANTS],\n resourceRelationships: resourcesRelationships,\n isSystemResource: true,\n\n /**\n * `read`/`list` are ALLOWED for the trusted path because the authorization layer itself has to\n * resolve a caller's usable grant before admitting a crossing, and it does so on a system context\n * — the caller is by definition not a member of the tenant whose grants are being read.\n *\n * No trusted `create`/`update`: every transition belongs to a custom implementation that applies\n * the tenant policy and the continuity-floor measurement. A system door around those would be a\n * second way to mint an elevation, which is the one thing this resource exists to prevent.\n */\n systemAccessPolicy: {\n read: ResourceSystemAccessMode.ALLOWED,\n list: ResourceSystemAccessMode.ALLOWED,\n\n /**\n * Subject-export disclosure — FORBIDDEN, and the declaration is REQUIRED rather than optional.\n *\n * `operatorUserId` and `approvedByUserId` are foreign keys back to USERS, so\n * `classifySubjectExportDisposition` puts these rows on a user's Art. 15 graph as\n * `INCLUDED_REFERENCES_SUBJECT` — personal data CONCERNING the subject even though the subject\n * does not own it. An included resource carrying NO declaration REFUSES the entire export, so\n * omitting this would trade a frontend boot failure for a broken disclosure right.\n *\n * FORBIDDEN for the reason AUDIT_LOGS is: this is a security/operational monitoring record, and\n * handing the monitoring trail to the person it monitors is self-defeating. It is also not only\n * about them — a grant names the TENANT's approver and carries the tenant's decision reason, so\n * disclosing it to the operator would expose another data subject's decision (Art. 15(4)).\n * FORBIDDEN rows are left OUT of the bundle and RECORDED with that reason, never silently\n * dropped, so the report still answers \"why is this missing?\".\n */\n exportSubject: ResourceSystemAccessMode.FORBIDDEN,\n },\n\n /**\n * Subject erasure RETAINS this row and scrubs its free text.\n *\n * Note this is a DIFFERENT question from the `exportSubject: FORBIDDEN` above, and the two answers\n * differ deliberately. That one asks whether the monitored operator may READ the monitoring trail —\n * no. This one asks what erasure DOES to the row, and nothing here says erasure must not reach it.\n *\n * The grant survives because its security value is WHO reached WHICH tenant, WHEN, and under whose\n * approval — none of which is scrubbed. What does not survive is `justification` and `decisionReason`:\n * operator- and approver-written prose, and the surface most likely to name a third party in passing.\n * That makes the erasure narrow rather than destructive of the record.\n *\n * Contrast `auditLogs`, which is exempt outright: it is the immutable ledger of what happened,\n * including this erasure, so scrubbing it would destroy the evidence the erasure was performed.\n */\n retentionPolicy: {\n mode: ErasureRetentionMode.RETAIN_AND_IMPERSONALIZE,\n },\n\n /**\n * Erasing one of these rows revokes NO session. The grant is a record ABOUT an operator's access, not\n * the operator; their session ends through the `USERS` row, which is `SELF_PRINCIPAL`.\n */\n dataSubjectPolicy: { kind: ResourceDataSubjectKind.NO_PRINCIPAL },\n\n coreOperations: [\n CoreResourceOperation.READ,\n CoreResourceOperation.LIST,\n CoreResourceOperation.COUNT,\n // Route-less; `retentionPolicy` requires READ + LIST + UPDATE_MANY.\n CoreResourceOperation.UPDATE_MANY,\n // Present for the tenant-purge cascade ONLY — see the operation's configuration below.\n CoreResourceOperation.DELETE,\n ],\n\n operationsConfiguration: {\n\n /*\n\n * Route-less retention plumbing — INTERNAL_CALL registers no route and must not be REPOSITORY_ONLY: the\n\n * retention primitives resolve through `getServiceOperationPathDefault`, which matches only\n\n * INTERNAL_CALL / API_CALL. CRITICAL — it is the verb the impersonalize writer uses to stamp markers.\n\n */\n\n [CoreResourceOperation.UPDATE_MANY]: {\n\n variants: [{\n\n variantType: ResourceOperationVariantType.INTERNAL_CALL,\n\n isDefault: true,\n\n roles: [CORE_APP_ROLES.APP_ADMIN_SUPER_ADMIN],\n\n riskLevel: ResourceOperationRiskLevel.CRITICAL,\n\n }],\n\n },\n\n [CoreResourceOperation.READ]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n // Both sides read the same row through the same door: a tenant admin sees elevations\n // raised against their tenant (the consent record is worthless if the consenting party\n // cannot see it), and the platform sees the ones it raised. The ORGANIZATIONS scope does\n // the tenant separation; the platform reaches it through the cross-tenant admission on\n // the verbs below.\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.LOW,\n },\n ],\n },\n\n [CoreResourceOperation.LIST]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.LOW,\n },\n ],\n },\n\n [CoreResourceOperation.COUNT]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.LOW,\n },\n ],\n },\n\n /**\n * PURGE ONLY — there is deliberately no `API_CALL` variant, so no client can delete a grant.\n *\n * The verb exists because grants are a COMPOSITION child of ORGANIZATIONS with\n * `onParentDelete` enabled, and a cascade can only call an operation the child actually\n * declares. Without it the registry's composition-cascade-deletability guard fails — correctly:\n * the cascade would have been declared and then silently unable to run, leaving grant rows\n * behind after their tenant was purged.\n *\n * Route-less is the whole point of the shape. `INTERNAL_CALL` mirrors `organizations.delete`'s\n * own default: the tenant purge may remove these rows, and nobody else may. Erasing a consent\n * record through an API would let either party rewrite the history of an access decision, which\n * is exactly what this resource exists to make impossible.\n */\n [CoreResourceOperation.DELETE]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.INTERNAL_CALL,\n isDefault: true,\n roles: [],\n riskLevel: ResourceOperationRiskLevel.CRITICAL,\n },\n ],\n },\n\n /**\n * The bootstrap verb, and the ONE operation here that must stay reachable without an existing\n * grant — otherwise the mechanism cannot start: an operator would need an elevation to request\n * an elevation. It therefore declares `admitsCrossTenantPlatformAdministration` and must be\n * explicitly exempted when the admission predicate later starts requiring a usable grant\n * (Step 4 of the plan). That exemption is load-bearing and gets its own pin.\n *\n * What keeps the exemption safe is that requesting is not accessing: this verb writes a row in\n * `PENDING_APPROVAL` (or `ACTIVE` when the tenant has not opted into approval) and touches\n * nothing else in the tenant. The blast radius of an abused request is a notification and an\n * audit row naming the operator.\n *\n * assurance-control: WILDO.ACCESS.CROSS_TENANT_ADMINISTRATION — elevation is requested, never assumed.\n * assurance-control: WILDO.ACCESS.PRIVILEGE_EVIDENCE\n */\n [PlatformAccessGrants_Operations.REQUEST_ACCESS]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_APP_ROLES.APP_ADMIN_SUPER_ADMIN],\n riskLevel: ResourceOperationRiskLevel.CRITICAL,\n resourceOperationLike: CoreResourceOperation.CREATE,\n admitsCrossTenantPlatformAdministration: true,\n /**\n * `organizationId` deliberately does NOT appear in this body DTO. The organization is\n * already the mandatory primary-scope path segment and the execution-context creator\n * validates that URL value before dispatch. Requiring it again in JSON made clients\n * author the same security-critical target twice and created an avoidable mismatch case.\n *\n * WHERE AN OPERATOR GETS the path id is still a deliberate product decision. There is\n * no in-product surface that lists organizations the operator does not belong to:\n * `organizations | LIST` is confined to the caller's own memberships. The id therefore\n * arrives with the customer support case, where it is also present in support URLs,\n * organization notifications and the audit trail.\n *\n * Do not widen `organizations | LIST` to make discovery convenient: a browsable\n * directory is the customer list and would restore the standing cross-tenant\n * visibility this workflow exists to avoid.\n */\n requestDto: z.object({\n justification: z.string().min(1).max(1000),\n /** Minutes. Clamped server-side to the 4h ceiling; a longer ask is not refused. */\n requestedDurationMinutes: z.number().int().positive().optional(),\n }),\n },\n ],\n userNotifications: [\n {\n // The tenant learns immediately that an operator asked for access — before it happens,\n // not after. Under the approval posture this notification IS the request; without it,\n // opting in would give a tenant a decision it never hears about.\n target: CoreUserNotificationTarget.ORGANIZATION_USERS,\n channel: CoreUserNotificationChannel.EMAIL,\n },\n ],\n },\n\n /**\n * The tenant's decision. Gated on the TENANT's own roles and deliberately NOT reachable by the\n * platform: an operator who could approve their own request would make the whole Lockbox\n * posture ceremonial. Note the absence of `admitsCrossTenantPlatformAdministration` here — that\n * absence is the control, so do not add it \"for symmetry\".\n */\n [PlatformAccessGrants_Operations.APPROVE]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.HIGH,\n resourceOperationLike: CoreResourceOperation.UPDATE,\n requestDto: z.object({\n decisionReason: z.string().max(1000).optional(),\n }),\n // Only a request still awaiting a decision can be decided. Fails closed server-side, so a\n // replayed approval cannot revive a denied, revoked or expired grant.\n enabledCondition: ({ currentObject }) => currentObject.status === PlatformAccessGrantStatus.PENDING_APPROVAL,\n },\n ],\n },\n\n [PlatformAccessGrants_Operations.DENY]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.MEDIUM,\n resourceOperationLike: CoreResourceOperation.UPDATE,\n requestDto: z.object({\n decisionReason: z.string().max(1000).optional(),\n }),\n enabledCondition: ({ currentObject }) => currentObject.status === PlatformAccessGrantStatus.PENDING_APPROVAL,\n },\n ],\n },\n\n /**\n * Ending an elevation early. Reachable by BOTH sides, which is why it carries the cross-tenant\n * admission while `approve`/`deny` do not: a tenant revokes access it granted, and an operator\n * closes out their own session rather than leaving a live window open until it lapses.\n *\n * Revoking is monotonic — it only ever removes authority — so admitting the platform side costs\n * nothing the reversibility test would object to.\n */\n [PlatformAccessGrants_Operations.REVOKE]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.MEDIUM,\n resourceOperationLike: CoreResourceOperation.UPDATE,\n admitsCrossTenantPlatformAdministration: true,\n requestDto: z.object({\n decisionReason: z.string().max(1000).optional(),\n }),\n enabledCondition: ({ currentObject }) =>\n currentObject.status === PlatformAccessGrantStatus.PENDING_APPROVAL\n || currentObject.status === PlatformAccessGrantStatus.ACTIVE,\n },\n ],\n },\n },\n // NOTE: the ORGANIZATIONS primary scope is NOT declared here. It is derived from the registry\n // relationship carrying `isPrimaryScope: true` (ORGANIZATIONS → PLATFORM_ACCESS_GRANTS), which is\n // the single place scope is expressed for every resource. Declaring it twice would let the two\n // drift, and the relationship is the one the authorizer actually reads.\n });\n"]}
|
|
1
|
+
{"version":3,"file":"platform-access-grants.shared.resources-config.schemas.js","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.resources-config.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Platform Access Grants — resource configuration.\n *\n * The operation set is unusual and the asymmetry is the point: the PLATFORM requests, the TENANT\n * decides. No verb lets one side do the other's job.\n *\n * requestAccess — platform-tier, crosses the tenant boundary\n * approve / deny — the TARGET tenant's own administrators, never platform-tier\n * revoke — either side, because either may end an elevation early\n *\n * See `platform-access-grants.shared.schemas.ts` for why the resource exists at all (rungs 4–5 of\n * the operator-access ladder in `.claude/rules/administrative-continuity-floors.md`) and\n * `.claude/plans/platform-access-grants-jit-elevation.md` for the remaining steps.\n */\n\nimport { z } from 'zod';\nimport { PlatformAccessGrantSchema, PlatformAccessGrantStatus, PlatformAccessGrants_Operations } from './platform-access-grants.shared.schemas';\nimport { CoreResourceOperation, CoreResourceType, coreResourceShared_FieldIdentifier } from '../../resources/resources.shared.core.definitions';\nimport {\n ResourceOperationRiskLevel,\n ResourceOperationVariantType,\n type ResourceRelationship,\n} from '../../resources/resources.shared.schemas';\nimport { createResourceConfiguration_Initialization } from '../../resources/resources-config.shared.factory';\nimport { ResourceSystemAccessMode } from '../../resources/resources-config.shared.schemas';\nimport { CoreUserNotificationTarget, CoreUserNotificationChannel } from '../../notifications/notifications.shared.schemas';\nimport { CORE_APP_ROLES, CORE_ORG_ROLES } from './roles.shared.schemas';\nimport { ErasureRetentionMode, ResourceDataSubjectKind } from '../../compliance/privacy/impersonalization.shared.schemas';\n\n\ntype PlatformAccessGrantsCoreOperations =\n | CoreResourceOperation.READ\n | CoreResourceOperation.LIST\n | CoreResourceOperation.COUNT\n | CoreResourceOperation.DELETE\n // Route-less; `retentionPolicy` requires READ + LIST + UPDATE_MANY.\n | CoreResourceOperation.UPDATE_MANY;\n\nexport const platformAccessGrantsResourceConfiguration_InitializationFactory = (resourcesRelationships: ResourceRelationship[]) =>\n createResourceConfiguration_Initialization<\n typeof PlatformAccessGrants_Operations,\n PlatformAccessGrantsCoreOperations,\n typeof PlatformAccessGrantSchema\n >({\n mainSchema: PlatformAccessGrantSchema,\n resourceIdentifier: CoreResourceType.PLATFORM_ACCESS_GRANTS,\n resourceFieldIdentifier: coreResourceShared_FieldIdentifier[CoreResourceType.PLATFORM_ACCESS_GRANTS],\n resourceRelationships: resourcesRelationships,\n isSystemResource: true,\n\n /**\n * `read`/`list` are ALLOWED for the trusted path because the authorization layer itself has to\n * resolve a caller's usable grant before admitting a crossing, and it does so on a system context\n * — the caller is by definition not a member of the tenant whose grants are being read.\n *\n * No trusted `create`/`update`: every transition belongs to a custom implementation that applies\n * the tenant policy and the continuity-floor measurement. A system door around those would be a\n * second way to mint an elevation, which is the one thing this resource exists to prevent.\n */\n systemAccessPolicy: {\n read: ResourceSystemAccessMode.ALLOWED,\n list: ResourceSystemAccessMode.ALLOWED,\n\n /**\n * Subject-export disclosure — FORBIDDEN, and the declaration is REQUIRED rather than optional.\n *\n * `operatorUserId` and `approvedByUserId` are foreign keys back to USERS, so\n * `classifySubjectExportDisposition` puts these rows on a user's Art. 15 graph as\n * `INCLUDED_REFERENCES_SUBJECT` — personal data CONCERNING the subject even though the subject\n * does not own it. An included resource carrying NO declaration REFUSES the entire export, so\n * omitting this would trade a frontend boot failure for a broken disclosure right.\n *\n * FORBIDDEN for the reason AUDIT_LOGS is: this is a security/operational monitoring record, and\n * handing the monitoring trail to the person it monitors is self-defeating. It is also not only\n * about them — a grant names the TENANT's approver and carries the tenant's decision reason, so\n * disclosing it to the operator would expose another data subject's decision (Art. 15(4)).\n * FORBIDDEN rows are left OUT of the bundle and RECORDED with that reason, never silently\n * dropped, so the report still answers \"why is this missing?\".\n */\n exportSubject: ResourceSystemAccessMode.FORBIDDEN,\n },\n\n /**\n * Subject erasure RETAINS this row and scrubs its free text.\n *\n * Note this is a DIFFERENT question from the `exportSubject: FORBIDDEN` above, and the two answers\n * differ deliberately. That one asks whether the monitored operator may READ the monitoring trail —\n * no. This one asks what erasure DOES to the row, and nothing here says erasure must not reach it.\n *\n * The grant survives because its security value is WHO reached WHICH tenant, WHEN, and under whose\n * approval — none of which is scrubbed. What does not survive is `justification` and `decisionReason`:\n * operator- and approver-written prose, and the surface most likely to name a third party in passing.\n * That makes the erasure narrow rather than destructive of the record.\n *\n * Contrast `auditLogs`, which is exempt outright: it is the immutable ledger of what happened,\n * including this erasure, so scrubbing it would destroy the evidence the erasure was performed.\n */\n retentionPolicy: {\n mode: ErasureRetentionMode.RETAIN_AND_IMPERSONALIZE,\n },\n\n /**\n * Erasing one of these rows revokes NO session. The grant is a record ABOUT an operator's access, not\n * the operator; their session ends through the `USERS` row, which is `SELF_PRINCIPAL`.\n */\n dataSubjectPolicy: { kind: ResourceDataSubjectKind.NO_PRINCIPAL },\n\n coreOperations: [\n CoreResourceOperation.READ,\n CoreResourceOperation.LIST,\n CoreResourceOperation.COUNT,\n // Route-less; `retentionPolicy` requires READ + LIST + UPDATE_MANY.\n CoreResourceOperation.UPDATE_MANY,\n // Present for the tenant-purge cascade ONLY — see the operation's configuration below.\n CoreResourceOperation.DELETE,\n ],\n\n operationsConfiguration: {\n\n /*\n\n * Route-less retention plumbing — INTERNAL_CALL registers no route and must not be REPOSITORY_ONLY: the\n\n * retention primitives resolve through `getServiceOperationPathDefault`, which matches only\n\n * INTERNAL_CALL / API_CALL. CRITICAL — it is the verb the impersonalize writer uses to stamp markers.\n\n */\n\n [CoreResourceOperation.UPDATE_MANY]: {\n\n variants: [{\n\n variantType: ResourceOperationVariantType.INTERNAL_CALL,\n\n isDefault: true,\n\n roles: [CORE_APP_ROLES.APP_ADMIN_SUPER_ADMIN],\n\n riskLevel: ResourceOperationRiskLevel.CRITICAL,\n\n }],\n\n },\n\n [CoreResourceOperation.READ]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n // Both sides read the same row through the same door: a tenant admin sees elevations\n // raised against their tenant (the consent record is worthless if the consenting party\n // cannot see it), and the platform sees the ones it raised. The ORGANIZATIONS scope does\n // the tenant separation; the platform reaches it through the cross-tenant admission on\n // the verbs below.\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.LOW,\n },\n ],\n },\n\n [CoreResourceOperation.LIST]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.LOW,\n },\n ],\n },\n\n [CoreResourceOperation.COUNT]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.LOW,\n },\n ],\n },\n\n /**\n * PURGE ONLY — there is deliberately no `API_CALL` variant, so no client can delete a grant.\n *\n * The verb exists because grants are a COMPOSITION child of ORGANIZATIONS with\n * `onParentDelete` enabled, and a cascade can only call an operation the child actually\n * declares. Without it the registry's composition-cascade-deletability guard fails — correctly:\n * the cascade would have been declared and then silently unable to run, leaving grant rows\n * behind after their tenant was purged.\n *\n * Route-less is the whole point of the shape. `INTERNAL_CALL` mirrors `organizations.delete`'s\n * own default: the tenant purge may remove these rows, and nobody else may. Erasing a consent\n * record through an API would let either party rewrite the history of an access decision, which\n * is exactly what this resource exists to make impossible.\n */\n [CoreResourceOperation.DELETE]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.INTERNAL_CALL,\n isDefault: true,\n roles: [],\n riskLevel: ResourceOperationRiskLevel.CRITICAL,\n },\n ],\n },\n\n /**\n * The bootstrap verb, and the ONE operation here that must stay reachable without an existing\n * grant — otherwise the mechanism cannot start: an operator would need an elevation to request\n * an elevation. It therefore declares `admitsCrossTenantPlatformAdministration` and must be\n * explicitly exempted when the admission predicate later starts requiring a usable grant\n * (Step 4 of the plan). That exemption is load-bearing and gets its own pin.\n *\n * What keeps the exemption safe is that requesting is not accessing: this verb writes a row in\n * `PENDING_APPROVAL` (or `ACTIVE` when the tenant has not opted into approval) and touches\n * nothing else in the tenant. The blast radius of an abused request is a notification and an\n * audit row naming the operator.\n *\n * assurance-control: WILDO.ACCESS.CROSS_TENANT_ADMINISTRATION — elevation is requested, never assumed.\n * assurance-control: WILDO.ACCESS.PRIVILEGE_EVIDENCE\n */\n [PlatformAccessGrants_Operations.REQUEST_ACCESS]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_APP_ROLES.APP_ADMIN_SUPER_ADMIN],\n riskLevel: ResourceOperationRiskLevel.CRITICAL,\n resourceOperationLike: CoreResourceOperation.CREATE,\n admitsCrossTenantPlatformAdministration: true,\n /**\n * `organizationId` deliberately does NOT appear in this body DTO. The organization is\n * already the mandatory primary-scope path segment and the execution-context creator\n * validates that URL value before dispatch. Requiring it again in JSON made clients\n * author the same security-critical target twice and created an avoidable mismatch case.\n *\n * WHERE AN OPERATOR GETS the path id is still a deliberate product decision. There is\n * no in-product surface that lists organizations the operator does not belong to:\n * `organizations | LIST` is confined to the caller's own memberships. The id therefore\n * arrives with the customer support case, where it is also present in support URLs,\n * organization notifications and the audit trail.\n *\n * Do not widen `organizations | LIST` to make discovery convenient: a browsable\n * directory is the customer list and would restore the standing cross-tenant\n * visibility this workflow exists to avoid.\n */\n requestDto: z.object({\n justification: z.string().min(1).max(1000),\n /** Minutes. Clamped server-side to the 4h ceiling; a longer ask is not refused. */\n requestedDurationMinutes: z.number().int().positive().optional(),\n }),\n },\n ],\n userNotifications: [\n {\n // The tenant learns immediately that an operator asked for access — before it happens,\n // not after. Under the approval posture this notification IS the request; without it,\n // opting in would give a tenant a decision it never hears about.\n target: CoreUserNotificationTarget.ORGANIZATION_USERS,\n channel: CoreUserNotificationChannel.EMAIL,\n },\n ],\n },\n\n /**\n * The tenant's decision. Gated on the TENANT's own roles and deliberately NOT reachable by the\n * platform: an operator who could approve their own request would make the whole Lockbox\n * posture ceremonial. Note the absence of `admitsCrossTenantPlatformAdministration` here — that\n * absence is the control, so do not add it \"for symmetry\".\n */\n [PlatformAccessGrants_Operations.APPROVE]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.HIGH,\n resourceOperationLike: CoreResourceOperation.UPDATE,\n requestDto: z.object({\n decisionReason: z.string().max(1000).optional(),\n }),\n // Only a request still awaiting a decision can be decided. Fails closed server-side, so a\n // replayed approval cannot revive a denied, revoked or expired grant.\n enabledCondition: ({ currentObject }) => currentObject.status === PlatformAccessGrantStatus.PENDING_APPROVAL,\n },\n ],\n },\n\n [PlatformAccessGrants_Operations.DENY]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.MEDIUM,\n resourceOperationLike: CoreResourceOperation.UPDATE,\n requestDto: z.object({\n decisionReason: z.string().max(1000).optional(),\n }),\n enabledCondition: ({ currentObject }) => currentObject.status === PlatformAccessGrantStatus.PENDING_APPROVAL,\n },\n ],\n },\n\n /**\n * Ending an elevation early. Reachable by BOTH sides, which is why it carries the cross-tenant\n * admission while `approve`/`deny` do not: a tenant revokes access it granted, and an operator\n * closes out their own session rather than leaving a live window open until it lapses.\n *\n * Revoking is monotonic — it only ever removes authority — so admitting the platform side costs\n * nothing the reversibility test would object to.\n */\n /**\n * ACTIVE → EXPIRED once the window has elapsed, dispatched by the credential-expiry sweep and\n * by nothing else (#413). INTERNAL_CALL: no route, no frontend affordance, and therefore no\n * `admitsCrossTenantPlatformAdministration` — the tenant-boundary question does not arise for\n * an operation no request can reach.\n *\n * The transition precondition lives in the paired implementation, which permits it only from\n * ACTIVE: a grant the tenant DENIED or REVOKED must keep saying so, and relabelling a\n * terminal grant would rewrite the decision history a customer audit reads.\n */\n [PlatformAccessGrants_Operations.EXPIRE]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.INTERNAL_CALL,\n isDefault: true,\n roles: [CORE_APP_ROLES.APP_ADMIN_SUPER_ADMIN],\n riskLevel: ResourceOperationRiskLevel.LOW,\n resourceOperationLike: CoreResourceOperation.UPDATE,\n // EMPTY BY CONTRACT, not by omission. The credential-expiry sweep dispatches this verb with `{}`\n // and the paired prefix implementation forces the status transition itself, so there is no field\n // a caller may supply. Declaring nothing is NOT the same as declaring this: an operation without\n // a `requestDto` inherits the resource's ENTIRE update contract, which would let an INTERNAL_CALL\n // that accepts nothing advertise every field — `status` included, the one field this verb owns.\n requestDto: z.object({}),\n },\n ],\n },\n\n [PlatformAccessGrants_Operations.REVOKE]: {\n variants: [\n {\n variantType: ResourceOperationVariantType.API_CALL,\n isDefault: true,\n roles: [CORE_ORG_ROLES.ORG_ADMIN],\n riskLevel: ResourceOperationRiskLevel.MEDIUM,\n resourceOperationLike: CoreResourceOperation.UPDATE,\n admitsCrossTenantPlatformAdministration: true,\n requestDto: z.object({\n decisionReason: z.string().max(1000).optional(),\n }),\n enabledCondition: ({ currentObject }) =>\n currentObject.status === PlatformAccessGrantStatus.PENDING_APPROVAL\n || currentObject.status === PlatformAccessGrantStatus.ACTIVE,\n },\n ],\n },\n },\n // NOTE: the ORGANIZATIONS primary scope is NOT declared here. It is derived from the registry\n // relationship carrying `isPrimaryScope: true` (ORGANIZATIONS → PLATFORM_ACCESS_GRANTS), which is\n // the single place scope is expressed for every resource. Declaring it twice would let the two\n // drift, and the relationship is the one the authorizer actually reads.\n });\n"]}
|
|
@@ -59,10 +59,14 @@ export declare enum PlatformAccessGrantStatus {
|
|
|
59
59
|
/** The tenant refused. Terminal — a new request must be raised rather than this one retried. */
|
|
60
60
|
DENIED = "denied",
|
|
61
61
|
/**
|
|
62
|
-
* The window elapsed. Terminal, and
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
62
|
+
* The window elapsed. Terminal, and written by the credential-expiry sweep since 2026-09-08
|
|
63
|
+
* (#413) — before that it was reached by NO writer at all, so an elapsed grant read as ACTIVE
|
|
64
|
+
* forever in the customer-facing listing of its own resource.
|
|
65
|
+
*
|
|
66
|
+
* The label is still bookkeeping for humans and reporting, NEVER the control: the admission
|
|
67
|
+
* predicate compares `expiresAt` against now, so an expired grant stops working whether or not
|
|
68
|
+
* the sweep has run. That separation is deliberate and must survive — if admission ever starts
|
|
69
|
+
* reading this label, a lagging sweep becomes an authorization hole rather than a stale display.
|
|
66
70
|
*/
|
|
67
71
|
EXPIRED = "expired",
|
|
68
72
|
/** Withdrawn before expiry, by the tenant or by the platform. Terminal. */
|
|
@@ -80,7 +84,18 @@ export declare enum PlatformAccessGrantLifecycleTransition {
|
|
|
80
84
|
REQUESTED = "requested",
|
|
81
85
|
APPROVED = "approved",
|
|
82
86
|
DENIED = "denied",
|
|
83
|
-
REVOKED = "revoked"
|
|
87
|
+
REVOKED = "revoked",
|
|
88
|
+
/**
|
|
89
|
+
* The window elapsed and the sweep relabelled the grant (#413). The ONE transition with no human
|
|
90
|
+
* actor — every other member records a decision somebody made, so an audit row for this one
|
|
91
|
+
* carries no `decidedByUserId`, and that absence is the fact rather than a gap.
|
|
92
|
+
*
|
|
93
|
+
* It is recorded even though the label is bookkeeping and never the control: a customer reading
|
|
94
|
+
* the history of an operator's access to their tenant should see the access END, and a grant that
|
|
95
|
+
* simply stops appearing as ACTIVE with no corresponding row is the version of that history that
|
|
96
|
+
* raises questions.
|
|
97
|
+
*/
|
|
98
|
+
EXPIRED = "expired"
|
|
84
99
|
}
|
|
85
100
|
/** Why a grant became {@link PlatformAccessGrantStatus.ACTIVE} without a tenant administrator acting. */
|
|
86
101
|
export declare enum PlatformAccessGrantAutoApprovalReason {
|
|
@@ -94,7 +109,31 @@ export declare enum PlatformAccessGrantAutoApprovalReason {
|
|
|
94
109
|
*/
|
|
95
110
|
TENANT_CANNOT_APPROVE = "tenant_cannot_approve"
|
|
96
111
|
}
|
|
97
|
-
|
|
112
|
+
/**
|
|
113
|
+
* The default life of a grant whose request names no duration.
|
|
114
|
+
*
|
|
115
|
+
* ONE HOUR, and deliberately far below the ceiling. A request that states no duration is the
|
|
116
|
+
* unconsidered case, and the unconsidered case should get the narrowest window that still works —
|
|
117
|
+
* not the widest the system allows. Until 2026-09-08 this was 240, equal to the maximum, so every
|
|
118
|
+
* grant that did not ask was issued a four-hour elevation; that is the opposite of what a
|
|
119
|
+
* just-in-time mechanism is for.
|
|
120
|
+
*
|
|
121
|
+
* Sixty rather than thirty, and the reasoning is the part worth keeping: the failure mode of a
|
|
122
|
+
* too-short default is not a security one, it is that an operator re-requesting mid-incident learns
|
|
123
|
+
* to ask for the maximum every time — which would restore the old behaviour through the front door
|
|
124
|
+
* and make the ceiling the effective default. An hour covers an ordinary support interaction
|
|
125
|
+
* without teaching that habit. An operator who genuinely needs longer asks, and that ask is the
|
|
126
|
+
* record we want.
|
|
127
|
+
*/
|
|
128
|
+
export declare const PLATFORM_ACCESS_GRANT_DEFAULT_DURATION_MINUTES = 60;
|
|
129
|
+
/**
|
|
130
|
+
* The maximum life of a grant, whatever a request asks for.
|
|
131
|
+
*
|
|
132
|
+
* Four hours is a working session, not a working week: long enough that an operator is not
|
|
133
|
+
* re-requesting mid-incident, short enough that a forgotten grant is not a standing privilege by
|
|
134
|
+
* another name. Callers may request LESS; the ceiling is enforced server-side so a client cannot
|
|
135
|
+
* mint a long-lived elevation by asking for one.
|
|
136
|
+
*/
|
|
98
137
|
export declare const PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES = 240;
|
|
99
138
|
/** Statuses from which a grant can still be withdrawn. */
|
|
100
139
|
export declare const PLATFORM_ACCESS_GRANT_REVOCABLE_STATUSES: readonly PlatformAccessGrantStatus[];
|
|
@@ -158,6 +197,12 @@ export declare enum PlatformAccessGrants_Operations {
|
|
|
158
197
|
REQUEST_ACCESS = "requestAccess",
|
|
159
198
|
APPROVE = "approve",
|
|
160
199
|
DENY = "deny",
|
|
161
|
-
REVOKE = "revoke"
|
|
200
|
+
REVOKE = "revoke",
|
|
201
|
+
/**
|
|
202
|
+
* ACTIVE → EXPIRED once the window has elapsed, dispatched by the credential-expiry sweep and by
|
|
203
|
+
* nothing else (#413). Not an operator verb: an operator who wants access to end early uses
|
|
204
|
+
* REVOKE, and nobody needs a button that declares a date has passed.
|
|
205
|
+
*/
|
|
206
|
+
EXPIRE = "expire"
|
|
162
207
|
}
|
|
163
208
|
//# sourceMappingURL=platform-access-grants.shared.schemas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-access-grants.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;GAKG;AACH,oBAAY,yBAAyB;IACnC,wFAAwF;IACxF,gBAAgB,qBAAqB;IACrC,yFAAyF;IACzF,MAAM,WAAW;IACjB,gGAAgG;IAChG,MAAM,WAAW;IACjB
|
|
1
|
+
{"version":3,"file":"platform-access-grants.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;GAKG;AACH,oBAAY,yBAAyB;IACnC,wFAAwF;IACxF,gBAAgB,qBAAqB;IACrC,yFAAyF;IACzF,MAAM,WAAW;IACjB,gGAAgG;IAChG,MAAM,WAAW;IACjB;;;;;;;;;OASG;IACH,OAAO,YAAY;IACnB,2EAA2E;IAC3E,OAAO,YAAY;CACpB;AAED;;;;;;;GAOG;AACH,oBAAY,sCAAsC;IAChD,SAAS,cAAc;IACvB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB;;;;;;;;;OASG;IACH,OAAO,YAAY;CACpB;AAED,yGAAyG;AACzG,oBAAY,qCAAqC;IAC/C,kGAAkG;IAClG,4BAA4B,iCAAiC;IAC7D;;;;;OAKG;IACH,qBAAqB,0BAA0B;CAChD;AAKD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,8CAA8C,KAAK,CAAC;AAEjE;;;;;;;GAOG;AACH,eAAO,MAAM,8CAA8C,MAAM,CAAC;AAElE,0DAA0D;AAC1D,eAAO,MAAM,wCAAwC,EAAE,SAAS,yBAAyB,EAGxF,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;iBAiFpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,WAAW,CAAC,GAAG,SAAS,EACpE,GAAG,EAAE,IAAI,GACR,OAAO,CAMT;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,wBAAwB,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,CAM9G;AAED;;;;;;;;;;GAUG;AACH;;;;;;;;GAQG;AACH,oBAAY,+BAA+B;IACzC,cAAc,kBAAkB;IAChC,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB;;;;OAIG;IACH,MAAM,WAAW;CAClB"}
|
|
@@ -63,10 +63,14 @@ export var PlatformAccessGrantStatus;
|
|
|
63
63
|
/** The tenant refused. Terminal — a new request must be raised rather than this one retried. */
|
|
64
64
|
PlatformAccessGrantStatus["DENIED"] = "denied";
|
|
65
65
|
/**
|
|
66
|
-
* The window elapsed. Terminal, and
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
66
|
+
* The window elapsed. Terminal, and written by the credential-expiry sweep since 2026-09-08
|
|
67
|
+
* (#413) — before that it was reached by NO writer at all, so an elapsed grant read as ACTIVE
|
|
68
|
+
* forever in the customer-facing listing of its own resource.
|
|
69
|
+
*
|
|
70
|
+
* The label is still bookkeeping for humans and reporting, NEVER the control: the admission
|
|
71
|
+
* predicate compares `expiresAt` against now, so an expired grant stops working whether or not
|
|
72
|
+
* the sweep has run. That separation is deliberate and must survive — if admission ever starts
|
|
73
|
+
* reading this label, a lagging sweep becomes an authorization hole rather than a stale display.
|
|
70
74
|
*/
|
|
71
75
|
PlatformAccessGrantStatus["EXPIRED"] = "expired";
|
|
72
76
|
/** Withdrawn before expiry, by the tenant or by the platform. Terminal. */
|
|
@@ -86,6 +90,17 @@ export var PlatformAccessGrantLifecycleTransition;
|
|
|
86
90
|
PlatformAccessGrantLifecycleTransition["APPROVED"] = "approved";
|
|
87
91
|
PlatformAccessGrantLifecycleTransition["DENIED"] = "denied";
|
|
88
92
|
PlatformAccessGrantLifecycleTransition["REVOKED"] = "revoked";
|
|
93
|
+
/**
|
|
94
|
+
* The window elapsed and the sweep relabelled the grant (#413). The ONE transition with no human
|
|
95
|
+
* actor — every other member records a decision somebody made, so an audit row for this one
|
|
96
|
+
* carries no `decidedByUserId`, and that absence is the fact rather than a gap.
|
|
97
|
+
*
|
|
98
|
+
* It is recorded even though the label is bookkeeping and never the control: a customer reading
|
|
99
|
+
* the history of an operator's access to their tenant should see the access END, and a grant that
|
|
100
|
+
* simply stops appearing as ACTIVE with no corresponding row is the version of that history that
|
|
101
|
+
* raises questions.
|
|
102
|
+
*/
|
|
103
|
+
PlatformAccessGrantLifecycleTransition["EXPIRED"] = "expired";
|
|
89
104
|
})(PlatformAccessGrantLifecycleTransition || (PlatformAccessGrantLifecycleTransition = {}));
|
|
90
105
|
/** Why a grant became {@link PlatformAccessGrantStatus.ACTIVE} without a tenant administrator acting. */
|
|
91
106
|
export var PlatformAccessGrantAutoApprovalReason;
|
|
@@ -100,17 +115,33 @@ export var PlatformAccessGrantAutoApprovalReason;
|
|
|
100
115
|
*/
|
|
101
116
|
PlatformAccessGrantAutoApprovalReason["TENANT_CANNOT_APPROVE"] = "tenant_cannot_approve";
|
|
102
117
|
})(PlatformAccessGrantAutoApprovalReason || (PlatformAccessGrantAutoApprovalReason = {}));
|
|
118
|
+
/** Fixed replacement for grant free-text that cannot be cleared (a `.min(1)` field). */
|
|
119
|
+
const ERASED_GRANT_TEXT = '[erased]';
|
|
120
|
+
/**
|
|
121
|
+
* The default life of a grant whose request names no duration.
|
|
122
|
+
*
|
|
123
|
+
* ONE HOUR, and deliberately far below the ceiling. A request that states no duration is the
|
|
124
|
+
* unconsidered case, and the unconsidered case should get the narrowest window that still works —
|
|
125
|
+
* not the widest the system allows. Until 2026-09-08 this was 240, equal to the maximum, so every
|
|
126
|
+
* grant that did not ask was issued a four-hour elevation; that is the opposite of what a
|
|
127
|
+
* just-in-time mechanism is for.
|
|
128
|
+
*
|
|
129
|
+
* Sixty rather than thirty, and the reasoning is the part worth keeping: the failure mode of a
|
|
130
|
+
* too-short default is not a security one, it is that an operator re-requesting mid-incident learns
|
|
131
|
+
* to ask for the maximum every time — which would restore the old behaviour through the front door
|
|
132
|
+
* and make the ceiling the effective default. An hour covers an ordinary support interaction
|
|
133
|
+
* without teaching that habit. An operator who genuinely needs longer asks, and that ask is the
|
|
134
|
+
* record we want.
|
|
135
|
+
*/
|
|
136
|
+
export const PLATFORM_ACCESS_GRANT_DEFAULT_DURATION_MINUTES = 60;
|
|
103
137
|
/**
|
|
104
|
-
* The maximum life of a grant,
|
|
138
|
+
* The maximum life of a grant, whatever a request asks for.
|
|
105
139
|
*
|
|
106
140
|
* Four hours is a working session, not a working week: long enough that an operator is not
|
|
107
141
|
* re-requesting mid-incident, short enough that a forgotten grant is not a standing privilege by
|
|
108
142
|
* another name. Callers may request LESS; the ceiling is enforced server-side so a client cannot
|
|
109
143
|
* mint a long-lived elevation by asking for one.
|
|
110
144
|
*/
|
|
111
|
-
/** Fixed replacement for grant free-text that cannot be cleared (a `.min(1)` field). */
|
|
112
|
-
const ERASED_GRANT_TEXT = '[erased]';
|
|
113
|
-
export const PLATFORM_ACCESS_GRANT_DEFAULT_DURATION_MINUTES = 240;
|
|
114
145
|
export const PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES = 240;
|
|
115
146
|
/** Statuses from which a grant can still be withdrawn. */
|
|
116
147
|
export const PLATFORM_ACCESS_GRANT_REVOCABLE_STATUSES = [
|
|
@@ -244,5 +275,11 @@ export var PlatformAccessGrants_Operations;
|
|
|
244
275
|
PlatformAccessGrants_Operations["APPROVE"] = "approve";
|
|
245
276
|
PlatformAccessGrants_Operations["DENY"] = "deny";
|
|
246
277
|
PlatformAccessGrants_Operations["REVOKE"] = "revoke";
|
|
278
|
+
/**
|
|
279
|
+
* ACTIVE → EXPIRED once the window has elapsed, dispatched by the credential-expiry sweep and by
|
|
280
|
+
* nothing else (#413). Not an operator verb: an operator who wants access to end early uses
|
|
281
|
+
* REVOKE, and nobody needs a button that declares a date has passed.
|
|
282
|
+
*/
|
|
283
|
+
PlatformAccessGrants_Operations["EXPIRE"] = "expire";
|
|
247
284
|
})(PlatformAccessGrants_Operations || (PlatformAccessGrants_Operations = {}));
|
|
248
285
|
//# sourceMappingURL=platform-access-grants.shared.schemas.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-access-grants.shared.schemas.js","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Platform Access Grants — time-bound, justified, optionally tenant-approved elevation that lets a\n * platform operator cross the tenant boundary.\n *\n * ## Where this sits\n *\n * Wildo's answer to \"may a platform super-administrator administer any tenant?\" is YES, as at most\n * B2B platforms. The question this resource answers is the narrower one that follows: *on what\n * terms?* The progression, recorded in `.claude/rules/administrative-continuity-floors.md`:\n *\n * ambient+unaudited → ambient+audited → declared, deny-by-default → **JIT/time-bound (here)**\n * → customer-approved (here, when the tenant opts in)\n *\n * Declaring a crossing per operation variant (`admitsCrossTenantPlatformAdministration`) removed\n * AMBIENT authority: a crossing must now be asked for in code, reviewed, and specified. It did not\n * remove STANDING authority — every platform administrator still held every declared crossing,\n * permanently, over every tenant. That is the shape zero-standing-privilege programmes exist to\n * eliminate, and what NIST SP 800-53 AC-2 / AC-6(1) mean by least privilege: privileged access is\n * requested, scoped, time-boxed, and expires on its own.\n *\n * A grant is therefore required IN ADDITION to the variant's declaration. The declaration says\n * \"this verb MAY cross\"; the grant says \"this operator MAY cross into THIS tenant, until THIS time,\n * for THIS reason\". Neither is sufficient alone.\n *\n * ## The tenant-approval half (Lockbox)\n *\n * Microsoft Customer Lockbox and Google Access Approval let the CUSTOMER approve provider access\n * before it happens. Wildo models that as {@link PlatformAccessGrantStatus.PENDING_APPROVAL}, gated\n * per tenant so it is an opt-in posture rather than a deployment-wide one — the same shape those\n * products ship, and for the same reason: a tenant that has not staffed an approver must not be\n * unable to receive support.\n *\n * ## ⚠️ The interaction that is easy to get wrong\n *\n * Tenant approval and the administrative-continuity floors are in direct tension. Approval requires\n * an administrator; the floors exist precisely because a tenant can end up WITHOUT one. Requiring a\n * stranded tenant to approve its own repair is circular — the tenant cannot approve, so the repair\n * cannot happen, so the tenant stays stranded.\n *\n * This is resolved by measurement, not by exception: when the target tenant has no administratively\n * usable owner, the grant is auto-approved with\n * {@link PlatformAccessGrantAutoApprovalReason.TENANT_CANNOT_APPROVE} and recorded loudly. The\n * condition is evaluated with the SAME predicate the owner floor uses to refuse writes, so the two\n * can never disagree about whether a tenant can administer itself. An operator cannot manufacture\n * the condition either: stranding a tenant is exactly what the floors refuse.\n */\n\nimport { z } from 'zod';\nimport { PersonalDataCategory } from '../../compliance/privacy/personal-data-category.shared.schemas';\nimport { RedactionType } from '../../compliance/privacy/redaction.shared.schemas';\nimport { addImpersonalizeWith } from '@wildo-ai/zod-decorators';\n\n/**\n * Lifecycle of one elevation request.\n *\n * A closed vocabulary with one named runtime source: schemas, guards, fixtures and comparisons all\n * derive from this enum rather than repeating literals.\n */\nexport enum PlatformAccessGrantStatus {\n /** Awaiting a decision from an administrator of the TARGET tenant (Lockbox posture). */\n PENDING_APPROVAL = 'pending_approval',\n /** Usable now. The admission predicate accepts this status, and only while unexpired. */\n ACTIVE = 'active',\n /** The tenant refused. Terminal — a new request must be raised rather than this one retried. */\n DENIED = 'denied',\n /**\n * The window elapsed. Terminal, and reached WITHOUT a writer: the admission predicate compares\n * `expiresAt` against now, so an expired grant stops working whether or not any sweeper has\n * relabelled it. A background transition to this status is bookkeeping for humans and reporting,\n * never the control.\n */\n EXPIRED = 'expired',\n /** Withdrawn before expiry, by the tenant or by the platform. Terminal. */\n REVOKED = 'revoked',\n}\n\n/**\n * Which step of a grant's life an audit row records.\n *\n * Distinct from {@link PlatformAccessGrantStatus}: a status is where the grant IS, a transition is\n * what just happened to it. They differ where it matters — an auto-approved grant lands in `ACTIVE`\n * through `REQUESTED`, never through `APPROVED`, and collapsing the two would erase exactly the\n * distinction a customer audit asks about.\n */\nexport enum PlatformAccessGrantLifecycleTransition {\n REQUESTED = 'requested',\n APPROVED = 'approved',\n DENIED = 'denied',\n REVOKED = 'revoked',\n}\n\n/** Why a grant became {@link PlatformAccessGrantStatus.ACTIVE} without a tenant administrator acting. */\nexport enum PlatformAccessGrantAutoApprovalReason {\n /** The tenant has not opted into approval. The default posture, matching Lockbox being opt-in. */\n TENANT_APPROVAL_NOT_REQUIRED = 'tenant_approval_not_required',\n /**\n * The tenant has NO administratively usable owner, so no principal exists who could approve.\n * Evaluated with the owner floor's own predicate — see this file's header for why the alternative\n * (refusing) is circular. Recorded at high severity: this is the one path where operator access\n * proceeds against a tenant that never consented and never could.\n */\n TENANT_CANNOT_APPROVE = 'tenant_cannot_approve',\n}\n\n/**\n * The maximum life of a grant, and the default when a request names none.\n *\n * Four hours is a working session, not a working week: long enough that an operator is not\n * re-requesting mid-incident, short enough that a forgotten grant is not a standing privilege by\n * another name. Callers may request LESS; the ceiling is enforced server-side so a client cannot\n * mint a long-lived elevation by asking for one.\n */\n/** Fixed replacement for grant free-text that cannot be cleared (a `.min(1)` field). */\nconst ERASED_GRANT_TEXT = '[erased]';\n\nexport const PLATFORM_ACCESS_GRANT_DEFAULT_DURATION_MINUTES = 240;\nexport const PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES = 240;\n\n/** Statuses from which a grant can still be withdrawn. */\nexport const PLATFORM_ACCESS_GRANT_REVOCABLE_STATUSES: readonly PlatformAccessGrantStatus[] = [\n PlatformAccessGrantStatus.PENDING_APPROVAL,\n PlatformAccessGrantStatus.ACTIVE,\n];\n\nexport const PlatformAccessGrantSchema = z.object({\n _id: z.string().min(1).isPrimaryKey().isSummaryField(),\n\n /**\n * The TARGET tenant — the one being reached into, never the operator's own.\n *\n * This is the scope anchor: the grant is an organization-scoped row so the tenant can see, approve\n * and revoke elevations raised against it. A grant the tenant cannot see would defeat the point of\n * modelling consent at all.\n */\n organizationId: z.string().min(1).isDBIndexed().isForeignKey().isSummaryField().excludeFromUpdate().isAuditEvidence(),\n\n /** The operator who requested the elevation. Server-authored from the session, never client-supplied. */\n operatorUserId: z.string().min(1).isDBIndexed().isForeignKey().isSummaryField().excludeFromCreate().excludeFromUpdate().isAuditEvidence(),\n\n /**\n * Why the operator needs access. REQUIRED, and deliberately not optional anywhere in the flow.\n *\n * An elevation record without a reason answers \"who and when\" but not \"why\", which is the only\n * question a reviewer or a customer actually asks. `AC-2(7)` wants privileged assignment monitored;\n * an unexplained monitored assignment is a log line, not a control.\n */\n // USER_CONTENT — free prose an OPERATOR typed, about why they need to reach a customer tenant.\n // The data subject here is the operator, not the tenant's users; a notice covering staff must\n // enumerate it, and it is exactly the free-text surface that can name a third party in passing.\n // MASK on erasure, not REMOVE: `.min(1)` makes this non-clearable, so a null would be rejected by the\n // strict update-DTO parse the impersonalize writer runs. A fixed non-empty string is accepted.\n // It must be scrubbed at all because it is free text an operator wrote about why they needed\n // access — exactly the surface that names a third party in passing.\n justification: addImpersonalizeWith(\n z.string().min(1).max(1000).isSummaryField()\n .dataCategories(PersonalDataCategory.USER_CONTENT),\n RedactionType.MASK,\n { maskValue: ERASED_GRANT_TEXT },\n ),\n\n status: z.enum(PlatformAccessGrantStatus)\n .systemEnum('PlatformAccessGrantStatus')\n .default(PlatformAccessGrantStatus.PENDING_APPROVAL)\n .isDBIndexed()\n .isSummaryField()\n .excludeFromCreate()\n .excludeFromUpdate()\n .isAuditEvidence(),\n\n /**\n * When the elevation stops working.\n *\n * Server-authored from the requested duration, clamped to\n * {@link PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES}. The admission predicate reads THIS field\n * rather than trusting `status`, so expiry needs no sweeper to take effect.\n */\n expiresAt: z.date().isDBIndexed().isSummaryField().excludeFromCreate().excludeFromUpdate().isAuditEvidence(),\n\n /** Set when a tenant administrator approved. Absent on an auto-approved grant — see {@link autoApprovalReason}. */\n approvedByUserId: z.string().min(1).optional().isForeignKey().excludeFromCreate().excludeFromUpdate().isAuditEvidence(),\n approvedAt: z.date().optional().excludeFromCreate().excludeFromUpdate(),\n\n /**\n * Present exactly when the grant became ACTIVE with no tenant administrator acting.\n *\n * Its absence on an ACTIVE grant is therefore meaningful: a human in the tenant approved it. That\n * distinction is what a customer audit needs and what a single `approved: true` boolean would erase.\n */\n autoApprovalReason: z.enum(PlatformAccessGrantAutoApprovalReason)\n .systemEnum('PlatformAccessGrantAutoApprovalReason')\n .optional()\n .excludeFromCreate()\n .excludeFromUpdate()\n .isAuditEvidence(),\n\n /** The tenant's reason for refusing, or the revoker's reason for withdrawing. */\n // REMOVE — free text again, and clearable (`.optional()`).\n decisionReason: addImpersonalizeWith(\n z.string().max(1000).optional().excludeFromCreate().excludeFromUpdate()\n .dataCategories(PersonalDataCategory.USER_CONTENT),\n RedactionType.REMOVE,\n ),\n\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\nexport type PlatformAccessGrant = z.infer<typeof PlatformAccessGrantSchema>;\n\n/**\n * Is this grant usable RIGHT NOW?\n *\n * The single predicate every consumer must use — the admission check, the tenant's UI, and any\n * report. Two independent conditions, and the expiry half is why this is a function rather than a\n * status comparison: a grant whose window elapsed is unusable the moment it elapses, with no writer\n * involved. Reading `status === ACTIVE` alone would honour a stale row for as long as no sweeper had\n * run, turning a time-bound elevation back into a standing one.\n *\n * `now` is injected so callers can evaluate a grant at a decision time they already fixed, and so\n * this stays testable without clock control.\n */\nexport function isPlatformAccessGrantUsable(\n grant: Pick<PlatformAccessGrant, 'status' | 'expiresAt'> | undefined,\n now: Date,\n): boolean {\n if (!grant) return false;\n if (grant.status !== PlatformAccessGrantStatus.ACTIVE) return false;\n return grant.expiresAt instanceof Date\n ? grant.expiresAt.getTime() > now.getTime()\n : new Date(grant.expiresAt).getTime() > now.getTime();\n}\n\n/**\n * Clamp a requested duration to the server-side ceiling.\n *\n * Applied to every request path, including trusted ones. A caller asking for a longer window is not\n * refused — being told \"no, ask again with a smaller number\" during an incident is friction with no\n * security benefit, since the ceiling is what actually binds. They simply get the ceiling.\n */\nexport function resolvePlatformAccessGrantExpiry(requestedDurationMinutes: number | undefined, now: Date): Date {\n const requested = requestedDurationMinutes && requestedDurationMinutes > 0\n ? requestedDurationMinutes\n : PLATFORM_ACCESS_GRANT_DEFAULT_DURATION_MINUTES;\n const minutes = Math.min(requested, PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES);\n return new Date(now.getTime() + minutes * 60_000);\n}\n\n/**\n * NOTE ON PLACEMENT — this enum lives with the VOCABULARY, not with the resource configuration,\n * and moving it back would reintroduce a real defect.\n *\n * The authorization layer needs `REQUEST_ACCESS` by name (it is the bootstrap verb, exempt from the\n * grant requirement it bootstraps). Importing that value from the resources-config module dragged\n * resource-configuration evaluation into the authorizer's module graph, and schema construction that\n * runs before the Zod decorators are initialised loses decorator metadata — which surfaced, far from\n * here, as the ephemeral-disclosure catalogue losing an operation-level declaration. A vocabulary has\n * no such side effects.\n */\n/**\n * Custom verbs. Ordinary CREATE/UPDATE/DELETE are deliberately NOT exposed:\n *\n * - CREATE would let a caller author `status`, `expiresAt` and `operatorUserId` directly, which are\n * precisely the fields whose server authorship IS the control.\n * - UPDATE would be a second, ungated path to the status transitions `approve`/`deny`/`revoke` own.\n * - DELETE exists but has NO client door — see its configuration below. An elevation either side could\n * erase is not evidence; the terminal statuses (DENIED / EXPIRED / REVOKED) are how a grant ends.\n */\nexport enum PlatformAccessGrants_Operations {\n REQUEST_ACCESS = 'requestAccess',\n APPROVE = 'approve',\n DENY = 'deny',\n REVOKE = 'revoke',\n}\n"]}
|
|
1
|
+
{"version":3,"file":"platform-access-grants.shared.schemas.js","sourceRoot":"","sources":["../../../../../src/security/authorizations/platform-access-grants.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Platform Access Grants — time-bound, justified, optionally tenant-approved elevation that lets a\n * platform operator cross the tenant boundary.\n *\n * ## Where this sits\n *\n * Wildo's answer to \"may a platform super-administrator administer any tenant?\" is YES, as at most\n * B2B platforms. The question this resource answers is the narrower one that follows: *on what\n * terms?* The progression, recorded in `.claude/rules/administrative-continuity-floors.md`:\n *\n * ambient+unaudited → ambient+audited → declared, deny-by-default → **JIT/time-bound (here)**\n * → customer-approved (here, when the tenant opts in)\n *\n * Declaring a crossing per operation variant (`admitsCrossTenantPlatformAdministration`) removed\n * AMBIENT authority: a crossing must now be asked for in code, reviewed, and specified. It did not\n * remove STANDING authority — every platform administrator still held every declared crossing,\n * permanently, over every tenant. That is the shape zero-standing-privilege programmes exist to\n * eliminate, and what NIST SP 800-53 AC-2 / AC-6(1) mean by least privilege: privileged access is\n * requested, scoped, time-boxed, and expires on its own.\n *\n * A grant is therefore required IN ADDITION to the variant's declaration. The declaration says\n * \"this verb MAY cross\"; the grant says \"this operator MAY cross into THIS tenant, until THIS time,\n * for THIS reason\". Neither is sufficient alone.\n *\n * ## The tenant-approval half (Lockbox)\n *\n * Microsoft Customer Lockbox and Google Access Approval let the CUSTOMER approve provider access\n * before it happens. Wildo models that as {@link PlatformAccessGrantStatus.PENDING_APPROVAL}, gated\n * per tenant so it is an opt-in posture rather than a deployment-wide one — the same shape those\n * products ship, and for the same reason: a tenant that has not staffed an approver must not be\n * unable to receive support.\n *\n * ## ⚠️ The interaction that is easy to get wrong\n *\n * Tenant approval and the administrative-continuity floors are in direct tension. Approval requires\n * an administrator; the floors exist precisely because a tenant can end up WITHOUT one. Requiring a\n * stranded tenant to approve its own repair is circular — the tenant cannot approve, so the repair\n * cannot happen, so the tenant stays stranded.\n *\n * This is resolved by measurement, not by exception: when the target tenant has no administratively\n * usable owner, the grant is auto-approved with\n * {@link PlatformAccessGrantAutoApprovalReason.TENANT_CANNOT_APPROVE} and recorded loudly. The\n * condition is evaluated with the SAME predicate the owner floor uses to refuse writes, so the two\n * can never disagree about whether a tenant can administer itself. An operator cannot manufacture\n * the condition either: stranding a tenant is exactly what the floors refuse.\n */\n\nimport { z } from 'zod';\nimport { PersonalDataCategory } from '../../compliance/privacy/personal-data-category.shared.schemas';\nimport { RedactionType } from '../../compliance/privacy/redaction.shared.schemas';\nimport { addImpersonalizeWith } from '@wildo-ai/zod-decorators';\n\n/**\n * Lifecycle of one elevation request.\n *\n * A closed vocabulary with one named runtime source: schemas, guards, fixtures and comparisons all\n * derive from this enum rather than repeating literals.\n */\nexport enum PlatformAccessGrantStatus {\n /** Awaiting a decision from an administrator of the TARGET tenant (Lockbox posture). */\n PENDING_APPROVAL = 'pending_approval',\n /** Usable now. The admission predicate accepts this status, and only while unexpired. */\n ACTIVE = 'active',\n /** The tenant refused. Terminal — a new request must be raised rather than this one retried. */\n DENIED = 'denied',\n /**\n * The window elapsed. Terminal, and written by the credential-expiry sweep since 2026-09-08\n * (#413) — before that it was reached by NO writer at all, so an elapsed grant read as ACTIVE\n * forever in the customer-facing listing of its own resource.\n *\n * The label is still bookkeeping for humans and reporting, NEVER the control: the admission\n * predicate compares `expiresAt` against now, so an expired grant stops working whether or not\n * the sweep has run. That separation is deliberate and must survive — if admission ever starts\n * reading this label, a lagging sweep becomes an authorization hole rather than a stale display.\n */\n EXPIRED = 'expired',\n /** Withdrawn before expiry, by the tenant or by the platform. Terminal. */\n REVOKED = 'revoked',\n}\n\n/**\n * Which step of a grant's life an audit row records.\n *\n * Distinct from {@link PlatformAccessGrantStatus}: a status is where the grant IS, a transition is\n * what just happened to it. They differ where it matters — an auto-approved grant lands in `ACTIVE`\n * through `REQUESTED`, never through `APPROVED`, and collapsing the two would erase exactly the\n * distinction a customer audit asks about.\n */\nexport enum PlatformAccessGrantLifecycleTransition {\n REQUESTED = 'requested',\n APPROVED = 'approved',\n DENIED = 'denied',\n REVOKED = 'revoked',\n /**\n * The window elapsed and the sweep relabelled the grant (#413). The ONE transition with no human\n * actor — every other member records a decision somebody made, so an audit row for this one\n * carries no `decidedByUserId`, and that absence is the fact rather than a gap.\n *\n * It is recorded even though the label is bookkeeping and never the control: a customer reading\n * the history of an operator's access to their tenant should see the access END, and a grant that\n * simply stops appearing as ACTIVE with no corresponding row is the version of that history that\n * raises questions.\n */\n EXPIRED = 'expired',\n}\n\n/** Why a grant became {@link PlatformAccessGrantStatus.ACTIVE} without a tenant administrator acting. */\nexport enum PlatformAccessGrantAutoApprovalReason {\n /** The tenant has not opted into approval. The default posture, matching Lockbox being opt-in. */\n TENANT_APPROVAL_NOT_REQUIRED = 'tenant_approval_not_required',\n /**\n * The tenant has NO administratively usable owner, so no principal exists who could approve.\n * Evaluated with the owner floor's own predicate — see this file's header for why the alternative\n * (refusing) is circular. Recorded at high severity: this is the one path where operator access\n * proceeds against a tenant that never consented and never could.\n */\n TENANT_CANNOT_APPROVE = 'tenant_cannot_approve',\n}\n\n/** Fixed replacement for grant free-text that cannot be cleared (a `.min(1)` field). */\nconst ERASED_GRANT_TEXT = '[erased]';\n\n/**\n * The default life of a grant whose request names no duration.\n *\n * ONE HOUR, and deliberately far below the ceiling. A request that states no duration is the\n * unconsidered case, and the unconsidered case should get the narrowest window that still works —\n * not the widest the system allows. Until 2026-09-08 this was 240, equal to the maximum, so every\n * grant that did not ask was issued a four-hour elevation; that is the opposite of what a\n * just-in-time mechanism is for.\n *\n * Sixty rather than thirty, and the reasoning is the part worth keeping: the failure mode of a\n * too-short default is not a security one, it is that an operator re-requesting mid-incident learns\n * to ask for the maximum every time — which would restore the old behaviour through the front door\n * and make the ceiling the effective default. An hour covers an ordinary support interaction\n * without teaching that habit. An operator who genuinely needs longer asks, and that ask is the\n * record we want.\n */\nexport const PLATFORM_ACCESS_GRANT_DEFAULT_DURATION_MINUTES = 60;\n\n/**\n * The maximum life of a grant, whatever a request asks for.\n *\n * Four hours is a working session, not a working week: long enough that an operator is not\n * re-requesting mid-incident, short enough that a forgotten grant is not a standing privilege by\n * another name. Callers may request LESS; the ceiling is enforced server-side so a client cannot\n * mint a long-lived elevation by asking for one.\n */\nexport const PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES = 240;\n\n/** Statuses from which a grant can still be withdrawn. */\nexport const PLATFORM_ACCESS_GRANT_REVOCABLE_STATUSES: readonly PlatformAccessGrantStatus[] = [\n PlatformAccessGrantStatus.PENDING_APPROVAL,\n PlatformAccessGrantStatus.ACTIVE,\n];\n\nexport const PlatformAccessGrantSchema = z.object({\n _id: z.string().min(1).isPrimaryKey().isSummaryField(),\n\n /**\n * The TARGET tenant — the one being reached into, never the operator's own.\n *\n * This is the scope anchor: the grant is an organization-scoped row so the tenant can see, approve\n * and revoke elevations raised against it. A grant the tenant cannot see would defeat the point of\n * modelling consent at all.\n */\n organizationId: z.string().min(1).isDBIndexed().isForeignKey().isSummaryField().excludeFromUpdate().isAuditEvidence(),\n\n /** The operator who requested the elevation. Server-authored from the session, never client-supplied. */\n operatorUserId: z.string().min(1).isDBIndexed().isForeignKey().isSummaryField().excludeFromCreate().excludeFromUpdate().isAuditEvidence(),\n\n /**\n * Why the operator needs access. REQUIRED, and deliberately not optional anywhere in the flow.\n *\n * An elevation record without a reason answers \"who and when\" but not \"why\", which is the only\n * question a reviewer or a customer actually asks. `AC-2(7)` wants privileged assignment monitored;\n * an unexplained monitored assignment is a log line, not a control.\n */\n // USER_CONTENT — free prose an OPERATOR typed, about why they need to reach a customer tenant.\n // The data subject here is the operator, not the tenant's users; a notice covering staff must\n // enumerate it, and it is exactly the free-text surface that can name a third party in passing.\n // MASK on erasure, not REMOVE: `.min(1)` makes this non-clearable, so a null would be rejected by the\n // strict update-DTO parse the impersonalize writer runs. A fixed non-empty string is accepted.\n // It must be scrubbed at all because it is free text an operator wrote about why they needed\n // access — exactly the surface that names a third party in passing.\n justification: addImpersonalizeWith(\n z.string().min(1).max(1000).isSummaryField()\n .dataCategories(PersonalDataCategory.USER_CONTENT),\n RedactionType.MASK,\n { maskValue: ERASED_GRANT_TEXT },\n ),\n\n status: z.enum(PlatformAccessGrantStatus)\n .systemEnum('PlatformAccessGrantStatus')\n .default(PlatformAccessGrantStatus.PENDING_APPROVAL)\n .isDBIndexed()\n .isSummaryField()\n .excludeFromCreate()\n .excludeFromUpdate()\n .isAuditEvidence(),\n\n /**\n * When the elevation stops working.\n *\n * Server-authored from the requested duration, clamped to\n * {@link PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES}. The admission predicate reads THIS field\n * rather than trusting `status`, so expiry needs no sweeper to take effect.\n */\n expiresAt: z.date().isDBIndexed().isSummaryField().excludeFromCreate().excludeFromUpdate().isAuditEvidence(),\n\n /** Set when a tenant administrator approved. Absent on an auto-approved grant — see {@link autoApprovalReason}. */\n approvedByUserId: z.string().min(1).optional().isForeignKey().excludeFromCreate().excludeFromUpdate().isAuditEvidence(),\n approvedAt: z.date().optional().excludeFromCreate().excludeFromUpdate(),\n\n /**\n * Present exactly when the grant became ACTIVE with no tenant administrator acting.\n *\n * Its absence on an ACTIVE grant is therefore meaningful: a human in the tenant approved it. That\n * distinction is what a customer audit needs and what a single `approved: true` boolean would erase.\n */\n autoApprovalReason: z.enum(PlatformAccessGrantAutoApprovalReason)\n .systemEnum('PlatformAccessGrantAutoApprovalReason')\n .optional()\n .excludeFromCreate()\n .excludeFromUpdate()\n .isAuditEvidence(),\n\n /** The tenant's reason for refusing, or the revoker's reason for withdrawing. */\n // REMOVE — free text again, and clearable (`.optional()`).\n decisionReason: addImpersonalizeWith(\n z.string().max(1000).optional().excludeFromCreate().excludeFromUpdate()\n .dataCategories(PersonalDataCategory.USER_CONTENT),\n RedactionType.REMOVE,\n ),\n\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\nexport type PlatformAccessGrant = z.infer<typeof PlatformAccessGrantSchema>;\n\n/**\n * Is this grant usable RIGHT NOW?\n *\n * The single predicate every consumer must use — the admission check, the tenant's UI, and any\n * report. Two independent conditions, and the expiry half is why this is a function rather than a\n * status comparison: a grant whose window elapsed is unusable the moment it elapses, with no writer\n * involved. Reading `status === ACTIVE` alone would honour a stale row for as long as no sweeper had\n * run, turning a time-bound elevation back into a standing one.\n *\n * `now` is injected so callers can evaluate a grant at a decision time they already fixed, and so\n * this stays testable without clock control.\n */\nexport function isPlatformAccessGrantUsable(\n grant: Pick<PlatformAccessGrant, 'status' | 'expiresAt'> | undefined,\n now: Date,\n): boolean {\n if (!grant) return false;\n if (grant.status !== PlatformAccessGrantStatus.ACTIVE) return false;\n return grant.expiresAt instanceof Date\n ? grant.expiresAt.getTime() > now.getTime()\n : new Date(grant.expiresAt).getTime() > now.getTime();\n}\n\n/**\n * Clamp a requested duration to the server-side ceiling.\n *\n * Applied to every request path, including trusted ones. A caller asking for a longer window is not\n * refused — being told \"no, ask again with a smaller number\" during an incident is friction with no\n * security benefit, since the ceiling is what actually binds. They simply get the ceiling.\n */\nexport function resolvePlatformAccessGrantExpiry(requestedDurationMinutes: number | undefined, now: Date): Date {\n const requested = requestedDurationMinutes && requestedDurationMinutes > 0\n ? requestedDurationMinutes\n : PLATFORM_ACCESS_GRANT_DEFAULT_DURATION_MINUTES;\n const minutes = Math.min(requested, PLATFORM_ACCESS_GRANT_MAXIMUM_DURATION_MINUTES);\n return new Date(now.getTime() + minutes * 60_000);\n}\n\n/**\n * NOTE ON PLACEMENT — this enum lives with the VOCABULARY, not with the resource configuration,\n * and moving it back would reintroduce a real defect.\n *\n * The authorization layer needs `REQUEST_ACCESS` by name (it is the bootstrap verb, exempt from the\n * grant requirement it bootstraps). Importing that value from the resources-config module dragged\n * resource-configuration evaluation into the authorizer's module graph, and schema construction that\n * runs before the Zod decorators are initialised loses decorator metadata — which surfaced, far from\n * here, as the ephemeral-disclosure catalogue losing an operation-level declaration. A vocabulary has\n * no such side effects.\n */\n/**\n * Custom verbs. Ordinary CREATE/UPDATE/DELETE are deliberately NOT exposed:\n *\n * - CREATE would let a caller author `status`, `expiresAt` and `operatorUserId` directly, which are\n * precisely the fields whose server authorship IS the control.\n * - UPDATE would be a second, ungated path to the status transitions `approve`/`deny`/`revoke` own.\n * - DELETE exists but has NO client door — see its configuration below. An elevation either side could\n * erase is not evidence; the terminal statuses (DENIED / EXPIRED / REVOKED) are how a grant ends.\n */\nexport enum PlatformAccessGrants_Operations {\n REQUEST_ACCESS = 'requestAccess',\n APPROVE = 'approve',\n DENY = 'deny',\n REVOKE = 'revoke',\n /**\n * ACTIVE → EXPIRED once the window has elapsed, dispatched by the credential-expiry sweep and by\n * nothing else (#413). Not an operator verb: an operator who wants access to end early uses\n * REVOKE, and nobody needs a button that declares a date has passed.\n */\n EXPIRE = 'expire',\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organization Provider Credentials — resource configuration.
|
|
3
|
+
*
|
|
4
|
+
* The tenant-owned service credential toward a third-party provider. See
|
|
5
|
+
* `provider-credentials.shared.schemas.ts` for what the resource is and what it deliberately is not.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { ProviderCredentialValidationState } from './provider-credentials.shared.schemas';
|
|
9
|
+
import { CoreResourceOperation } from '../../resources/resources.shared.core.definitions';
|
|
10
|
+
import { ResourceRelationship } from '../../resources/resources.shared.schemas';
|
|
11
|
+
type OrgProviderCredentialsCoreOperations = CoreResourceOperation.READ | CoreResourceOperation.LIST | CoreResourceOperation.CREATE | CoreResourceOperation.UPDATE | CoreResourceOperation.DELETE | CoreResourceOperation.UPDATE_MANY;
|
|
12
|
+
export declare const orgProviderCredentialsResourceConfiguration_InitializationFactory: (resourcesRelationships: ResourceRelationship[]) => import("../..").ResourceConfiguration<undefined, OrgProviderCredentialsCoreOperations, import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodObject<{
|
|
13
|
+
_id: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodString>>;
|
|
14
|
+
organizationId: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodString>>>>;
|
|
15
|
+
providerRef: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodString>>>;
|
|
16
|
+
secretSlug: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodString>>>;
|
|
17
|
+
secretValue: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodString>;
|
|
18
|
+
enabled: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodDefault<z.ZodBoolean>>>;
|
|
19
|
+
validationState: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodDefault<z.ZodEnum<typeof ProviderCredentialValidationState>>>>;
|
|
20
|
+
validationError: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodOptional<z.ZodString>>>;
|
|
21
|
+
lastValidatedAt: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodOptional<z.ZodDate>>>;
|
|
22
|
+
lastUsedAt: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodOptional<z.ZodDate>>>>;
|
|
23
|
+
setByUserId: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodOptional<z.ZodString>>>>;
|
|
24
|
+
secretSetAt: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodOptional<z.ZodDate>>>;
|
|
25
|
+
connectionParameters: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
26
|
+
description: z.ZodOptional<z.ZodString>;
|
|
27
|
+
createdAt: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodDefault<z.ZodDate>>>>>;
|
|
28
|
+
updatedAt: import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<import("@wildo-ai/zod-decorators").DecoratedPrimitiveZodType<z.ZodDefault<z.ZodDate>>>>;
|
|
29
|
+
}, z.core.$strip>>>;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=provider-credentials-organization.shared.resources-config.schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-credentials-organization.shared.resources-config.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAEL,iCAAiC,EAClC,MAAM,uCAAuC,CAAC;AAK/C,OAAO,EAAE,qBAAqB,EAAwD,MAAM,mDAAmD,CAAC;AAChJ,OAAO,EAA4D,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAY1I,KAAK,oCAAoC,GACrC,qBAAqB,CAAC,IAAI,GAC1B,qBAAqB,CAAC,IAAI,GAC1B,qBAAqB,CAAC,MAAM,GAC5B,qBAAqB,CAAC,MAAM,GAC5B,qBAAqB,CAAC,MAAM,GAC5B,qBAAqB,CAAC,WAAW,CAAC;AAEtC,eAAO,MAAM,iEAAiE,GAC5E,wBAAwB,oBAAoB,EAAE;;;;;;;;;;;;;;;;;mBA8L9C,CAAC"}
|