@portaidentity/server 1.7.3 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/applications/index.d.ts +2 -2
- package/dist/applications/index.d.ts.map +1 -1
- package/dist/applications/index.js +2 -2
- package/dist/applications/index.js.map +1 -1
- package/dist/applications/repository.d.ts +49 -4
- package/dist/applications/repository.d.ts.map +1 -1
- package/dist/applications/repository.js +148 -10
- package/dist/applications/repository.js.map +1 -1
- package/dist/applications/service.d.ts +35 -17
- package/dist/applications/service.d.ts.map +1 -1
- package/dist/applications/service.js +144 -35
- package/dist/applications/service.js.map +1 -1
- package/dist/applications/types.d.ts +1 -1
- package/dist/applications/types.d.ts.map +1 -1
- package/dist/applications/validators.d.ts +14 -0
- package/dist/applications/validators.d.ts.map +1 -0
- package/dist/applications/validators.js +14 -0
- package/dist/applications/validators.js.map +1 -0
- package/dist/auth/effective-branding.d.ts +35 -0
- package/dist/auth/effective-branding.d.ts.map +1 -0
- package/dist/auth/effective-branding.js +81 -0
- package/dist/auth/effective-branding.js.map +1 -0
- package/dist/auth/email-service.d.ts +3 -8
- package/dist/auth/email-service.d.ts.map +1 -1
- package/dist/auth/email-service.js +22 -30
- package/dist/auth/email-service.js.map +1 -1
- package/dist/auth/i18n.d.ts +5 -0
- package/dist/auth/i18n.d.ts.map +1 -1
- package/dist/auth/i18n.js +6 -5
- package/dist/auth/i18n.js.map +1 -1
- package/dist/auth/rate-limiter.d.ts +6 -10
- package/dist/auth/rate-limiter.d.ts.map +1 -1
- package/dist/auth/rate-limiter.js +12 -16
- package/dist/auth/rate-limiter.js.map +1 -1
- package/dist/auth/recovery-job-processor.d.ts.map +1 -1
- package/dist/auth/recovery-job-processor.js +1 -1
- package/dist/auth/recovery-job-processor.js.map +1 -1
- package/dist/auth/template-engine.d.ts +3 -1
- package/dist/auth/template-engine.d.ts.map +1 -1
- package/dist/auth/template-engine.js +1 -1
- package/dist/auth/template-engine.js.map +1 -1
- package/dist/auth/token-repository.d.ts +9 -3
- package/dist/auth/token-repository.d.ts.map +1 -1
- package/dist/auth/token-repository.js +17 -8
- package/dist/auth/token-repository.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +12 -12
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/error-handler.d.ts +3 -2
- package/dist/cli/error-handler.d.ts.map +1 -1
- package/dist/cli/error-handler.js +9 -2
- package/dist/cli/error-handler.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/clients/index.d.ts +1 -1
- package/dist/clients/index.js +1 -1
- package/dist/clients/repository.d.ts +24 -0
- package/dist/clients/repository.d.ts.map +1 -1
- package/dist/clients/repository.js +39 -0
- package/dist/clients/repository.js.map +1 -1
- package/dist/clients/secret-repository.d.ts +35 -8
- package/dist/clients/secret-repository.d.ts.map +1 -1
- package/dist/clients/secret-repository.js +69 -16
- package/dist/clients/secret-repository.js.map +1 -1
- package/dist/clients/secret-service.d.ts +5 -9
- package/dist/clients/secret-service.d.ts.map +1 -1
- package/dist/clients/secret-service.js +13 -22
- package/dist/clients/secret-service.js.map +1 -1
- package/dist/clients/service.d.ts +10 -13
- package/dist/clients/service.d.ts.map +1 -1
- package/dist/clients/service.js +121 -42
- package/dist/clients/service.js.map +1 -1
- package/dist/clients/types.d.ts +14 -1
- package/dist/clients/types.d.ts.map +1 -1
- package/dist/clients/types.js +1 -0
- package/dist/clients/types.js.map +1 -1
- package/dist/clients/validators.d.ts +83 -1
- package/dist/clients/validators.d.ts.map +1 -1
- package/dist/clients/validators.js +110 -0
- package/dist/clients/validators.js.map +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts +1 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +23 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/custom-claims/repository.d.ts +14 -9
- package/dist/custom-claims/repository.d.ts.map +1 -1
- package/dist/custom-claims/repository.js +38 -11
- package/dist/custom-claims/repository.js.map +1 -1
- package/dist/custom-claims/service.d.ts +11 -6
- package/dist/custom-claims/service.d.ts.map +1 -1
- package/dist/custom-claims/service.js +43 -20
- package/dist/custom-claims/service.js.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/admin-permissions.d.ts +12 -7
- package/dist/lib/admin-permissions.d.ts.map +1 -1
- package/dist/lib/admin-permissions.js +26 -16
- package/dist/lib/admin-permissions.js.map +1 -1
- package/dist/lib/audit-log.d.ts +2 -2
- package/dist/lib/audit-log.d.ts.map +1 -1
- package/dist/lib/audit-log.js +1 -1
- package/dist/lib/audit-log.js.map +1 -1
- package/dist/lib/authority-revocation.d.ts +18 -0
- package/dist/lib/authority-revocation.d.ts.map +1 -0
- package/dist/lib/authority-revocation.js +37 -0
- package/dist/lib/authority-revocation.js.map +1 -0
- package/dist/lib/branding-assets.d.ts +35 -5
- package/dist/lib/branding-assets.d.ts.map +1 -1
- package/dist/lib/branding-assets.js +33 -26
- package/dist/lib/branding-assets.js.map +1 -1
- package/dist/lib/bulk-operations.d.ts +1 -1
- package/dist/lib/bulk-operations.d.ts.map +1 -1
- package/dist/lib/bulk-operations.js +1 -13
- package/dist/lib/bulk-operations.js.map +1 -1
- package/dist/lib/cursor.d.ts +2 -0
- package/dist/lib/cursor.d.ts.map +1 -1
- package/dist/lib/cursor.js +2 -7
- package/dist/lib/cursor.js.map +1 -1
- package/dist/lib/database.d.ts.map +1 -1
- package/dist/lib/database.js +5 -0
- package/dist/lib/database.js.map +1 -1
- package/dist/lib/deletion-cleanup.d.ts +43 -0
- package/dist/lib/deletion-cleanup.d.ts.map +1 -0
- package/dist/lib/deletion-cleanup.js +207 -0
- package/dist/lib/deletion-cleanup.js.map +1 -0
- package/dist/lib/image-validator.d.ts +3 -1
- package/dist/lib/image-validator.d.ts.map +1 -1
- package/dist/lib/image-validator.js +32 -19
- package/dist/lib/image-validator.js.map +1 -1
- package/dist/lib/log-format.d.ts +20 -0
- package/dist/lib/log-format.d.ts.map +1 -0
- package/dist/lib/log-format.js +22 -0
- package/dist/lib/log-format.js.map +1 -0
- package/dist/lib/logger.d.ts +3 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +21 -4
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/redis.d.ts.map +1 -1
- package/dist/lib/redis.js +3 -0
- package/dist/lib/redis.js.map +1 -1
- package/dist/lib/session-tracking.d.ts +73 -11
- package/dist/lib/session-tracking.d.ts.map +1 -1
- package/dist/lib/session-tracking.js +76 -32
- package/dist/lib/session-tracking.js.map +1 -1
- package/dist/lib/signing-key-crypto.d.ts.map +1 -1
- package/dist/lib/signing-key-crypto.js +4 -5
- package/dist/lib/signing-key-crypto.js.map +1 -1
- package/dist/lib/signing-keys.d.ts +3 -4
- package/dist/lib/signing-keys.d.ts.map +1 -1
- package/dist/lib/signing-keys.js +66 -41
- package/dist/lib/signing-keys.js.map +1 -1
- package/dist/lib/super-admin-protection.d.ts +5 -5
- package/dist/lib/super-admin-protection.d.ts.map +1 -1
- package/dist/lib/super-admin-protection.js +6 -9
- package/dist/lib/super-admin-protection.js.map +1 -1
- package/dist/lib/system-config-catalog.d.ts +268 -0
- package/dist/lib/system-config-catalog.d.ts.map +1 -0
- package/dist/lib/system-config-catalog.js +90 -0
- package/dist/lib/system-config-catalog.js.map +1 -0
- package/dist/lib/system-config.d.ts +30 -33
- package/dist/lib/system-config.d.ts.map +1 -1
- package/dist/lib/system-config.js +78 -93
- package/dist/lib/system-config.js.map +1 -1
- package/dist/lib/with-timeout.d.ts +32 -0
- package/dist/lib/with-timeout.d.ts.map +1 -0
- package/dist/lib/with-timeout.js +45 -0
- package/dist/lib/with-timeout.js.map +1 -0
- package/dist/middleware/admin-auth.d.ts +6 -5
- package/dist/middleware/admin-auth.d.ts.map +1 -1
- package/dist/middleware/admin-auth.js +30 -20
- package/dist/middleware/admin-auth.js.map +1 -1
- package/dist/middleware/admin-cors.d.ts +3 -3
- package/dist/middleware/admin-cors.js +3 -3
- package/dist/middleware/admin-mutation-audit.d.ts +3 -2
- package/dist/middleware/admin-mutation-audit.d.ts.map +1 -1
- package/dist/middleware/admin-mutation-audit.js +12 -5
- package/dist/middleware/admin-mutation-audit.js.map +1 -1
- package/dist/middleware/admin-rate-limiter.d.ts +7 -8
- package/dist/middleware/admin-rate-limiter.d.ts.map +1 -1
- package/dist/middleware/admin-rate-limiter.js +7 -8
- package/dist/middleware/admin-rate-limiter.js.map +1 -1
- package/dist/middleware/client-secret-hash.d.ts +10 -29
- package/dist/middleware/client-secret-hash.d.ts.map +1 -1
- package/dist/middleware/client-secret-hash.js +161 -59
- package/dist/middleware/client-secret-hash.js.map +1 -1
- package/dist/middleware/health.d.ts +17 -0
- package/dist/middleware/health.d.ts.map +1 -1
- package/dist/middleware/health.js +25 -21
- package/dist/middleware/health.js.map +1 -1
- package/dist/middleware/ready.d.ts.map +1 -1
- package/dist/middleware/ready.js +1 -12
- package/dist/middleware/ready.js.map +1 -1
- package/dist/middleware/require-existing-organization.d.ts +18 -0
- package/dist/middleware/require-existing-organization.d.ts.map +1 -0
- package/dist/middleware/require-existing-organization.js +38 -0
- package/dist/middleware/require-existing-organization.js.map +1 -0
- package/dist/middleware/require-permission.d.ts.map +1 -1
- package/dist/middleware/require-permission.js +35 -1
- package/dist/middleware/require-permission.js.map +1 -1
- package/dist/middleware/require-user-organization.d.ts.map +1 -1
- package/dist/middleware/require-user-organization.js +4 -2
- package/dist/middleware/require-user-organization.js.map +1 -1
- package/dist/middleware/security-headers.d.ts +18 -0
- package/dist/middleware/security-headers.d.ts.map +1 -1
- package/dist/middleware/security-headers.js +32 -1
- package/dist/middleware/security-headers.js.map +1 -1
- package/dist/middleware/tenant-resolver.d.ts +1 -2
- package/dist/middleware/tenant-resolver.d.ts.map +1 -1
- package/dist/middleware/tenant-resolver.js +1 -5
- package/dist/middleware/tenant-resolver.js.map +1 -1
- package/dist/middleware/token-rate-limiter.d.ts +37 -16
- package/dist/middleware/token-rate-limiter.d.ts.map +1 -1
- package/dist/middleware/token-rate-limiter.js +126 -54
- package/dist/middleware/token-rate-limiter.js.map +1 -1
- package/dist/oidc/account-finder.d.ts +5 -5
- package/dist/oidc/account-finder.d.ts.map +1 -1
- package/dist/oidc/account-finder.js +31 -23
- package/dist/oidc/account-finder.js.map +1 -1
- package/dist/oidc/adapter-factory.d.ts.map +1 -1
- package/dist/oidc/adapter-factory.js +83 -3
- package/dist/oidc/adapter-factory.js.map +1 -1
- package/dist/oidc/configuration.d.ts +3 -8
- package/dist/oidc/configuration.d.ts.map +1 -1
- package/dist/oidc/configuration.js +67 -50
- package/dist/oidc/configuration.js.map +1 -1
- package/dist/oidc/provider.d.ts.map +1 -1
- package/dist/oidc/provider.js +7 -0
- package/dist/oidc/provider.js.map +1 -1
- package/dist/oidc/redis-adapter.d.ts +2 -3
- package/dist/oidc/redis-adapter.d.ts.map +1 -1
- package/dist/oidc/redis-adapter.js +54 -46
- package/dist/oidc/redis-adapter.js.map +1 -1
- package/dist/organizations/branding-url.d.ts +17 -0
- package/dist/organizations/branding-url.d.ts.map +1 -0
- package/dist/organizations/branding-url.js +38 -0
- package/dist/organizations/branding-url.js.map +1 -0
- package/dist/organizations/index.d.ts +2 -2
- package/dist/organizations/index.d.ts.map +1 -1
- package/dist/organizations/index.js +1 -1
- package/dist/organizations/index.js.map +1 -1
- package/dist/organizations/repository.d.ts +22 -32
- package/dist/organizations/repository.d.ts.map +1 -1
- package/dist/organizations/repository.js +64 -45
- package/dist/organizations/repository.js.map +1 -1
- package/dist/organizations/service.d.ts +14 -46
- package/dist/organizations/service.d.ts.map +1 -1
- package/dist/organizations/service.js +60 -112
- package/dist/organizations/service.js.map +1 -1
- package/dist/organizations/types.d.ts +1 -15
- package/dist/organizations/types.d.ts.map +1 -1
- package/dist/organizations/validators.d.ts +41 -0
- package/dist/organizations/validators.d.ts.map +1 -0
- package/dist/organizations/validators.js +48 -0
- package/dist/organizations/validators.js.map +1 -0
- package/dist/portability/apply.d.ts +15 -0
- package/dist/portability/apply.d.ts.map +1 -0
- package/dist/portability/apply.js +274 -0
- package/dist/portability/apply.js.map +1 -0
- package/dist/portability/authorization.d.ts +30 -0
- package/dist/portability/authorization.d.ts.map +1 -0
- package/dist/portability/authorization.js +130 -0
- package/dist/portability/authorization.js.map +1 -0
- package/dist/portability/cleanup.d.ts +29 -0
- package/dist/portability/cleanup.d.ts.map +1 -0
- package/dist/portability/cleanup.js +167 -0
- package/dist/portability/cleanup.js.map +1 -0
- package/dist/portability/export.d.ts +18 -0
- package/dist/portability/export.d.ts.map +1 -0
- package/dist/portability/export.js +125 -0
- package/dist/portability/export.js.map +1 -0
- package/dist/portability/import-repository.d.ts +204 -0
- package/dist/portability/import-repository.d.ts.map +1 -0
- package/dist/portability/import-repository.js +348 -0
- package/dist/portability/import-repository.js.map +1 -0
- package/dist/portability/import-user-client-writers.d.ts +40 -0
- package/dist/portability/import-user-client-writers.d.ts.map +1 -0
- package/dist/portability/import-user-client-writers.js +171 -0
- package/dist/portability/import-user-client-writers.js.map +1 -0
- package/dist/portability/index.d.ts +8 -0
- package/dist/portability/index.d.ts.map +1 -0
- package/dist/portability/index.js +8 -0
- package/dist/portability/index.js.map +1 -0
- package/dist/portability/plan-support.d.ts +137 -0
- package/dist/portability/plan-support.d.ts.map +1 -0
- package/dist/portability/plan-support.js +337 -0
- package/dist/portability/plan-support.js.map +1 -0
- package/dist/portability/plan.d.ts +34 -0
- package/dist/portability/plan.d.ts.map +1 -0
- package/dist/portability/plan.js +450 -0
- package/dist/portability/plan.js.map +1 -0
- package/dist/portability/repository.d.ts +95 -0
- package/dist/portability/repository.d.ts.map +1 -0
- package/dist/portability/repository.js +390 -0
- package/dist/portability/repository.js.map +1 -0
- package/dist/portability/schema.d.ts +591 -0
- package/dist/portability/schema.d.ts.map +1 -0
- package/dist/portability/schema.js +459 -0
- package/dist/portability/schema.js.map +1 -0
- package/dist/portability/types.d.ts +382 -0
- package/dist/portability/types.d.ts.map +1 -0
- package/dist/portability/types.js +19 -0
- package/dist/portability/types.js.map +1 -0
- package/dist/rbac/errors.d.ts +4 -0
- package/dist/rbac/errors.d.ts.map +1 -1
- package/dist/rbac/errors.js +7 -0
- package/dist/rbac/errors.js.map +1 -1
- package/dist/rbac/index.d.ts +3 -3
- package/dist/rbac/index.d.ts.map +1 -1
- package/dist/rbac/index.js +3 -3
- package/dist/rbac/index.js.map +1 -1
- package/dist/rbac/mapping-repository.d.ts +84 -9
- package/dist/rbac/mapping-repository.d.ts.map +1 -1
- package/dist/rbac/mapping-repository.js +222 -55
- package/dist/rbac/mapping-repository.js.map +1 -1
- package/dist/rbac/permission-repository.d.ts +36 -19
- package/dist/rbac/permission-repository.d.ts.map +1 -1
- package/dist/rbac/permission-repository.js +93 -35
- package/dist/rbac/permission-repository.js.map +1 -1
- package/dist/rbac/permission-service.d.ts +18 -19
- package/dist/rbac/permission-service.d.ts.map +1 -1
- package/dist/rbac/permission-service.js +100 -57
- package/dist/rbac/permission-service.js.map +1 -1
- package/dist/rbac/role-repository.d.ts +29 -24
- package/dist/rbac/role-repository.d.ts.map +1 -1
- package/dist/rbac/role-repository.js +66 -43
- package/dist/rbac/role-repository.js.map +1 -1
- package/dist/rbac/role-service.d.ts +35 -32
- package/dist/rbac/role-service.d.ts.map +1 -1
- package/dist/rbac/role-service.js +210 -96
- package/dist/rbac/role-service.js.map +1 -1
- package/dist/rbac/slugs.d.ts +16 -27
- package/dist/rbac/slugs.d.ts.map +1 -1
- package/dist/rbac/slugs.js +36 -59
- package/dist/rbac/slugs.js.map +1 -1
- package/dist/rbac/types.d.ts +2 -4
- package/dist/rbac/types.d.ts.map +1 -1
- package/dist/rbac/types.js.map +1 -1
- package/dist/rbac/user-role-service.d.ts +23 -24
- package/dist/rbac/user-role-service.d.ts.map +1 -1
- package/dist/rbac/user-role-service.js +117 -61
- package/dist/rbac/user-role-service.js.map +1 -1
- package/dist/routes/applications.d.ts +4 -2
- package/dist/routes/applications.d.ts.map +1 -1
- package/dist/routes/applications.js +57 -19
- package/dist/routes/applications.js.map +1 -1
- package/dist/routes/audit.js +1 -1
- package/dist/routes/audit.js.map +1 -1
- package/dist/routes/branding.d.ts +3 -3
- package/dist/routes/branding.d.ts.map +1 -1
- package/dist/routes/branding.js +44 -16
- package/dist/routes/branding.js.map +1 -1
- package/dist/routes/bulk.d.ts +0 -5
- package/dist/routes/bulk.d.ts.map +1 -1
- package/dist/routes/bulk.js +3 -5
- package/dist/routes/bulk.js.map +1 -1
- package/dist/routes/clients.d.ts +4 -4
- package/dist/routes/clients.d.ts.map +1 -1
- package/dist/routes/clients.js +113 -52
- package/dist/routes/clients.js.map +1 -1
- package/dist/routes/config.d.ts +17 -12
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +165 -64
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/custom-claims.d.ts.map +1 -1
- package/dist/routes/custom-claims.js +8 -2
- package/dist/routes/custom-claims.js.map +1 -1
- package/dist/routes/exports.d.ts +2 -1
- package/dist/routes/exports.d.ts.map +1 -1
- package/dist/routes/exports.js +57 -1
- package/dist/routes/exports.js.map +1 -1
- package/dist/routes/imports.d.ts +2 -2
- package/dist/routes/imports.d.ts.map +1 -1
- package/dist/routes/imports.js +95 -40
- package/dist/routes/imports.js.map +1 -1
- package/dist/routes/interactions.d.ts.map +1 -1
- package/dist/routes/interactions.js +113 -87
- package/dist/routes/interactions.js.map +1 -1
- package/dist/routes/invitation.d.ts.map +1 -1
- package/dist/routes/invitation.js +28 -27
- package/dist/routes/invitation.js.map +1 -1
- package/dist/routes/keys.d.ts.map +1 -1
- package/dist/routes/keys.js +26 -13
- package/dist/routes/keys.js.map +1 -1
- package/dist/routes/magic-link.d.ts.map +1 -1
- package/dist/routes/magic-link.js +5 -17
- package/dist/routes/magic-link.js.map +1 -1
- package/dist/routes/organizations.d.ts +1 -2
- package/dist/routes/organizations.d.ts.map +1 -1
- package/dist/routes/organizations.js +43 -104
- package/dist/routes/organizations.js.map +1 -1
- package/dist/routes/password-reset.d.ts.map +1 -1
- package/dist/routes/password-reset.js +13 -35
- package/dist/routes/password-reset.js.map +1 -1
- package/dist/routes/permissions.d.ts +1 -1
- package/dist/routes/permissions.d.ts.map +1 -1
- package/dist/routes/permissions.js +58 -17
- package/dist/routes/permissions.js.map +1 -1
- package/dist/routes/public-branding.d.ts +16 -0
- package/dist/routes/public-branding.d.ts.map +1 -0
- package/dist/routes/public-branding.js +52 -0
- package/dist/routes/public-branding.js.map +1 -0
- package/dist/routes/roles.d.ts +1 -1
- package/dist/routes/roles.d.ts.map +1 -1
- package/dist/routes/roles.js +63 -21
- package/dist/routes/roles.js.map +1 -1
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +23 -12
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/two-factor.d.ts.map +1 -1
- package/dist/routes/two-factor.js +91 -38
- package/dist/routes/two-factor.js.map +1 -1
- package/dist/routes/user-roles.d.ts.map +1 -1
- package/dist/routes/user-roles.js +56 -9
- package/dist/routes/user-roles.js.map +1 -1
- package/dist/routes/users.d.ts +4 -8
- package/dist/routes/users.d.ts.map +1 -1
- package/dist/routes/users.js +108 -265
- package/dist/routes/users.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +53 -37
- package/dist/server.js.map +1 -1
- package/dist/two-factor/errors.d.ts +9 -0
- package/dist/two-factor/errors.d.ts.map +1 -1
- package/dist/two-factor/errors.js +12 -0
- package/dist/two-factor/errors.js.map +1 -1
- package/dist/two-factor/index.d.ts +5 -4
- package/dist/two-factor/index.d.ts.map +1 -1
- package/dist/two-factor/index.js +4 -4
- package/dist/two-factor/index.js.map +1 -1
- package/dist/two-factor/repository.d.ts +17 -6
- package/dist/two-factor/repository.d.ts.map +1 -1
- package/dist/two-factor/repository.js +37 -9
- package/dist/two-factor/repository.js.map +1 -1
- package/dist/two-factor/service.d.ts.map +1 -1
- package/dist/two-factor/service.js +26 -19
- package/dist/two-factor/service.js.map +1 -1
- package/dist/two-factor/totp.d.ts +13 -2
- package/dist/two-factor/totp.d.ts.map +1 -1
- package/dist/two-factor/totp.js +20 -7
- package/dist/two-factor/totp.js.map +1 -1
- package/dist/two-factor/types.d.ts +3 -0
- package/dist/two-factor/types.d.ts.map +1 -1
- package/dist/two-factor/types.js +5 -0
- package/dist/two-factor/types.js.map +1 -1
- package/dist/users/gdpr.d.ts +2 -40
- package/dist/users/gdpr.d.ts.map +1 -1
- package/dist/users/gdpr.js +3 -110
- package/dist/users/gdpr.js.map +1 -1
- package/dist/users/index.d.ts +5 -4
- package/dist/users/index.d.ts.map +1 -1
- package/dist/users/index.js +5 -4
- package/dist/users/index.js.map +1 -1
- package/dist/users/repository.d.ts +49 -3
- package/dist/users/repository.d.ts.map +1 -1
- package/dist/users/repository.js +169 -18
- package/dist/users/repository.js.map +1 -1
- package/dist/users/service.d.ts +19 -51
- package/dist/users/service.d.ts.map +1 -1
- package/dist/users/service.js +72 -122
- package/dist/users/service.js.map +1 -1
- package/dist/users/types.d.ts +4 -5
- package/dist/users/types.d.ts.map +1 -1
- package/dist/users/types.js.map +1 -1
- package/dist/users/validators.d.ts +28 -0
- package/dist/users/validators.d.ts.map +1 -0
- package/dist/users/validators.js +25 -0
- package/dist/users/validators.js.map +1 -0
- package/locales/default/en/errors.json +2 -1
- package/migrations/024_application_client_correction.sql +39 -0
- package/migrations/025_record_deletion_lifecycle.sql +26 -0
- package/migrations/026_simplify_user_lifecycle.sql +33 -0
- package/migrations/027_branding_asset_size_limits.sql +19 -0
- package/migrations/028_totp_replay_protection.sql +17 -0
- package/migrations/029_public_session_identifiers.sql +16 -0
- package/migrations/030_global_configuration_catalog.sql +39 -0
- package/migrations/031_monotonic_updated_at.sql +28 -0
- package/migrations/032_client_require_consent.sql +15 -0
- package/package.json +2 -2
- package/dist/lib/data-import-plan.d.ts +0 -50
- package/dist/lib/data-import-plan.d.ts.map +0 -1
- package/dist/lib/data-import-plan.js +0 -235
- package/dist/lib/data-import-plan.js.map +0 -1
- package/dist/lib/data-import.d.ts +0 -276
- package/dist/lib/data-import.d.ts.map +0 -1
- package/dist/lib/data-import.js +0 -1694
- package/dist/lib/data-import.js.map +0 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { afterDatabaseCommit } from './database.js';
|
|
2
|
+
import { logger } from './logger.js';
|
|
3
|
+
import { getRedis } from './redis.js';
|
|
4
|
+
/** OIDC models currently stored beneath the Redis adapter namespace. */
|
|
5
|
+
const REDIS_OIDC_MODELS = [
|
|
6
|
+
'Session',
|
|
7
|
+
'Interaction',
|
|
8
|
+
'AuthorizationCode',
|
|
9
|
+
'ReplayDetection',
|
|
10
|
+
'ClientCredentials',
|
|
11
|
+
'PushedAuthorizationRequest',
|
|
12
|
+
];
|
|
13
|
+
const REDIS_OIDC_MODEL_SET = new Set(REDIS_OIDC_MODELS);
|
|
14
|
+
/** Atomically remove a reusable slug key only while it still names the deleted record. */
|
|
15
|
+
const DELETE_MATCHING_SLUG = `
|
|
16
|
+
local value = redis.call('GET', KEYS[1])
|
|
17
|
+
if not value then return 0 end
|
|
18
|
+
local ok, decoded = pcall(cjson.decode, value)
|
|
19
|
+
if ok and decoded['id'] == ARGV[1] then
|
|
20
|
+
return redis.call('DEL', KEYS[1])
|
|
21
|
+
end
|
|
22
|
+
return 0
|
|
23
|
+
`;
|
|
24
|
+
/** Return true when a decoded payload is safe to inspect by field name. */
|
|
25
|
+
function isRecord(value) {
|
|
26
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
27
|
+
}
|
|
28
|
+
/** Test one optional string field against a captured identifier set. */
|
|
29
|
+
function hasReference(values, value) {
|
|
30
|
+
return typeof value === 'string' && values.has(value);
|
|
31
|
+
}
|
|
32
|
+
/** Determine whether an OIDC payload references authority removed by the deletion. */
|
|
33
|
+
function referencesDeletedAuthority(payload, clientIds, grantIds, userIds) {
|
|
34
|
+
if (hasReference(clientIds, payload.clientId) ||
|
|
35
|
+
hasReference(grantIds, payload.grantId) ||
|
|
36
|
+
hasReference(userIds, payload.accountId)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (!isRecord(payload.authorizations))
|
|
40
|
+
return false;
|
|
41
|
+
return Object.entries(payload.authorizations).some(([clientId, authorization]) => clientIds.has(clientId) ||
|
|
42
|
+
(isRecord(authorization) && hasReference(grantIds, authorization.grantId)));
|
|
43
|
+
}
|
|
44
|
+
/** Build the exact cache and grant-index keys represented by a deletion descriptor. */
|
|
45
|
+
function exactKeys(descriptor) {
|
|
46
|
+
const keys = new Set(exactAuthorityKeys(descriptor));
|
|
47
|
+
if (descriptor.resource === 'organization')
|
|
48
|
+
keys.add(`org:id:${descriptor.targetId}`);
|
|
49
|
+
if (descriptor.resource === 'application') {
|
|
50
|
+
keys.add(`app:id:${descriptor.targetId}`);
|
|
51
|
+
keys.add(`claims:defs:${descriptor.targetId}`);
|
|
52
|
+
}
|
|
53
|
+
if (descriptor.resource === 'claim') {
|
|
54
|
+
for (const applicationId of descriptor.applicationIds) {
|
|
55
|
+
keys.add(`claims:defs:${applicationId}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const id of descriptor.clientIds)
|
|
59
|
+
keys.add(`client:id:${id}`);
|
|
60
|
+
for (const id of descriptor.publicClientIds)
|
|
61
|
+
keys.add(`client:cid:${id}`);
|
|
62
|
+
for (const id of descriptor.userIds) {
|
|
63
|
+
keys.add(`user:id:${id}`);
|
|
64
|
+
}
|
|
65
|
+
return [...keys];
|
|
66
|
+
}
|
|
67
|
+
/** Build exact RBAC cache keys for an authority change. */
|
|
68
|
+
function exactAuthorityKeys(descriptor) {
|
|
69
|
+
const keys = new Set();
|
|
70
|
+
for (const id of descriptor.roleIds)
|
|
71
|
+
keys.add(`rbac:role:${id}`);
|
|
72
|
+
for (const id of descriptor.userIds) {
|
|
73
|
+
keys.add(`rbac:user-roles:${id}`);
|
|
74
|
+
keys.add(`rbac:user-perms:${id}`);
|
|
75
|
+
}
|
|
76
|
+
for (const model of REDIS_OIDC_MODELS) {
|
|
77
|
+
for (const grantId of descriptor.grantIds) {
|
|
78
|
+
keys.add(`oidc:${model}:grant:${grantId}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return [...keys];
|
|
82
|
+
}
|
|
83
|
+
/** Read one JSON payload without allowing malformed Redis data to stop cleanup. */
|
|
84
|
+
function parsePayload(value) {
|
|
85
|
+
if (value === null)
|
|
86
|
+
return null;
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(value);
|
|
89
|
+
return isRecord(parsed) ? parsed : null;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Remove matching OIDC main payloads and the indexes derivable from those payloads. */
|
|
96
|
+
async function scanOidcPayloads(descriptor) {
|
|
97
|
+
const redis = getRedis();
|
|
98
|
+
const clientIds = new Set(descriptor.publicClientIds);
|
|
99
|
+
const grantIds = new Set(descriptor.grantIds);
|
|
100
|
+
const userIds = new Set(descriptor.userIds);
|
|
101
|
+
let cursor = '0';
|
|
102
|
+
do {
|
|
103
|
+
const [nextCursor, candidates] = await redis.scan(cursor, 'MATCH', 'oidc:*', 'COUNT', 100);
|
|
104
|
+
cursor = nextCursor;
|
|
105
|
+
const mainKeys = candidates.filter((key) => {
|
|
106
|
+
const parts = key.split(':');
|
|
107
|
+
return parts.length === 3 && parts[0] === 'oidc' && REDIS_OIDC_MODEL_SET.has(parts[1]);
|
|
108
|
+
});
|
|
109
|
+
if (mainKeys.length === 0)
|
|
110
|
+
continue;
|
|
111
|
+
const payloads = await redis.mget(...mainKeys);
|
|
112
|
+
const keysToDelete = new Set();
|
|
113
|
+
for (let index = 0; index < mainKeys.length; index += 1) {
|
|
114
|
+
const payload = parsePayload(payloads[index] ?? null);
|
|
115
|
+
if (!payload || !referencesDeletedAuthority(payload, clientIds, grantIds, userIds))
|
|
116
|
+
continue;
|
|
117
|
+
const mainKey = mainKeys[index];
|
|
118
|
+
const model = mainKey.split(':')[1];
|
|
119
|
+
keysToDelete.add(mainKey);
|
|
120
|
+
if (typeof payload.uid === 'string')
|
|
121
|
+
keysToDelete.add(`oidc:${model}:uid:${payload.uid}`);
|
|
122
|
+
if (typeof payload.userCode === 'string') {
|
|
123
|
+
keysToDelete.add(`oidc:${model}:user_code:${payload.userCode}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (keysToDelete.size > 0)
|
|
127
|
+
await redis.del(...keysToDelete);
|
|
128
|
+
} while (cursor !== '0');
|
|
129
|
+
}
|
|
130
|
+
/** Remove exact RBAC keys and user-linked OIDC state after an authority change. */
|
|
131
|
+
async function cleanupAuthorityRedis(descriptor) {
|
|
132
|
+
const redis = getRedis();
|
|
133
|
+
const keys = exactAuthorityKeys(descriptor);
|
|
134
|
+
if (keys.length > 0)
|
|
135
|
+
await redis.del(...keys);
|
|
136
|
+
if (descriptor.revokeOidcState) {
|
|
137
|
+
await scanOidcPayloads({
|
|
138
|
+
userIds: descriptor.userIds,
|
|
139
|
+
publicClientIds: [],
|
|
140
|
+
grantIds: descriptor.grantIds,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/** Execute the single best-effort Redis cleanup pass for a committed deletion. */
|
|
145
|
+
async function cleanupDeletionRedis(descriptor) {
|
|
146
|
+
const redis = getRedis();
|
|
147
|
+
const keys = exactKeys(descriptor);
|
|
148
|
+
if (keys.length > 0)
|
|
149
|
+
await redis.del(...keys);
|
|
150
|
+
if (descriptor.targetSlug && descriptor.resource === 'organization') {
|
|
151
|
+
await redis.eval(DELETE_MATCHING_SLUG, 1, `org:slug:${descriptor.targetSlug}`, descriptor.targetId);
|
|
152
|
+
}
|
|
153
|
+
if (descriptor.targetSlug && descriptor.resource === 'application') {
|
|
154
|
+
await redis.eval(DELETE_MATCHING_SLUG, 1, `app:slug:${descriptor.targetSlug}`, descriptor.targetId);
|
|
155
|
+
}
|
|
156
|
+
await scanOidcPayloads(descriptor);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Register immutable cleanup input on the current transaction's post-commit boundary.
|
|
160
|
+
* The hook schedules one detached Redis pass and returns without waiting for cache I/O.
|
|
161
|
+
*
|
|
162
|
+
* @param descriptor - Identifiers captured before the database cascade.
|
|
163
|
+
*/
|
|
164
|
+
export async function registerDeletionCleanup(descriptor) {
|
|
165
|
+
const immutable = Object.freeze({
|
|
166
|
+
...descriptor,
|
|
167
|
+
userIds: Object.freeze([...descriptor.userIds]),
|
|
168
|
+
clientIds: Object.freeze([...descriptor.clientIds]),
|
|
169
|
+
publicClientIds: Object.freeze([...descriptor.publicClientIds]),
|
|
170
|
+
grantIds: Object.freeze([...descriptor.grantIds]),
|
|
171
|
+
roleIds: Object.freeze([...descriptor.roleIds]),
|
|
172
|
+
permissionIds: Object.freeze([...descriptor.permissionIds]),
|
|
173
|
+
claimIds: Object.freeze([...descriptor.claimIds]),
|
|
174
|
+
applicationIds: Object.freeze([...descriptor.applicationIds]),
|
|
175
|
+
});
|
|
176
|
+
await afterDatabaseCommit(async () => {
|
|
177
|
+
setImmediate(() => {
|
|
178
|
+
void cleanupDeletionRedis(immutable).catch(() => {
|
|
179
|
+
logger.warn({ event: 'deletion-redis-cleanup-failed' }, 'Deletion Redis cleanup failed');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Register targeted RBAC cleanup after the current transaction commits.
|
|
186
|
+
*
|
|
187
|
+
* The hook schedules one best-effort Redis pass and does not hold the request
|
|
188
|
+
* open for cache I/O. Failures emit one fixed warning without identifiers.
|
|
189
|
+
*
|
|
190
|
+
* @param descriptor - Authority identifiers captured inside the transaction
|
|
191
|
+
*/
|
|
192
|
+
export async function registerAuthorityCleanup(descriptor) {
|
|
193
|
+
const immutable = Object.freeze({
|
|
194
|
+
userIds: Object.freeze([...descriptor.userIds]),
|
|
195
|
+
grantIds: Object.freeze([...descriptor.grantIds]),
|
|
196
|
+
roleIds: Object.freeze([...descriptor.roleIds]),
|
|
197
|
+
revokeOidcState: descriptor.revokeOidcState,
|
|
198
|
+
});
|
|
199
|
+
await afterDatabaseCommit(async () => {
|
|
200
|
+
setImmediate(() => {
|
|
201
|
+
void cleanupAuthorityRedis(immutable).catch(() => {
|
|
202
|
+
logger.warn({ event: 'authority-redis-cleanup-failed' }, 'Authority Redis cleanup failed');
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=deletion-cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deletion-cleanup.js","sourceRoot":"","sources":["../../src/lib/deletion-cleanup.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
* - SVG-based XSS via embedded scripts or event handlers
|
|
9
9
|
*
|
|
10
10
|
* @module image-validator
|
|
11
|
-
* @see 06-bulk-operations-branding.md
|
|
12
11
|
*/
|
|
12
|
+
/** Branding image slot whose size limit should be enforced. */
|
|
13
13
|
export type AssetType = 'logo' | 'favicon';
|
|
14
14
|
/** Result of image validation — either valid or contains an error message */
|
|
15
15
|
export interface ImageValidationResult {
|
|
16
|
+
/** Whether the supplied bytes satisfy every validation rule. */
|
|
16
17
|
valid: boolean;
|
|
18
|
+
/** Human-readable validation failure for trusted internal callers. */
|
|
17
19
|
error?: string;
|
|
18
20
|
/** The detected content type from magic bytes (may differ from declared) */
|
|
19
21
|
detectedType?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-validator.d.ts","sourceRoot":"","sources":["../../src/lib/image-validator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"image-validator.d.ts","sourceRoot":"","sources":["../../src/lib/image-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,+DAA+D;AAC/D,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3C,6EAA6E;AAC7E,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,KAAK,EAAE,OAAO,CAAC;IACf,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA0ED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,SAAS,GACnB,qBAAqB,CA8BvB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAEzD"}
|
|
@@ -8,15 +8,14 @@
|
|
|
8
8
|
* - SVG-based XSS via embedded scripts or event handlers
|
|
9
9
|
*
|
|
10
10
|
* @module image-validator
|
|
11
|
-
* @see 06-bulk-operations-branding.md
|
|
12
11
|
*/
|
|
13
12
|
// ============================================================================
|
|
14
13
|
// Constants
|
|
15
14
|
// ============================================================================
|
|
16
15
|
/** Size limits per asset type (in bytes) */
|
|
17
16
|
const SIZE_LIMITS = {
|
|
18
|
-
logo: 2 * 1024 * 1024,
|
|
19
|
-
favicon: 512 * 1024,
|
|
17
|
+
logo: 2 * 1024 * 1024,
|
|
18
|
+
favicon: 512 * 1024,
|
|
20
19
|
};
|
|
21
20
|
/**
|
|
22
21
|
* Magic byte signatures for supported image formats.
|
|
@@ -24,11 +23,23 @@ const SIZE_LIMITS = {
|
|
|
24
23
|
* SVG is XML-based and has no magic bytes — validated separately.
|
|
25
24
|
*/
|
|
26
25
|
const MAGIC_SIGNATURES = [
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{ type: 'image/
|
|
26
|
+
{
|
|
27
|
+
type: 'image/png',
|
|
28
|
+
segments: [{ offset: 0, bytes: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] }],
|
|
29
|
+
},
|
|
30
|
+
{ type: 'image/jpeg', segments: [{ offset: 0, bytes: [0xff, 0xd8] }] },
|
|
31
|
+
{
|
|
32
|
+
type: 'image/webp',
|
|
33
|
+
segments: [
|
|
34
|
+
{ offset: 0, bytes: [0x52, 0x49, 0x46, 0x46] },
|
|
35
|
+
{ offset: 8, bytes: [0x57, 0x45, 0x42, 0x50] },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
{ type: 'image/x-icon', segments: [{ offset: 0, bytes: [0x00, 0x00, 0x01, 0x00] }] },
|
|
39
|
+
{
|
|
40
|
+
type: 'image/vnd.microsoft.icon',
|
|
41
|
+
segments: [{ offset: 0, bytes: [0x00, 0x00, 0x01, 0x00] }],
|
|
42
|
+
},
|
|
32
43
|
];
|
|
33
44
|
/** Content types that are allowed for upload */
|
|
34
45
|
const ALLOWED_TYPES = new Set([
|
|
@@ -110,16 +121,14 @@ function validateMagicBytes(buffer, contentType) {
|
|
|
110
121
|
// No signature defined for this type — allow it (shouldn't happen due to ALLOWED_TYPES check)
|
|
111
122
|
return { valid: true, detectedType: contentType, data: buffer };
|
|
112
123
|
}
|
|
113
|
-
|
|
114
|
-
if (buffer.length <
|
|
124
|
+
const requiredLength = Math.max(...signature.segments.map((segment) => segment.offset + segment.bytes.length));
|
|
125
|
+
if (buffer.length < requiredLength) {
|
|
115
126
|
return {
|
|
116
127
|
valid: false,
|
|
117
128
|
error: `File too small to be a valid ${contentType} image`,
|
|
118
129
|
};
|
|
119
130
|
}
|
|
120
|
-
|
|
121
|
-
const matches = signature.bytes.every((byte, i) => buffer[i] === byte);
|
|
122
|
-
if (!matches) {
|
|
131
|
+
if (!matchesSignature(buffer, signature)) {
|
|
123
132
|
// Try to detect what the file actually is
|
|
124
133
|
const detected = detectContentType(buffer);
|
|
125
134
|
return {
|
|
@@ -145,7 +154,10 @@ function validateAndSanitizeSvg(buffer) {
|
|
|
145
154
|
}
|
|
146
155
|
// Basic SVG structure check — must contain an <svg element
|
|
147
156
|
if (!/<svg[\s>]/i.test(content)) {
|
|
148
|
-
return {
|
|
157
|
+
return {
|
|
158
|
+
valid: false,
|
|
159
|
+
error: 'File does not appear to be a valid SVG (no <svg> element found)',
|
|
160
|
+
};
|
|
149
161
|
}
|
|
150
162
|
// Sanitize: strip dangerous elements and attributes
|
|
151
163
|
let sanitized = content;
|
|
@@ -183,14 +195,15 @@ function validateAndSanitizeSvg(buffer) {
|
|
|
183
195
|
*/
|
|
184
196
|
function detectContentType(buffer) {
|
|
185
197
|
for (const sig of MAGIC_SIGNATURES) {
|
|
186
|
-
if (buffer
|
|
187
|
-
|
|
188
|
-
if (matches)
|
|
189
|
-
return sig.type;
|
|
190
|
-
}
|
|
198
|
+
if (matchesSignature(buffer, sig))
|
|
199
|
+
return sig.type;
|
|
191
200
|
}
|
|
192
201
|
return null;
|
|
193
202
|
}
|
|
203
|
+
/** Return whether every required segment is present at its exact byte offset. */
|
|
204
|
+
function matchesSignature(buffer, signature) {
|
|
205
|
+
return signature.segments.every((segment) => segment.bytes.every((byte, index) => buffer[segment.offset + index] === byte));
|
|
206
|
+
}
|
|
194
207
|
/**
|
|
195
208
|
* Format bytes into a human-readable string (e.g., "512 KB", "2 MB").
|
|
196
209
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-validator.js","sourceRoot":"","sources":["../../src/lib/image-validator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"image-validator.js","sourceRoot":"","sources":["../../src/lib/image-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log output format selection for the process logger.
|
|
3
|
+
*
|
|
4
|
+
* Production always emits structured JSON so an external collector can parse each event without
|
|
5
|
+
* guessing at human formatting. An owner-controlled non-production runtime may request the same
|
|
6
|
+
* format through the `PORTA_LOG_FORMAT` environment variable. Only the exact value `json` is
|
|
7
|
+
* recognized; any other value keeps the human-readable development default.
|
|
8
|
+
*
|
|
9
|
+
* @module lib/log-format
|
|
10
|
+
*/
|
|
11
|
+
/** Exact `PORTA_LOG_FORMAT` value which requests structured JSON logs outside production. */
|
|
12
|
+
export declare const JSON_LOG_FORMAT_VALUE = "json";
|
|
13
|
+
/**
|
|
14
|
+
* Decide whether the process logger must emit structured JSON.
|
|
15
|
+
*
|
|
16
|
+
* @param environment - Process environment to read, defaulting to the running process.
|
|
17
|
+
* @returns True when structured JSON logging is required.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveJsonLogFormat(environment?: NodeJS.ProcessEnv): boolean;
|
|
20
|
+
//# sourceMappingURL=log-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-format.d.ts","sourceRoot":"","sources":["../../src/lib/log-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,6FAA6F;AAC7F,eAAO,MAAM,qBAAqB,SAAS,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAI1F"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log output format selection for the process logger.
|
|
3
|
+
*
|
|
4
|
+
* Production always emits structured JSON so an external collector can parse each event without
|
|
5
|
+
* guessing at human formatting. An owner-controlled non-production runtime may request the same
|
|
6
|
+
* format through the `PORTA_LOG_FORMAT` environment variable. Only the exact value `json` is
|
|
7
|
+
* recognized; any other value keeps the human-readable development default.
|
|
8
|
+
*
|
|
9
|
+
* @module lib/log-format
|
|
10
|
+
*/
|
|
11
|
+
/** Exact `PORTA_LOG_FORMAT` value which requests structured JSON logs outside production. */
|
|
12
|
+
export const JSON_LOG_FORMAT_VALUE = 'json';
|
|
13
|
+
/**
|
|
14
|
+
* Decide whether the process logger must emit structured JSON.
|
|
15
|
+
*
|
|
16
|
+
* @param environment - Process environment to read, defaulting to the running process.
|
|
17
|
+
* @returns True when structured JSON logging is required.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveJsonLogFormat(environment = process.env) {
|
|
20
|
+
return (environment.NODE_ENV === 'production' || environment.PORTA_LOG_FORMAT === JSON_LOG_FORMAT_VALUE);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=log-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-format.js","sourceRoot":"","sources":["../../src/lib/log-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,6FAA6F;AAC7F,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAW,GAAsB,OAAO,CAAC,GAAG;IAC/E,OAAO,CACL,WAAW,CAAC,QAAQ,KAAK,YAAY,IAAI,WAAW,CAAC,gBAAgB,KAAK,qBAAqB,CAChG,CAAC;AACJ,CAAC"}
|
package/dist/lib/logger.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ export type OperationalLogObserver = (serializedArguments: string) => void;
|
|
|
5
5
|
*
|
|
6
6
|
* This is intended for owner-controlled diagnostics and executable privacy validation. Observers
|
|
7
7
|
* are process-local, receive no replay buffer, and must detach immediately after their bounded
|
|
8
|
-
* operation.
|
|
8
|
+
* operation. While at least one observer is attached, the logger accepts every level so the
|
|
9
|
+
* observer can validate calls hidden by a quiet test configuration. The original level is restored
|
|
10
|
+
* after the final observer detaches. Observers cannot alter, suppress, or replace a log write.
|
|
9
11
|
*
|
|
10
12
|
* @param observer - Callback receiving one JSON representation per logger call.
|
|
11
13
|
* @returns A function which removes exactly this observer.
|
package/dist/lib/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAIA,uFAAuF;AACvF,MAAM,MAAM,sBAAsB,GAAG,CAAC,mBAAmB,EAAE,MAAM,KAAK,IAAI,CAAC;AAK3E;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,IAAI,CAaxF;AAID,eAAO,MAAM,MAAM,uCAqDjB,CAAC"}
|
package/dist/lib/logger.js
CHANGED
|
@@ -1,24 +1,39 @@
|
|
|
1
1
|
import { pino, stdSerializers } from 'pino';
|
|
2
|
+
import { resolveJsonLogFormat } from './log-format.js';
|
|
2
3
|
const operationalLogObservers = new Set();
|
|
4
|
+
let levelBeforeOperationalObservation = null;
|
|
3
5
|
/**
|
|
4
6
|
* Observe arguments delivered to the production logger boundary.
|
|
5
7
|
*
|
|
6
8
|
* This is intended for owner-controlled diagnostics and executable privacy validation. Observers
|
|
7
9
|
* are process-local, receive no replay buffer, and must detach immediately after their bounded
|
|
8
|
-
* operation.
|
|
10
|
+
* operation. While at least one observer is attached, the logger accepts every level so the
|
|
11
|
+
* observer can validate calls hidden by a quiet test configuration. The original level is restored
|
|
12
|
+
* after the final observer detaches. Observers cannot alter, suppress, or replace a log write.
|
|
9
13
|
*
|
|
10
14
|
* @param observer - Callback receiving one JSON representation per logger call.
|
|
11
15
|
* @returns A function which removes exactly this observer.
|
|
12
16
|
*/
|
|
13
17
|
export function observeOperationalLogOutput(observer) {
|
|
18
|
+
if (operationalLogObservers.size === 0) {
|
|
19
|
+
levelBeforeOperationalObservation = logger.level;
|
|
20
|
+
logger.level = 'trace';
|
|
21
|
+
}
|
|
14
22
|
operationalLogObservers.add(observer);
|
|
15
|
-
return () =>
|
|
23
|
+
return () => {
|
|
24
|
+
operationalLogObservers.delete(observer);
|
|
25
|
+
if (operationalLogObservers.size === 0 && levelBeforeOperationalObservation !== null) {
|
|
26
|
+
logger.level = levelBeforeOperationalObservation;
|
|
27
|
+
levelBeforeOperationalObservation = null;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
16
30
|
}
|
|
17
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
|
18
31
|
const isTest = process.env.NODE_ENV === 'test';
|
|
19
32
|
export const logger = pino({
|
|
20
33
|
level: process.env.LOG_LEVEL || (isTest ? 'silent' : 'info'),
|
|
21
|
-
transport:
|
|
34
|
+
transport: resolveJsonLogFormat()
|
|
35
|
+
? undefined
|
|
36
|
+
: { target: 'pino-pretty', options: { colorize: true } },
|
|
22
37
|
serializers: {
|
|
23
38
|
err: stdSerializers.err,
|
|
24
39
|
req: stdSerializers.req,
|
|
@@ -46,12 +61,14 @@ export const logger = pino({
|
|
|
46
61
|
'cookie',
|
|
47
62
|
'refresh_token',
|
|
48
63
|
'client_secret',
|
|
64
|
+
'urn:porta:internal_application_id',
|
|
49
65
|
'req.headers.authorization',
|
|
50
66
|
'req.headers.cookie',
|
|
51
67
|
'*.password',
|
|
52
68
|
'*.token',
|
|
53
69
|
'*.refresh_token',
|
|
54
70
|
'*.client_secret',
|
|
71
|
+
'*.urn:porta:internal_application_id',
|
|
55
72
|
'*.authorization',
|
|
56
73
|
'email',
|
|
57
74
|
'userId',
|
package/dist/lib/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/redis.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/lib/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/lib/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAShC,wBAAsB,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC,CAenD;AAED,wBAAgB,QAAQ,IAAI,KAAK,CAGhC;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAMrD"}
|
package/dist/lib/redis.js
CHANGED
|
@@ -2,8 +2,11 @@ import { Redis } from 'ioredis';
|
|
|
2
2
|
import { config } from '../config/index.js';
|
|
3
3
|
import { logger } from './logger.js';
|
|
4
4
|
let redis = null;
|
|
5
|
+
/** Maximum time one Redis command may hold a public request while Redis is unavailable. */
|
|
6
|
+
const REDIS_COMMAND_TIMEOUT_MS = 1000;
|
|
5
7
|
export async function connectRedis() {
|
|
6
8
|
redis = new Redis(config.redisUrl, {
|
|
9
|
+
commandTimeout: REDIS_COMMAND_TIMEOUT_MS,
|
|
7
10
|
maxRetriesPerRequest: 3,
|
|
8
11
|
lazyConnect: true,
|
|
9
12
|
});
|
package/dist/lib/redis.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/lib/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,IAAI,KAAK,GAAiB,IAAI,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;QACjC,oBAAoB,EAAE,CAAC;QACvB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IACtB,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAE/B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;QAC/B,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,GAAG,IAAI,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/lib/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,IAAI,KAAK,GAAiB,IAAI,CAAC;AAE/B,2FAA2F;AAC3F,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;QACjC,cAAc,EAAE,wBAAwB;QACxC,oBAAoB,EAAE,CAAC;QACvB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IACtB,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAE/B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;QAC/B,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,GAAG,IAAI,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
|