@adaptive-ds/project-registry 0.2.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/LICENSE +22 -0
- package/README.md +40 -0
- package/dist/access/Actor.d.ts +7 -0
- package/dist/access/Actor.d.ts.map +1 -0
- package/dist/access/Actor.js +2 -0
- package/dist/access/Actor.js.map +1 -0
- package/dist/access/ProjectAccess.d.ts +8 -0
- package/dist/access/ProjectAccess.d.ts.map +1 -0
- package/dist/access/ProjectAccess.js +2 -0
- package/dist/access/ProjectAccess.js.map +1 -0
- package/dist/access/ProjectAccessCreateOptions.d.ts +27 -0
- package/dist/access/ProjectAccessCreateOptions.d.ts.map +1 -0
- package/dist/access/ProjectAccessCreateOptions.js +2 -0
- package/dist/access/ProjectAccessCreateOptions.js.map +1 -0
- package/dist/access/Role.d.ts +2 -0
- package/dist/access/Role.d.ts.map +1 -0
- package/dist/access/Role.js +2 -0
- package/dist/access/Role.js.map +1 -0
- package/dist/access/SuperadminOperation.d.ts +2 -0
- package/dist/access/SuperadminOperation.d.ts.map +1 -0
- package/dist/access/SuperadminOperation.js +2 -0
- package/dist/access/SuperadminOperation.js.map +1 -0
- package/dist/access/projectAccessCreate.d.ts +4 -0
- package/dist/access/projectAccessCreate.d.ts.map +1 -0
- package/dist/access/projectAccessCreate.js +180 -0
- package/dist/access/projectAccessCreate.js.map +1 -0
- package/dist/access/projectAuthorize.d.ts +5 -0
- package/dist/access/projectAuthorize.d.ts.map +1 -0
- package/dist/access/projectAuthorize.js +34 -0
- package/dist/access/projectAuthorize.js.map +1 -0
- package/dist/access/roleResolve.d.ts +4 -0
- package/dist/access/roleResolve.d.ts.map +1 -0
- package/dist/access/roleResolve.js +21 -0
- package/dist/access/roleResolve.js.map +1 -0
- package/dist/access/serviceAuthorize.d.ts +5 -0
- package/dist/access/serviceAuthorize.d.ts.map +1 -0
- package/dist/access/serviceAuthorize.js +10 -0
- package/dist/access/serviceAuthorize.js.map +1 -0
- package/dist/access/superadminAuthorize.d.ts +5 -0
- package/dist/access/superadminAuthorize.d.ts.map +1 -0
- package/dist/access/superadminAuthorize.js +24 -0
- package/dist/access/superadminAuthorize.js.map +1 -0
- package/dist/access/visibleUserList.d.ts +6 -0
- package/dist/access/visibleUserList.d.ts.map +1 -0
- package/dist/access/visibleUserList.js +51 -0
- package/dist/access/visibleUserList.js.map +1 -0
- package/dist/access-log/ProjectAccessLogRecord.d.ts +8 -0
- package/dist/access-log/ProjectAccessLogRecord.d.ts.map +1 -0
- package/dist/access-log/ProjectAccessLogRecord.js +2 -0
- package/dist/access-log/ProjectAccessLogRecord.js.map +1 -0
- package/dist/access-log/ProjectAccessLogSource.d.ts +22 -0
- package/dist/access-log/ProjectAccessLogSource.d.ts.map +1 -0
- package/dist/access-log/ProjectAccessLogSource.js +2 -0
- package/dist/access-log/ProjectAccessLogSource.js.map +1 -0
- package/dist/access-log/projectAccessLogCaddyRetention.d.ts +5 -0
- package/dist/access-log/projectAccessLogCaddyRetention.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogCaddyRetention.js +5 -0
- package/dist/access-log/projectAccessLogCaddyRetention.js.map +1 -0
- package/dist/access-log/projectAccessLogCursor.d.ts +22 -0
- package/dist/access-log/projectAccessLogCursor.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogCursor.js +148 -0
- package/dist/access-log/projectAccessLogCursor.js.map +1 -0
- package/dist/access-log/projectAccessLogId.d.ts +3 -0
- package/dist/access-log/projectAccessLogId.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogId.js +6 -0
- package/dist/access-log/projectAccessLogId.js.map +1 -0
- package/dist/access-log/projectAccessLogListUseCase.d.ts +14 -0
- package/dist/access-log/projectAccessLogListUseCase.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogListUseCase.js +74 -0
- package/dist/access-log/projectAccessLogListUseCase.js.map +1 -0
- package/dist/access-log/projectAccessLogOpenat2.d.ts +12 -0
- package/dist/access-log/projectAccessLogOpenat2.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogOpenat2.js +123 -0
- package/dist/access-log/projectAccessLogOpenat2.js.map +1 -0
- package/dist/access-log/projectAccessLogParser.d.ts +4 -0
- package/dist/access-log/projectAccessLogParser.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogParser.js +88 -0
- package/dist/access-log/projectAccessLogParser.js.map +1 -0
- package/dist/access-log/projectAccessLogPath.d.ts +4 -0
- package/dist/access-log/projectAccessLogPath.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogPath.js +11 -0
- package/dist/access-log/projectAccessLogPath.js.map +1 -0
- package/dist/access-log/projectAccessLogRetentionMaximumActiveProjectIds.d.ts +2 -0
- package/dist/access-log/projectAccessLogRetentionMaximumActiveProjectIds.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogRetentionMaximumActiveProjectIds.js +2 -0
- package/dist/access-log/projectAccessLogRetentionMaximumActiveProjectIds.js.map +1 -0
- package/dist/access-log/projectAccessLogRetentionReconcile.d.ts +19 -0
- package/dist/access-log/projectAccessLogRetentionReconcile.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogRetentionReconcile.js +1365 -0
- package/dist/access-log/projectAccessLogRetentionReconcile.js.map +1 -0
- package/dist/access-log/projectAccessLogRootSchema.d.ts +3 -0
- package/dist/access-log/projectAccessLogRootSchema.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogRootSchema.js +4 -0
- package/dist/access-log/projectAccessLogRootSchema.js.map +1 -0
- package/dist/access-log/projectAccessLogRootValidate.d.ts +3 -0
- package/dist/access-log/projectAccessLogRootValidate.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogRootValidate.js +18 -0
- package/dist/access-log/projectAccessLogRootValidate.js.map +1 -0
- package/dist/access-log/projectAccessLogSourceFileCreate.d.ts +22 -0
- package/dist/access-log/projectAccessLogSourceFileCreate.d.ts.map +1 -0
- package/dist/access-log/projectAccessLogSourceFileCreate.js +871 -0
- package/dist/access-log/projectAccessLogSourceFileCreate.js.map +1 -0
- package/dist/api/projectRegistryApiHandlerCreate.d.ts +18 -0
- package/dist/api/projectRegistryApiHandlerCreate.d.ts.map +1 -0
- package/dist/api/projectRegistryApiHandlerCreate.js +738 -0
- package/dist/api/projectRegistryApiHandlerCreate.js.map +1 -0
- package/dist/caddy/CaddyAdminLoadOptions.d.ts +10 -0
- package/dist/caddy/CaddyAdminLoadOptions.d.ts.map +1 -0
- package/dist/caddy/CaddyAdminLoadOptions.js +2 -0
- package/dist/caddy/CaddyAdminLoadOptions.js.map +1 -0
- package/dist/caddy/CaddyApplication.d.ts +12 -0
- package/dist/caddy/CaddyApplication.d.ts.map +1 -0
- package/dist/caddy/CaddyApplication.js +2 -0
- package/dist/caddy/CaddyApplication.js.map +1 -0
- package/dist/caddy/CaddyApplicationOptions.d.ts +24 -0
- package/dist/caddy/CaddyApplicationOptions.d.ts.map +1 -0
- package/dist/caddy/CaddyApplicationOptions.js +2 -0
- package/dist/caddy/CaddyApplicationOptions.js.map +1 -0
- package/dist/caddy/CaddyApplicationQueue.d.ts +4 -0
- package/dist/caddy/CaddyApplicationQueue.d.ts.map +1 -0
- package/dist/caddy/CaddyApplicationQueue.js +2 -0
- package/dist/caddy/CaddyApplicationQueue.js.map +1 -0
- package/dist/caddy/CaddyApplicationResult.d.ts +8 -0
- package/dist/caddy/CaddyApplicationResult.d.ts.map +1 -0
- package/dist/caddy/CaddyApplicationResult.js +2 -0
- package/dist/caddy/CaddyApplicationResult.js.map +1 -0
- package/dist/caddy/CaddyApplicationStatus.d.ts +11 -0
- package/dist/caddy/CaddyApplicationStatus.d.ts.map +1 -0
- package/dist/caddy/CaddyApplicationStatus.js +2 -0
- package/dist/caddy/CaddyApplicationStatus.js.map +1 -0
- package/dist/caddy/CaddyClock.d.ts +2 -0
- package/dist/caddy/CaddyClock.d.ts.map +1 -0
- package/dist/caddy/CaddyClock.js +2 -0
- package/dist/caddy/CaddyClock.js.map +1 -0
- package/dist/caddy/CaddyConfig.d.ts +38 -0
- package/dist/caddy/CaddyConfig.d.ts.map +1 -0
- package/dist/caddy/CaddyConfig.js +2 -0
- package/dist/caddy/CaddyConfig.js.map +1 -0
- package/dist/caddy/CaddyConfigInspectUseCaseOptions.d.ts +6 -0
- package/dist/caddy/CaddyConfigInspectUseCaseOptions.d.ts.map +1 -0
- package/dist/caddy/CaddyConfigInspectUseCaseOptions.js +2 -0
- package/dist/caddy/CaddyConfigInspectUseCaseOptions.js.map +1 -0
- package/dist/caddy/CaddyConfigInspection.d.ts +10 -0
- package/dist/caddy/CaddyConfigInspection.d.ts.map +1 -0
- package/dist/caddy/CaddyConfigInspection.js +2 -0
- package/dist/caddy/CaddyConfigInspection.js.map +1 -0
- package/dist/caddy/CaddyConfigSummaryEntry.d.ts +9 -0
- package/dist/caddy/CaddyConfigSummaryEntry.d.ts.map +1 -0
- package/dist/caddy/CaddyConfigSummaryEntry.js +2 -0
- package/dist/caddy/CaddyConfigSummaryEntry.js.map +1 -0
- package/dist/caddy/CaddyConfigValidateOptions.d.ts +10 -0
- package/dist/caddy/CaddyConfigValidateOptions.d.ts.map +1 -0
- package/dist/caddy/CaddyConfigValidateOptions.js +2 -0
- package/dist/caddy/CaddyConfigValidateOptions.js.map +1 -0
- package/dist/caddy/CaddyDocsUrlsUseCaseOptions.d.ts +8 -0
- package/dist/caddy/CaddyDocsUrlsUseCaseOptions.d.ts.map +1 -0
- package/dist/caddy/CaddyDocsUrlsUseCaseOptions.js +2 -0
- package/dist/caddy/CaddyDocsUrlsUseCaseOptions.js.map +1 -0
- package/dist/caddy/CaddyFetch.d.ts +2 -0
- package/dist/caddy/CaddyFetch.d.ts.map +1 -0
- package/dist/caddy/CaddyFetch.js +2 -0
- package/dist/caddy/CaddyFetch.js.map +1 -0
- package/dist/caddy/CaddyInspectionOptions.d.ts +10 -0
- package/dist/caddy/CaddyInspectionOptions.d.ts.map +1 -0
- package/dist/caddy/CaddyInspectionOptions.js +2 -0
- package/dist/caddy/CaddyInspectionOptions.js.map +1 -0
- package/dist/caddy/CaddyProcessRunOptions.d.ts +5 -0
- package/dist/caddy/CaddyProcessRunOptions.d.ts.map +1 -0
- package/dist/caddy/CaddyProcessRunOptions.js +2 -0
- package/dist/caddy/CaddyProcessRunOptions.js.map +1 -0
- package/dist/caddy/CaddyProcessRunner.d.ts +8 -0
- package/dist/caddy/CaddyProcessRunner.d.ts.map +1 -0
- package/dist/caddy/CaddyProcessRunner.js +2 -0
- package/dist/caddy/CaddyProcessRunner.js.map +1 -0
- package/dist/caddy/CaddyProjectListAccess.d.ts +7 -0
- package/dist/caddy/CaddyProjectListAccess.d.ts.map +1 -0
- package/dist/caddy/CaddyProjectListAccess.js +2 -0
- package/dist/caddy/CaddyProjectListAccess.js.map +1 -0
- package/dist/caddy/CaddyTimer.d.ts +8 -0
- package/dist/caddy/CaddyTimer.d.ts.map +1 -0
- package/dist/caddy/CaddyTimer.js +2 -0
- package/dist/caddy/CaddyTimer.js.map +1 -0
- package/dist/caddy/caddyAdminLoad.d.ts +6 -0
- package/dist/caddy/caddyAdminLoad.d.ts.map +1 -0
- package/dist/caddy/caddyAdminLoad.js +222 -0
- package/dist/caddy/caddyAdminLoad.js.map +1 -0
- package/dist/caddy/caddyAdminReload.d.ts +3 -0
- package/dist/caddy/caddyAdminReload.d.ts.map +1 -0
- package/dist/caddy/caddyAdminReload.js +5 -0
- package/dist/caddy/caddyAdminReload.js.map +1 -0
- package/dist/caddy/caddyApplicationCreate.d.ts +6 -0
- package/dist/caddy/caddyApplicationCreate.d.ts.map +1 -0
- package/dist/caddy/caddyApplicationCreate.js +776 -0
- package/dist/caddy/caddyApplicationCreate.js.map +1 -0
- package/dist/caddy/caddyApplicationQueueCreate.d.ts +3 -0
- package/dist/caddy/caddyApplicationQueueCreate.d.ts.map +1 -0
- package/dist/caddy/caddyApplicationQueueCreate.js +11 -0
- package/dist/caddy/caddyApplicationQueueCreate.js.map +1 -0
- package/dist/caddy/caddyConfigGenerate.d.ts +4 -0
- package/dist/caddy/caddyConfigGenerate.d.ts.map +1 -0
- package/dist/caddy/caddyConfigGenerate.js +390 -0
- package/dist/caddy/caddyConfigGenerate.js.map +1 -0
- package/dist/caddy/caddyConfigInspect.d.ts +4 -0
- package/dist/caddy/caddyConfigInspect.d.ts.map +1 -0
- package/dist/caddy/caddyConfigInspect.js +61 -0
- package/dist/caddy/caddyConfigInspect.js.map +1 -0
- package/dist/caddy/caddyConfigInspectUseCase.d.ts +5 -0
- package/dist/caddy/caddyConfigInspectUseCase.d.ts.map +1 -0
- package/dist/caddy/caddyConfigInspectUseCase.js +19 -0
- package/dist/caddy/caddyConfigInspectUseCase.js.map +1 -0
- package/dist/caddy/caddyConfigOptionsFromEnv.d.ts +4 -0
- package/dist/caddy/caddyConfigOptionsFromEnv.d.ts.map +1 -0
- package/dist/caddy/caddyConfigOptionsFromEnv.js +44 -0
- package/dist/caddy/caddyConfigOptionsFromEnv.js.map +1 -0
- package/dist/caddy/caddyConfigOptionsSchema.d.ts +47 -0
- package/dist/caddy/caddyConfigOptionsSchema.d.ts.map +1 -0
- package/dist/caddy/caddyConfigOptionsSchema.js +24 -0
- package/dist/caddy/caddyConfigOptionsSchema.js.map +1 -0
- package/dist/caddy/caddyConfigSelect.d.ts +5 -0
- package/dist/caddy/caddyConfigSelect.d.ts.map +1 -0
- package/dist/caddy/caddyConfigSelect.js +128 -0
- package/dist/caddy/caddyConfigSelect.js.map +1 -0
- package/dist/caddy/caddyConfigSerialize.d.ts +3 -0
- package/dist/caddy/caddyConfigSerialize.d.ts.map +1 -0
- package/dist/caddy/caddyConfigSerialize.js +121 -0
- package/dist/caddy/caddyConfigSerialize.js.map +1 -0
- package/dist/caddy/caddyConfigSummary.d.ts +4 -0
- package/dist/caddy/caddyConfigSummary.d.ts.map +1 -0
- package/dist/caddy/caddyConfigSummary.js +47 -0
- package/dist/caddy/caddyConfigSummary.js.map +1 -0
- package/dist/caddy/caddyConfigValidate.d.ts +6 -0
- package/dist/caddy/caddyConfigValidate.d.ts.map +1 -0
- package/dist/caddy/caddyConfigValidate.js +214 -0
- package/dist/caddy/caddyConfigValidate.js.map +1 -0
- package/dist/caddy/caddyDocsTemplate.d.ts +2 -0
- package/dist/caddy/caddyDocsTemplate.d.ts.map +1 -0
- package/dist/caddy/caddyDocsTemplate.js +6 -0
- package/dist/caddy/caddyDocsTemplate.js.map +1 -0
- package/dist/caddy/caddyProcessRun.d.ts +13 -0
- package/dist/caddy/caddyProcessRun.d.ts.map +1 -0
- package/dist/caddy/caddyProcessRun.js +128 -0
- package/dist/caddy/caddyProcessRun.js.map +1 -0
- package/dist/caddy/caddyProcessRunnerAsUser.d.ts +3 -0
- package/dist/caddy/caddyProcessRunnerAsUser.d.ts.map +1 -0
- package/dist/caddy/caddyProcessRunnerAsUser.js +5 -0
- package/dist/caddy/caddyProcessRunnerAsUser.js.map +1 -0
- package/dist/caddy/caddyVisibleProjects.d.ts +5 -0
- package/dist/caddy/caddyVisibleProjects.d.ts.map +1 -0
- package/dist/caddy/caddyVisibleProjects.js +54 -0
- package/dist/caddy/caddyVisibleProjects.js.map +1 -0
- package/dist/caddy/projectDocsUrls.d.ts +6 -0
- package/dist/caddy/projectDocsUrls.d.ts.map +1 -0
- package/dist/caddy/projectDocsUrls.js +47 -0
- package/dist/caddy/projectDocsUrls.js.map +1 -0
- package/dist/caddy/projectDocsUrlsUseCase.d.ts +5 -0
- package/dist/caddy/projectDocsUrlsUseCase.d.ts.map +1 -0
- package/dist/caddy/projectDocsUrlsUseCase.js +38 -0
- package/dist/caddy/projectDocsUrlsUseCase.js.map +1 -0
- package/dist/cli/ProjectRegistryCliCaddyOptions.d.ts +14 -0
- package/dist/cli/ProjectRegistryCliCaddyOptions.d.ts.map +1 -0
- package/dist/cli/ProjectRegistryCliCaddyOptions.js +2 -0
- package/dist/cli/ProjectRegistryCliCaddyOptions.js.map +1 -0
- package/dist/cli/ProjectRegistryCliFetch.d.ts +4 -0
- package/dist/cli/ProjectRegistryCliFetch.d.ts.map +1 -0
- package/dist/cli/ProjectRegistryCliFetch.js +2 -0
- package/dist/cli/ProjectRegistryCliFetch.js.map +1 -0
- package/dist/cli/ProjectRegistryCliInvocation.d.ts +59 -0
- package/dist/cli/ProjectRegistryCliInvocation.d.ts.map +1 -0
- package/dist/cli/ProjectRegistryCliInvocation.js +2 -0
- package/dist/cli/ProjectRegistryCliInvocation.js.map +1 -0
- package/dist/cli/projectNameFromPath.d.ts +8 -0
- package/dist/cli/projectNameFromPath.d.ts.map +1 -0
- package/dist/cli/projectNameFromPath.js +29 -0
- package/dist/cli/projectNameFromPath.js.map +1 -0
- package/dist/cli/projectRegistryCliArgumentsParse.d.ts +4 -0
- package/dist/cli/projectRegistryCliArgumentsParse.d.ts.map +1 -0
- package/dist/cli/projectRegistryCliArgumentsParse.js +386 -0
- package/dist/cli/projectRegistryCliArgumentsParse.js.map +1 -0
- package/dist/cli/projectRegistryCliHelp.d.ts +2 -0
- package/dist/cli/projectRegistryCliHelp.d.ts.map +1 -0
- package/dist/cli/projectRegistryCliHelp.js +38 -0
- package/dist/cli/projectRegistryCliHelp.js.map +1 -0
- package/dist/cli/projectRegistryCliOutputFormat.d.ts +4 -0
- package/dist/cli/projectRegistryCliOutputFormat.d.ts.map +1 -0
- package/dist/cli/projectRegistryCliOutputFormat.js +208 -0
- package/dist/cli/projectRegistryCliOutputFormat.js.map +1 -0
- package/dist/cli/projectRegistryCliRequest.d.ts +9 -0
- package/dist/cli/projectRegistryCliRequest.d.ts.map +1 -0
- package/dist/cli/projectRegistryCliRequest.js +75 -0
- package/dist/cli/projectRegistryCliRequest.js.map +1 -0
- package/dist/cli/projectRegistryCliRun.d.ts +10 -0
- package/dist/cli/projectRegistryCliRun.d.ts.map +1 -0
- package/dist/cli/projectRegistryCliRun.js +200 -0
- package/dist/cli/projectRegistryCliRun.js.map +1 -0
- package/dist/cli/projectRegistryCliSocketResolve.d.ts +3 -0
- package/dist/cli/projectRegistryCliSocketResolve.d.ts.map +1 -0
- package/dist/cli/projectRegistryCliSocketResolve.js +21 -0
- package/dist/cli/projectRegistryCliSocketResolve.js.map +1 -0
- package/dist/cli/projectRegistryCliVersion.d.ts +2 -0
- package/dist/cli/projectRegistryCliVersion.d.ts.map +1 -0
- package/dist/cli/projectRegistryCliVersion.js +2 -0
- package/dist/cli/projectRegistryCliVersion.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -0
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +40 -0
- package/dist/daemon.js.map +1 -0
- package/dist/identity/IdentityDirectory.d.ts +8 -0
- package/dist/identity/IdentityDirectory.d.ts.map +1 -0
- package/dist/identity/IdentityDirectory.js +2 -0
- package/dist/identity/IdentityDirectory.js.map +1 -0
- package/dist/identity/IdentityDirectoryUser.d.ts +5 -0
- package/dist/identity/IdentityDirectoryUser.d.ts.map +1 -0
- package/dist/identity/IdentityDirectoryUser.js +2 -0
- package/dist/identity/IdentityDirectoryUser.js.map +1 -0
- package/dist/identity/MappedUser.d.ts +7 -0
- package/dist/identity/MappedUser.d.ts.map +1 -0
- package/dist/identity/MappedUser.js +2 -0
- package/dist/identity/MappedUser.js.map +1 -0
- package/dist/identity/PosixUserDirectory.d.ts +5 -0
- package/dist/identity/PosixUserDirectory.d.ts.map +1 -0
- package/dist/identity/PosixUserDirectory.js +2 -0
- package/dist/identity/PosixUserDirectory.js.map +1 -0
- package/dist/identity/VisibleUser.d.ts +7 -0
- package/dist/identity/VisibleUser.d.ts.map +1 -0
- package/dist/identity/VisibleUser.js +2 -0
- package/dist/identity/VisibleUser.js.map +1 -0
- package/dist/identity/VisibleUserDirectoryListOptions.d.ts +12 -0
- package/dist/identity/VisibleUserDirectoryListOptions.d.ts.map +1 -0
- package/dist/identity/VisibleUserDirectoryListOptions.js +2 -0
- package/dist/identity/VisibleUserDirectoryListOptions.js.map +1 -0
- package/dist/identity/posixUserDirectoryCreate.d.ts +4 -0
- package/dist/identity/posixUserDirectoryCreate.d.ts.map +1 -0
- package/dist/identity/posixUserDirectoryCreate.js +47 -0
- package/dist/identity/posixUserDirectoryCreate.js.map +1 -0
- package/dist/identity/preferredUsernameMap.d.ts +7 -0
- package/dist/identity/preferredUsernameMap.d.ts.map +1 -0
- package/dist/identity/preferredUsernameMap.js +19 -0
- package/dist/identity/preferredUsernameMap.js.map +1 -0
- package/dist/identity/userRoleResolve.d.ts +8 -0
- package/dist/identity/userRoleResolve.d.ts.map +1 -0
- package/dist/identity/userRoleResolve.js +31 -0
- package/dist/identity/userRoleResolve.js.map +1 -0
- package/dist/identity/visibleUserDirectoryList.d.ts +6 -0
- package/dist/identity/visibleUserDirectoryList.d.ts.map +1 -0
- package/dist/identity/visibleUserDirectoryList.js +70 -0
- package/dist/identity/visibleUserDirectoryList.js.map +1 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/project/Project.d.ts +2 -0
- package/dist/project/Project.d.ts.map +1 -0
- package/dist/project/Project.js +2 -0
- package/dist/project/Project.js.map +1 -0
- package/dist/project/ProjectMutationOptions.d.ts +5 -0
- package/dist/project/ProjectMutationOptions.d.ts.map +1 -0
- package/dist/project/ProjectMutationOptions.js +2 -0
- package/dist/project/ProjectMutationOptions.js.map +1 -0
- package/dist/project/ProjectUseCaseOptions.d.ts +9 -0
- package/dist/project/ProjectUseCaseOptions.d.ts.map +1 -0
- package/dist/project/ProjectUseCaseOptions.js +2 -0
- package/dist/project/ProjectUseCaseOptions.js.map +1 -0
- package/dist/project/projectCollisions.d.ts +10 -0
- package/dist/project/projectCollisions.d.ts.map +1 -0
- package/dist/project/projectCollisions.js +67 -0
- package/dist/project/projectCollisions.js.map +1 -0
- package/dist/project/projectCreate.d.ts +6 -0
- package/dist/project/projectCreate.d.ts.map +1 -0
- package/dist/project/projectCreate.js +40 -0
- package/dist/project/projectCreate.js.map +1 -0
- package/dist/project/projectDelete.d.ts +7 -0
- package/dist/project/projectDelete.d.ts.map +1 -0
- package/dist/project/projectDelete.js +24 -0
- package/dist/project/projectDelete.js.map +1 -0
- package/dist/project/projectDomainNormalize.d.ts +2 -0
- package/dist/project/projectDomainNormalize.d.ts.map +1 -0
- package/dist/project/projectDomainNormalize.js +4 -0
- package/dist/project/projectDomainNormalize.js.map +1 -0
- package/dist/project/projectEdit.d.ts +7 -0
- package/dist/project/projectEdit.d.ts.map +1 -0
- package/dist/project/projectEdit.js +85 -0
- package/dist/project/projectEdit.js.map +1 -0
- package/dist/project/projectGet.d.ts +5 -0
- package/dist/project/projectGet.d.ts.map +1 -0
- package/dist/project/projectGet.js +12 -0
- package/dist/project/projectGet.js.map +1 -0
- package/dist/project/projectGetUseCase.d.ts +6 -0
- package/dist/project/projectGetUseCase.d.ts.map +1 -0
- package/dist/project/projectGetUseCase.js +19 -0
- package/dist/project/projectGetUseCase.js.map +1 -0
- package/dist/project/projectHeaderUpSchema.d.ts +3 -0
- package/dist/project/projectHeaderUpSchema.d.ts.map +1 -0
- package/dist/project/projectHeaderUpSchema.js +28 -0
- package/dist/project/projectHeaderUpSchema.js.map +1 -0
- package/dist/project/projectHistory.d.ts +6 -0
- package/dist/project/projectHistory.d.ts.map +1 -0
- package/dist/project/projectHistory.js +11 -0
- package/dist/project/projectHistory.js.map +1 -0
- package/dist/project/projectInputSchema.d.ts +36 -0
- package/dist/project/projectInputSchema.d.ts.map +1 -0
- package/dist/project/projectInputSchema.js +42 -0
- package/dist/project/projectInputSchema.js.map +1 -0
- package/dist/project/projectKey.d.ts +4 -0
- package/dist/project/projectKey.d.ts.map +1 -0
- package/dist/project/projectKey.js +4 -0
- package/dist/project/projectKey.js.map +1 -0
- package/dist/project/projectKeyEqual.d.ts +3 -0
- package/dist/project/projectKeyEqual.d.ts.map +1 -0
- package/dist/project/projectKeyEqual.js +4 -0
- package/dist/project/projectKeyEqual.js.map +1 -0
- package/dist/project/projectList.d.ts +4 -0
- package/dist/project/projectList.d.ts.map +1 -0
- package/dist/project/projectList.js +6 -0
- package/dist/project/projectList.js.map +1 -0
- package/dist/project/projectListUseCase.d.ts +12 -0
- package/dist/project/projectListUseCase.d.ts.map +1 -0
- package/dist/project/projectListUseCase.js +78 -0
- package/dist/project/projectListUseCase.js.map +1 -0
- package/dist/project/projectMutationExpectedRevision.d.ts +4 -0
- package/dist/project/projectMutationExpectedRevision.d.ts.map +1 -0
- package/dist/project/projectMutationExpectedRevision.js +21 -0
- package/dist/project/projectMutationExpectedRevision.js.map +1 -0
- package/dist/project/projectNormalize.d.ts +12 -0
- package/dist/project/projectNormalize.d.ts.map +1 -0
- package/dist/project/projectNormalize.js +174 -0
- package/dist/project/projectNormalize.js.map +1 -0
- package/dist/project/projectOwnerAuthorize.d.ts +5 -0
- package/dist/project/projectOwnerAuthorize.d.ts.map +1 -0
- package/dist/project/projectOwnerAuthorize.js +12 -0
- package/dist/project/projectOwnerAuthorize.js.map +1 -0
- package/dist/project/projectPortCollision.d.ts +4 -0
- package/dist/project/projectPortCollision.d.ts.map +1 -0
- package/dist/project/projectPortCollision.js +12 -0
- package/dist/project/projectPortCollision.js.map +1 -0
- package/dist/project/projectPortNext.d.ts +9 -0
- package/dist/project/projectPortNext.d.ts.map +1 -0
- package/dist/project/projectPortNext.js +32 -0
- package/dist/project/projectPortNext.js.map +1 -0
- package/dist/project/projectRevisionValidate.d.ts +4 -0
- package/dist/project/projectRevisionValidate.d.ts.map +1 -0
- package/dist/project/projectRevisionValidate.js +9 -0
- package/dist/project/projectRevisionValidate.js.map +1 -0
- package/dist/project/projectSchema.d.ts +36 -0
- package/dist/project/projectSchema.d.ts.map +1 -0
- package/dist/project/projectSchema.js +43 -0
- package/dist/project/projectSchema.js.map +1 -0
- package/dist/project/projectSort.d.ts +3 -0
- package/dist/project/projectSort.d.ts.map +1 -0
- package/dist/project/projectSort.js +24 -0
- package/dist/project/projectSort.js.map +1 -0
- package/dist/project/projectValidate.d.ts +10 -0
- package/dist/project/projectValidate.d.ts.map +1 -0
- package/dist/project/projectValidate.js +26 -0
- package/dist/project/projectValidate.js.map +1 -0
- package/dist/project-store/ProjectRepository.d.ts +20 -0
- package/dist/project-store/ProjectRepository.d.ts.map +1 -0
- package/dist/project-store/ProjectRepository.js +2 -0
- package/dist/project-store/ProjectRepository.js.map +1 -0
- package/dist/project-store/ProjectRepositoryEntry.d.ts +7 -0
- package/dist/project-store/ProjectRepositoryEntry.d.ts.map +1 -0
- package/dist/project-store/ProjectRepositoryEntry.js +2 -0
- package/dist/project-store/ProjectRepositoryEntry.js.map +1 -0
- package/dist/project-store/ProjectRepositoryMutation.d.ts +18 -0
- package/dist/project-store/ProjectRepositoryMutation.d.ts.map +1 -0
- package/dist/project-store/ProjectRepositoryMutation.js +2 -0
- package/dist/project-store/ProjectRepositoryMutation.js.map +1 -0
- package/dist/project-store/ProjectRepositoryMutationOptions.d.ts +6 -0
- package/dist/project-store/ProjectRepositoryMutationOptions.d.ts.map +1 -0
- package/dist/project-store/ProjectRepositoryMutationOptions.js +2 -0
- package/dist/project-store/ProjectRepositoryMutationOptions.js.map +1 -0
- package/dist/project-store/ProjectRepositoryOptions.d.ts +8 -0
- package/dist/project-store/ProjectRepositoryOptions.d.ts.map +1 -0
- package/dist/project-store/ProjectRepositoryOptions.js +7 -0
- package/dist/project-store/ProjectRepositoryOptions.js.map +1 -0
- package/dist/project-store/ProjectRepositoryReadiness.d.ts +8 -0
- package/dist/project-store/ProjectRepositoryReadiness.d.ts.map +1 -0
- package/dist/project-store/ProjectRepositoryReadiness.js +2 -0
- package/dist/project-store/ProjectRepositoryReadiness.js.map +1 -0
- package/dist/project-store/ProjectRepositoryRevision.d.ts +2 -0
- package/dist/project-store/ProjectRepositoryRevision.d.ts.map +1 -0
- package/dist/project-store/ProjectRepositoryRevision.js +2 -0
- package/dist/project-store/ProjectRepositoryRevision.js.map +1 -0
- package/dist/project-store/ProjectRepositorySnapshot.d.ts +7 -0
- package/dist/project-store/ProjectRepositorySnapshot.d.ts.map +1 -0
- package/dist/project-store/ProjectRepositorySnapshot.js +2 -0
- package/dist/project-store/ProjectRepositorySnapshot.js.map +1 -0
- package/dist/project-store/projectRepositoryOpen.d.ts +4 -0
- package/dist/project-store/projectRepositoryOpen.d.ts.map +1 -0
- package/dist/project-store/projectRepositoryOpen.js +813 -0
- package/dist/project-store/projectRepositoryOpen.js.map +1 -0
- package/dist/project-store/projectRepositoryOwnerPath.d.ts +3 -0
- package/dist/project-store/projectRepositoryOwnerPath.d.ts.map +1 -0
- package/dist/project-store/projectRepositoryOwnerPath.js +25 -0
- package/dist/project-store/projectRepositoryOwnerPath.js.map +1 -0
- package/dist/project-store/projectRepositoryPath.d.ts +4 -0
- package/dist/project-store/projectRepositoryPath.d.ts.map +1 -0
- package/dist/project-store/projectRepositoryPath.js +21 -0
- package/dist/project-store/projectRepositoryPath.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemon.d.ts +19 -0
- package/dist/runtime/ProjectRegistryDaemon.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemon.js +2 -0
- package/dist/runtime/ProjectRegistryDaemon.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonBrowserAuth.d.ts +14 -0
- package/dist/runtime/ProjectRegistryDaemonBrowserAuth.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonBrowserAuth.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonBrowserAuth.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonConfig.d.ts +38 -0
- package/dist/runtime/ProjectRegistryDaemonConfig.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonConfig.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonConfig.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonFileStat.d.ts +7 -0
- package/dist/runtime/ProjectRegistryDaemonFileStat.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonFileStat.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonFileStat.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonFilesystem.d.ts +13 -0
- package/dist/runtime/ProjectRegistryDaemonFilesystem.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonFilesystem.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonFilesystem.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonHealth.d.ts +6 -0
- package/dist/runtime/ProjectRegistryDaemonHealth.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonHealth.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonHealth.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUser.d.ts +6 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUser.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUser.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUser.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUsersResolve.d.ts +4 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUsersResolve.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUsersResolve.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonMappedUsersResolve.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonOptions.d.ts +39 -0
- package/dist/runtime/ProjectRegistryDaemonOptions.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonOptions.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonOptions.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonPosix.d.ts +7 -0
- package/dist/runtime/ProjectRegistryDaemonPosix.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonPosix.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonPosix.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonReadiness.d.ts +11 -0
- package/dist/runtime/ProjectRegistryDaemonReadiness.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonReadiness.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonReadiness.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonRequestContext.d.ts +10 -0
- package/dist/runtime/ProjectRegistryDaemonRequestContext.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonRequestContext.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonRequestContext.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonRequestHandler.d.ts +3 -0
- package/dist/runtime/ProjectRegistryDaemonRequestHandler.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonRequestHandler.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonRequestHandler.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonServer.d.ts +6 -0
- package/dist/runtime/ProjectRegistryDaemonServer.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonServer.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonServer.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonServerFactory.d.ts +4 -0
- package/dist/runtime/ProjectRegistryDaemonServerFactory.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonServerFactory.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonServerFactory.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonServerOptions.d.ts +7 -0
- package/dist/runtime/ProjectRegistryDaemonServerOptions.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonServerOptions.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonServerOptions.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonSignals.d.ts +4 -0
- package/dist/runtime/ProjectRegistryDaemonSignals.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonSignals.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonSignals.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonSocketAccessResolve.d.ts +4 -0
- package/dist/runtime/ProjectRegistryDaemonSocketAccessResolve.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonSocketAccessResolve.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonSocketAccessResolve.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonSocketRefresh.d.ts +7 -0
- package/dist/runtime/ProjectRegistryDaemonSocketRefresh.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonSocketRefresh.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonSocketRefresh.js.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonState.d.ts +2 -0
- package/dist/runtime/ProjectRegistryDaemonState.d.ts.map +1 -0
- package/dist/runtime/ProjectRegistryDaemonState.js +2 -0
- package/dist/runtime/ProjectRegistryDaemonState.js.map +1 -0
- package/dist/runtime/clockNowResolve.d.ts +3 -0
- package/dist/runtime/clockNowResolve.d.ts.map +1 -0
- package/dist/runtime/clockNowResolve.js +18 -0
- package/dist/runtime/clockNowResolve.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonConfigFromEnv.d.ts +4 -0
- package/dist/runtime/projectRegistryDaemonConfigFromEnv.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonConfigFromEnv.js +158 -0
- package/dist/runtime/projectRegistryDaemonConfigFromEnv.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonConfigSchema.d.ts +57 -0
- package/dist/runtime/projectRegistryDaemonConfigSchema.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonConfigSchema.js +79 -0
- package/dist/runtime/projectRegistryDaemonConfigSchema.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonConfigValidate.d.ts +4 -0
- package/dist/runtime/projectRegistryDaemonConfigValidate.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonConfigValidate.js +59 -0
- package/dist/runtime/projectRegistryDaemonConfigValidate.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonCreate.d.ts +5 -0
- package/dist/runtime/projectRegistryDaemonCreate.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonCreate.js +1251 -0
- package/dist/runtime/projectRegistryDaemonCreate.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonFilesystemDefault.d.ts +3 -0
- package/dist/runtime/projectRegistryDaemonFilesystemDefault.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonFilesystemDefault.js +62 -0
- package/dist/runtime/projectRegistryDaemonFilesystemDefault.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonOpen.d.ts +5 -0
- package/dist/runtime/projectRegistryDaemonOpen.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonOpen.js +132 -0
- package/dist/runtime/projectRegistryDaemonOpen.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonPosixDefault.d.ts +3 -0
- package/dist/runtime/projectRegistryDaemonPosixDefault.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonPosixDefault.js +30 -0
- package/dist/runtime/projectRegistryDaemonPosixDefault.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonServerDefault.d.ts +3 -0
- package/dist/runtime/projectRegistryDaemonServerDefault.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonServerDefault.js +20 -0
- package/dist/runtime/projectRegistryDaemonServerDefault.js.map +1 -0
- package/dist/runtime/projectRegistryDaemonSignalsDefault.d.ts +3 -0
- package/dist/runtime/projectRegistryDaemonSignalsDefault.d.ts.map +1 -0
- package/dist/runtime/projectRegistryDaemonSignalsDefault.js +9 -0
- package/dist/runtime/projectRegistryDaemonSignalsDefault.js.map +1 -0
- package/dist/runtime/promiseBoundedRace.d.ts +6 -0
- package/dist/runtime/promiseBoundedRace.d.ts.map +1 -0
- package/dist/runtime/promiseBoundedRace.js +52 -0
- package/dist/runtime/promiseBoundedRace.js.map +1 -0
- package/dist/runtime/randomBytesResultResolve.d.ts +3 -0
- package/dist/runtime/randomBytesResultResolve.d.ts.map +1 -0
- package/dist/runtime/randomBytesResultResolve.js +25 -0
- package/dist/runtime/randomBytesResultResolve.js.map +1 -0
- package/dist/runtime/timeExpiryResolve.d.ts +3 -0
- package/dist/runtime/timeExpiryResolve.d.ts.map +1 -0
- package/dist/runtime/timeExpiryResolve.js +15 -0
- package/dist/runtime/timeExpiryResolve.js.map +1 -0
- package/dist/runtime/timeMillisecondsValidate.d.ts +2 -0
- package/dist/runtime/timeMillisecondsValidate.d.ts.map +1 -0
- package/dist/runtime/timeMillisecondsValidate.js +4 -0
- package/dist/runtime/timeMillisecondsValidate.js.map +1 -0
- package/dist/runtime/timeSecondsValidate.d.ts +2 -0
- package/dist/runtime/timeSecondsValidate.d.ts.map +1 -0
- package/dist/runtime/timeSecondsValidate.js +5 -0
- package/dist/runtime/timeSecondsValidate.js.map +1 -0
- package/dist/session/Clock.d.ts +2 -0
- package/dist/session/Clock.d.ts.map +1 -0
- package/dist/session/Clock.js +2 -0
- package/dist/session/Clock.js.map +1 -0
- package/dist/session/CsrfTokenStore.d.ts +7 -0
- package/dist/session/CsrfTokenStore.d.ts.map +1 -0
- package/dist/session/CsrfTokenStore.js +2 -0
- package/dist/session/CsrfTokenStore.js.map +1 -0
- package/dist/session/CsrfTokenStoreOptions.d.ts +9 -0
- package/dist/session/CsrfTokenStoreOptions.d.ts.map +1 -0
- package/dist/session/CsrfTokenStoreOptions.js +2 -0
- package/dist/session/CsrfTokenStoreOptions.js.map +1 -0
- package/dist/session/RandomBytes.d.ts +3 -0
- package/dist/session/RandomBytes.d.ts.map +1 -0
- package/dist/session/RandomBytes.js +2 -0
- package/dist/session/RandomBytes.js.map +1 -0
- package/dist/session/SessionActorResolveOptions.d.ts +15 -0
- package/dist/session/SessionActorResolveOptions.d.ts.map +1 -0
- package/dist/session/SessionActorResolveOptions.js +2 -0
- package/dist/session/SessionActorResolveOptions.js.map +1 -0
- package/dist/session/SessionCookieOptions.d.ts +5 -0
- package/dist/session/SessionCookieOptions.d.ts.map +1 -0
- package/dist/session/SessionCookieOptions.js +2 -0
- package/dist/session/SessionCookieOptions.js.map +1 -0
- package/dist/session/SessionCreateInput.d.ts +6 -0
- package/dist/session/SessionCreateInput.d.ts.map +1 -0
- package/dist/session/SessionCreateInput.js +2 -0
- package/dist/session/SessionCreateInput.js.map +1 -0
- package/dist/session/SessionLogoutOptions.d.ts +12 -0
- package/dist/session/SessionLogoutOptions.d.ts.map +1 -0
- package/dist/session/SessionLogoutOptions.js +2 -0
- package/dist/session/SessionLogoutOptions.js.map +1 -0
- package/dist/session/SessionRecord.d.ts +9 -0
- package/dist/session/SessionRecord.d.ts.map +1 -0
- package/dist/session/SessionRecord.js +2 -0
- package/dist/session/SessionRecord.js.map +1 -0
- package/dist/session/SessionStore.d.ts +11 -0
- package/dist/session/SessionStore.d.ts.map +1 -0
- package/dist/session/SessionStore.js +2 -0
- package/dist/session/SessionStore.js.map +1 -0
- package/dist/session/SessionStoreOptions.d.ts +11 -0
- package/dist/session/SessionStoreOptions.d.ts.map +1 -0
- package/dist/session/SessionStoreOptions.js +2 -0
- package/dist/session/SessionStoreOptions.js.map +1 -0
- package/dist/session/TokenReferenceStore.d.ts +10 -0
- package/dist/session/TokenReferenceStore.d.ts.map +1 -0
- package/dist/session/TokenReferenceStore.js +2 -0
- package/dist/session/TokenReferenceStore.js.map +1 -0
- package/dist/session/TokenReferenceStoreOptions.d.ts +8 -0
- package/dist/session/TokenReferenceStoreOptions.d.ts.map +1 -0
- package/dist/session/TokenReferenceStoreOptions.js +2 -0
- package/dist/session/TokenReferenceStoreOptions.js.map +1 -0
- package/dist/session/TokenReferenceTokens.d.ts +6 -0
- package/dist/session/TokenReferenceTokens.d.ts.map +1 -0
- package/dist/session/TokenReferenceTokens.js +2 -0
- package/dist/session/TokenReferenceTokens.js.map +1 -0
- package/dist/session/csrfTokenIssue.d.ts +4 -0
- package/dist/session/csrfTokenIssue.d.ts.map +1 -0
- package/dist/session/csrfTokenIssue.js +4 -0
- package/dist/session/csrfTokenIssue.js.map +1 -0
- package/dist/session/csrfTokenStoreCreate.d.ts +4 -0
- package/dist/session/csrfTokenStoreCreate.d.ts.map +1 -0
- package/dist/session/csrfTokenStoreCreate.js +179 -0
- package/dist/session/csrfTokenStoreCreate.js.map +1 -0
- package/dist/session/csrfTokenValidate.d.ts +4 -0
- package/dist/session/csrfTokenValidate.d.ts.map +1 -0
- package/dist/session/csrfTokenValidate.js +16 -0
- package/dist/session/csrfTokenValidate.js.map +1 -0
- package/dist/session/randomBytesGenerate.d.ts +3 -0
- package/dist/session/randomBytesGenerate.d.ts.map +1 -0
- package/dist/session/randomBytesGenerate.js +16 -0
- package/dist/session/randomBytesGenerate.js.map +1 -0
- package/dist/session/sessionActorResolve.d.ts +5 -0
- package/dist/session/sessionActorResolve.d.ts.map +1 -0
- package/dist/session/sessionActorResolve.js +98 -0
- package/dist/session/sessionActorResolve.js.map +1 -0
- package/dist/session/sessionCookieClear.d.ts +4 -0
- package/dist/session/sessionCookieClear.d.ts.map +1 -0
- package/dist/session/sessionCookieClear.js +20 -0
- package/dist/session/sessionCookieClear.js.map +1 -0
- package/dist/session/sessionCookieParse.d.ts +4 -0
- package/dist/session/sessionCookieParse.d.ts.map +1 -0
- package/dist/session/sessionCookieParse.js +42 -0
- package/dist/session/sessionCookieParse.js.map +1 -0
- package/dist/session/sessionCookieSerialize.d.ts +4 -0
- package/dist/session/sessionCookieSerialize.d.ts.map +1 -0
- package/dist/session/sessionCookieSerialize.js +28 -0
- package/dist/session/sessionCookieSerialize.js.map +1 -0
- package/dist/session/sessionLogout.d.ts +8 -0
- package/dist/session/sessionLogout.d.ts.map +1 -0
- package/dist/session/sessionLogout.js +74 -0
- package/dist/session/sessionLogout.js.map +1 -0
- package/dist/session/sessionRecordValidate.d.ts +4 -0
- package/dist/session/sessionRecordValidate.d.ts.map +1 -0
- package/dist/session/sessionRecordValidate.js +44 -0
- package/dist/session/sessionRecordValidate.js.map +1 -0
- package/dist/session/sessionRequestResolve.d.ts +9 -0
- package/dist/session/sessionRequestResolve.d.ts.map +1 -0
- package/dist/session/sessionRequestResolve.js +23 -0
- package/dist/session/sessionRequestResolve.js.map +1 -0
- package/dist/session/sessionStoreCreate.d.ts +4 -0
- package/dist/session/sessionStoreCreate.d.ts.map +1 -0
- package/dist/session/sessionStoreCreate.js +220 -0
- package/dist/session/sessionStoreCreate.js.map +1 -0
- package/dist/session/tokenReferenceIdValidate.d.ts +3 -0
- package/dist/session/tokenReferenceIdValidate.d.ts.map +1 -0
- package/dist/session/tokenReferenceIdValidate.js +10 -0
- package/dist/session/tokenReferenceIdValidate.js.map +1 -0
- package/dist/session/tokenReferenceStoreCreate.d.ts +4 -0
- package/dist/session/tokenReferenceStoreCreate.d.ts.map +1 -0
- package/dist/session/tokenReferenceStoreCreate.js +96 -0
- package/dist/session/tokenReferenceStoreCreate.js.map +1 -0
- package/dist/session/tokenReferenceTokensValidate.d.ts +4 -0
- package/dist/session/tokenReferenceTokensValidate.d.ts.map +1 -0
- package/dist/session/tokenReferenceTokensValidate.js +26 -0
- package/dist/session/tokenReferenceTokensValidate.js.map +1 -0
- package/dist/ui/assets/index-C5h9COjm.css +1 -0
- package/dist/ui/assets/index-CwUhaCYM.js +1 -0
- package/dist/ui/index.html +13 -0
- package/dist/web-server/MutationSecurityOptions.d.ts +11 -0
- package/dist/web-server/MutationSecurityOptions.d.ts.map +1 -0
- package/dist/web-server/MutationSecurityOptions.js +2 -0
- package/dist/web-server/MutationSecurityOptions.js.map +1 -0
- package/dist/web-server/mutationOriginValidate.d.ts +3 -0
- package/dist/web-server/mutationOriginValidate.d.ts.map +1 -0
- package/dist/web-server/mutationOriginValidate.js +30 -0
- package/dist/web-server/mutationOriginValidate.js.map +1 -0
- package/dist/web-server/mutationSecurityValidate.d.ts +4 -0
- package/dist/web-server/mutationSecurityValidate.d.ts.map +1 -0
- package/dist/web-server/mutationSecurityValidate.js +27 -0
- package/dist/web-server/mutationSecurityValidate.js.map +1 -0
- package/dist/zitadel/LoginTransaction.d.ts +9 -0
- package/dist/zitadel/LoginTransaction.d.ts.map +1 -0
- package/dist/zitadel/LoginTransaction.js +2 -0
- package/dist/zitadel/LoginTransaction.js.map +1 -0
- package/dist/zitadel/LoginTransactionStore.d.ts +7 -0
- package/dist/zitadel/LoginTransactionStore.d.ts.map +1 -0
- package/dist/zitadel/LoginTransactionStore.js +2 -0
- package/dist/zitadel/LoginTransactionStore.js.map +1 -0
- package/dist/zitadel/LoginTransactionStoreOptions.d.ts +6 -0
- package/dist/zitadel/LoginTransactionStoreOptions.d.ts.map +1 -0
- package/dist/zitadel/LoginTransactionStoreOptions.js +2 -0
- package/dist/zitadel/LoginTransactionStoreOptions.js.map +1 -0
- package/dist/zitadel/ZitadelCallbackOptions.d.ts +28 -0
- package/dist/zitadel/ZitadelCallbackOptions.d.ts.map +1 -0
- package/dist/zitadel/ZitadelCallbackOptions.js +2 -0
- package/dist/zitadel/ZitadelCallbackOptions.js.map +1 -0
- package/dist/zitadel/ZitadelCallbackResult.d.ts +8 -0
- package/dist/zitadel/ZitadelCallbackResult.d.ts.map +1 -0
- package/dist/zitadel/ZitadelCallbackResult.js +2 -0
- package/dist/zitadel/ZitadelCallbackResult.js.map +1 -0
- package/dist/zitadel/ZitadelDiscoveryDocument.d.ts +7 -0
- package/dist/zitadel/ZitadelDiscoveryDocument.d.ts.map +1 -0
- package/dist/zitadel/ZitadelDiscoveryDocument.js +2 -0
- package/dist/zitadel/ZitadelDiscoveryDocument.js.map +1 -0
- package/dist/zitadel/ZitadelHttp.d.ts +2 -0
- package/dist/zitadel/ZitadelHttp.d.ts.map +1 -0
- package/dist/zitadel/ZitadelHttp.js +2 -0
- package/dist/zitadel/ZitadelHttp.js.map +1 -0
- package/dist/zitadel/ZitadelHttpOptions.d.ts +6 -0
- package/dist/zitadel/ZitadelHttpOptions.d.ts.map +1 -0
- package/dist/zitadel/ZitadelHttpOptions.js +2 -0
- package/dist/zitadel/ZitadelHttpOptions.js.map +1 -0
- package/dist/zitadel/ZitadelIdentityClaims.d.ts +6 -0
- package/dist/zitadel/ZitadelIdentityClaims.d.ts.map +1 -0
- package/dist/zitadel/ZitadelIdentityClaims.js +2 -0
- package/dist/zitadel/ZitadelIdentityClaims.js.map +1 -0
- package/dist/zitadel/ZitadelIdentityDirectoryOptions.d.ts +11 -0
- package/dist/zitadel/ZitadelIdentityDirectoryOptions.d.ts.map +1 -0
- package/dist/zitadel/ZitadelIdentityDirectoryOptions.js +2 -0
- package/dist/zitadel/ZitadelIdentityDirectoryOptions.js.map +1 -0
- package/dist/zitadel/ZitadelJwk.d.ts +12 -0
- package/dist/zitadel/ZitadelJwk.d.ts.map +1 -0
- package/dist/zitadel/ZitadelJwk.js +2 -0
- package/dist/zitadel/ZitadelJwk.js.map +1 -0
- package/dist/zitadel/ZitadelJwks.d.ts +5 -0
- package/dist/zitadel/ZitadelJwks.d.ts.map +1 -0
- package/dist/zitadel/ZitadelJwks.js +2 -0
- package/dist/zitadel/ZitadelJwks.js.map +1 -0
- package/dist/zitadel/ZitadelLoginStartOptions.d.ts +17 -0
- package/dist/zitadel/ZitadelLoginStartOptions.d.ts.map +1 -0
- package/dist/zitadel/ZitadelLoginStartOptions.js +2 -0
- package/dist/zitadel/ZitadelLoginStartOptions.js.map +1 -0
- package/dist/zitadel/ZitadelLoginStartResult.d.ts +6 -0
- package/dist/zitadel/ZitadelLoginStartResult.d.ts.map +1 -0
- package/dist/zitadel/ZitadelLoginStartResult.js +2 -0
- package/dist/zitadel/ZitadelLoginStartResult.js.map +1 -0
- package/dist/zitadel/ZitadelOidcConfig.d.ts +10 -0
- package/dist/zitadel/ZitadelOidcConfig.d.ts.map +1 -0
- package/dist/zitadel/ZitadelOidcConfig.js +2 -0
- package/dist/zitadel/ZitadelOidcConfig.js.map +1 -0
- package/dist/zitadel/ZitadelPreAuthCookieOptions.d.ts +4 -0
- package/dist/zitadel/ZitadelPreAuthCookieOptions.d.ts.map +1 -0
- package/dist/zitadel/ZitadelPreAuthCookieOptions.js +2 -0
- package/dist/zitadel/ZitadelPreAuthCookieOptions.js.map +1 -0
- package/dist/zitadel/ZitadelTokenExchangeOptions.d.ts +17 -0
- package/dist/zitadel/ZitadelTokenExchangeOptions.d.ts.map +1 -0
- package/dist/zitadel/ZitadelTokenExchangeOptions.js +2 -0
- package/dist/zitadel/ZitadelTokenExchangeOptions.js.map +1 -0
- package/dist/zitadel/ZitadelTokens.d.ts +7 -0
- package/dist/zitadel/ZitadelTokens.d.ts.map +1 -0
- package/dist/zitadel/ZitadelTokens.js +2 -0
- package/dist/zitadel/ZitadelTokens.js.map +1 -0
- package/dist/zitadel/zitadelCallbackHandle.d.ts +5 -0
- package/dist/zitadel/zitadelCallbackHandle.d.ts.map +1 -0
- package/dist/zitadel/zitadelCallbackHandle.js +255 -0
- package/dist/zitadel/zitadelCallbackHandle.js.map +1 -0
- package/dist/zitadel/zitadelConfigValidate.d.ts +4 -0
- package/dist/zitadel/zitadelConfigValidate.d.ts.map +1 -0
- package/dist/zitadel/zitadelConfigValidate.js +88 -0
- package/dist/zitadel/zitadelConfigValidate.js.map +1 -0
- package/dist/zitadel/zitadelDiscoveryFetch.d.ts +7 -0
- package/dist/zitadel/zitadelDiscoveryFetch.d.ts.map +1 -0
- package/dist/zitadel/zitadelDiscoveryFetch.js +55 -0
- package/dist/zitadel/zitadelDiscoveryFetch.js.map +1 -0
- package/dist/zitadel/zitadelDiscoveryValidate.d.ts +4 -0
- package/dist/zitadel/zitadelDiscoveryValidate.d.ts.map +1 -0
- package/dist/zitadel/zitadelDiscoveryValidate.js +43 -0
- package/dist/zitadel/zitadelDiscoveryValidate.js.map +1 -0
- package/dist/zitadel/zitadelHttpJsonFetch.d.ts +8 -0
- package/dist/zitadel/zitadelHttpJsonFetch.d.ts.map +1 -0
- package/dist/zitadel/zitadelHttpJsonFetch.js +118 -0
- package/dist/zitadel/zitadelHttpJsonFetch.js.map +1 -0
- package/dist/zitadel/zitadelIdTokenValidate.d.ts +7 -0
- package/dist/zitadel/zitadelIdTokenValidate.d.ts.map +1 -0
- package/dist/zitadel/zitadelIdTokenValidate.js +170 -0
- package/dist/zitadel/zitadelIdTokenValidate.js.map +1 -0
- package/dist/zitadel/zitadelIdentityDirectoryCreate.d.ts +5 -0
- package/dist/zitadel/zitadelIdentityDirectoryCreate.d.ts.map +1 -0
- package/dist/zitadel/zitadelIdentityDirectoryCreate.js +268 -0
- package/dist/zitadel/zitadelIdentityDirectoryCreate.js.map +1 -0
- package/dist/zitadel/zitadelJwksFetch.d.ts +6 -0
- package/dist/zitadel/zitadelJwksFetch.d.ts.map +1 -0
- package/dist/zitadel/zitadelJwksFetch.js +36 -0
- package/dist/zitadel/zitadelJwksFetch.js.map +1 -0
- package/dist/zitadel/zitadelJwksValidate.d.ts +4 -0
- package/dist/zitadel/zitadelJwksValidate.d.ts.map +1 -0
- package/dist/zitadel/zitadelJwksValidate.js +69 -0
- package/dist/zitadel/zitadelJwksValidate.js.map +1 -0
- package/dist/zitadel/zitadelLoginStart.d.ts +5 -0
- package/dist/zitadel/zitadelLoginStart.d.ts.map +1 -0
- package/dist/zitadel/zitadelLoginStart.js +102 -0
- package/dist/zitadel/zitadelLoginStart.js.map +1 -0
- package/dist/zitadel/zitadelLoginTransactionStoreCreate.d.ts +4 -0
- package/dist/zitadel/zitadelLoginTransactionStoreCreate.d.ts.map +1 -0
- package/dist/zitadel/zitadelLoginTransactionStoreCreate.js +82 -0
- package/dist/zitadel/zitadelLoginTransactionStoreCreate.js.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieClear.d.ts +3 -0
- package/dist/zitadel/zitadelPreAuthCookieClear.d.ts.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieClear.js +6 -0
- package/dist/zitadel/zitadelPreAuthCookieClear.js.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieHash.d.ts +3 -0
- package/dist/zitadel/zitadelPreAuthCookieHash.d.ts.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieHash.js +20 -0
- package/dist/zitadel/zitadelPreAuthCookieHash.js.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieParse.d.ts +3 -0
- package/dist/zitadel/zitadelPreAuthCookieParse.d.ts.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieParse.js +33 -0
- package/dist/zitadel/zitadelPreAuthCookieParse.js.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieSerialize.d.ts +4 -0
- package/dist/zitadel/zitadelPreAuthCookieSerialize.d.ts.map +1 -0
- package/dist/zitadel/zitadelPreAuthCookieSerialize.js +20 -0
- package/dist/zitadel/zitadelPreAuthCookieSerialize.js.map +1 -0
- package/dist/zitadel/zitadelTokenExchange.d.ts +5 -0
- package/dist/zitadel/zitadelTokenExchange.d.ts.map +1 -0
- package/dist/zitadel/zitadelTokenExchange.js +92 -0
- package/dist/zitadel/zitadelTokenExchange.js.map +1 -0
- package/package.json +137 -0
|
@@ -0,0 +1,1365 @@
|
|
|
1
|
+
import { dlopen, FFIType } from "bun:ffi";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { lstat, mkdir, open, opendir, rename, rmdir, unlink } from "node:fs/promises";
|
|
5
|
+
import { join, posix } from "node:path";
|
|
6
|
+
import * as a from "valibot";
|
|
7
|
+
import { createResult, createResultError } from "#result";
|
|
8
|
+
import { projectAccessLogCaddyRetention } from "./projectAccessLogCaddyRetention.js";
|
|
9
|
+
import { projectAccessLogOpenat2 } from "./projectAccessLogOpenat2.js";
|
|
10
|
+
import { projectAccessLogRetentionMaximumActiveProjectIds } from "./projectAccessLogRetentionMaximumActiveProjectIds.js";
|
|
11
|
+
import { projectAccessLogRootSchema } from "./projectAccessLogRootSchema.js";
|
|
12
|
+
const metadataName = ".project-registry-retention.json";
|
|
13
|
+
const metadataTemporaryNamePrefix = `${metadataName}.tmp-`;
|
|
14
|
+
const metadataTemporaryNamePattern = /^\.project-registry-retention\.json\.tmp-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
15
|
+
const quarantineDirectoryName = "quarantine";
|
|
16
|
+
const metadataMaximumBytes = 4 * 1024;
|
|
17
|
+
const metadataTemporaryCreateAttempts = 8;
|
|
18
|
+
const metadataTemporaryMaximumFiles = 8;
|
|
19
|
+
const maximumProjectEntries = 1_024;
|
|
20
|
+
const maximumWorkEntries = 4_096;
|
|
21
|
+
const retentionWindowMs = projectAccessLogCaddyRetention.rollKeepDays * 24 * 60 * 60 * 1_000;
|
|
22
|
+
const quarantineGraceMs = 24 * 60 * 60 * 1_000;
|
|
23
|
+
const archiveNamePattern = /^access-[A-Za-z0-9_.-]+\.jsonl(?:\.gz)?$/;
|
|
24
|
+
const projectIdPattern = /^[a-f0-9]{64}$/;
|
|
25
|
+
const noFollowFlag = constants.O_NOFOLLOW ?? 0;
|
|
26
|
+
const directoryFlag = constants.O_DIRECTORY ?? 0;
|
|
27
|
+
const nonBlockingFlag = constants.O_NONBLOCK ?? 0;
|
|
28
|
+
const descriptorDirectoryFlags = constants.O_RDONLY | directoryFlag | noFollowFlag;
|
|
29
|
+
const descriptorFileFlags = constants.O_RDONLY | noFollowFlag | nonBlockingFlag;
|
|
30
|
+
const descriptorTraversalAvailable = noFollowFlag !== 0 && directoryFlag !== 0;
|
|
31
|
+
const renameNoReplaceFlag = 1;
|
|
32
|
+
const retentionFileSystemDefault = {
|
|
33
|
+
syncDirectory: async (directory) => {
|
|
34
|
+
await directory.sync();
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
const renameAt2 = (() => {
|
|
38
|
+
if (process.platform !== "linux")
|
|
39
|
+
return undefined;
|
|
40
|
+
try {
|
|
41
|
+
return dlopen("libc.so.6", {
|
|
42
|
+
renameat2: {
|
|
43
|
+
args: [FFIType.i32, FFIType.cstring, FFIType.i32, FFIType.cstring, FFIType.u32],
|
|
44
|
+
returns: FFIType.i32,
|
|
45
|
+
},
|
|
46
|
+
}).symbols.renameat2;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
})();
|
|
52
|
+
let reconciliationFlight = Promise.resolve();
|
|
53
|
+
function retentionError(message, errorData) {
|
|
54
|
+
return createResultError("projectAccessLogRetentionReconcile", message, errorData);
|
|
55
|
+
}
|
|
56
|
+
function errorCode(error) {
|
|
57
|
+
if (typeof error !== "object" || error === null || !("code" in error))
|
|
58
|
+
return undefined;
|
|
59
|
+
const code = error.code;
|
|
60
|
+
return typeof code === "string" ? code : undefined;
|
|
61
|
+
}
|
|
62
|
+
function descriptorChildPath(directory, name) {
|
|
63
|
+
return `/proc/self/fd/${directory.fd}/${name}`;
|
|
64
|
+
}
|
|
65
|
+
async function fileHandleClose(handle) {
|
|
66
|
+
if (handle === undefined)
|
|
67
|
+
return;
|
|
68
|
+
try {
|
|
69
|
+
await handle.close();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// The reconciliation result is already determined; close failures must not escape.
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function statSameObject(left, right) {
|
|
76
|
+
return left.dev === right.dev && left.ino === right.ino;
|
|
77
|
+
}
|
|
78
|
+
function directoryRenameNoReplace(source, sourceName, destination, destinationName) {
|
|
79
|
+
// fs.rename replaces an existing empty directory. renameat2 with RENAME_NOREPLACE keeps a collision intact.
|
|
80
|
+
if (renameAt2 === undefined)
|
|
81
|
+
return false;
|
|
82
|
+
try {
|
|
83
|
+
return renameAt2(source.fd, sourceName, destination.fd, destinationName, renameNoReplaceFlag) === 0;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function retentionOptionsNormalize(options) {
|
|
90
|
+
const op = "projectAccessLogRetentionReconcile";
|
|
91
|
+
try {
|
|
92
|
+
if (typeof options !== "object" || options === null || Array.isArray(options)) {
|
|
93
|
+
return createResultError(op, "retention reconciliation options are invalid");
|
|
94
|
+
}
|
|
95
|
+
const input = options;
|
|
96
|
+
if (typeof input.root !== "string")
|
|
97
|
+
return createResultError(op, "retention reconciliation root is invalid");
|
|
98
|
+
const rootR = a.safeParse(projectAccessLogRootSchema, input.root);
|
|
99
|
+
if (!rootR.success)
|
|
100
|
+
return createResultError(op, a.summarize(rootR.issues));
|
|
101
|
+
if (!Array.isArray(input.activeProjectIds)) {
|
|
102
|
+
return createResultError(op, "retention reconciliation active project IDs are invalid");
|
|
103
|
+
}
|
|
104
|
+
if (input.activeProjectIds.length > projectAccessLogRetentionMaximumActiveProjectIds) {
|
|
105
|
+
return createResultError(op, `retention reconciliation active project ID limit exceeded (maximum ${projectAccessLogRetentionMaximumActiveProjectIds})`);
|
|
106
|
+
}
|
|
107
|
+
const activeProjectIds = [];
|
|
108
|
+
for (const id of input.activeProjectIds) {
|
|
109
|
+
if (typeof id !== "string" || !projectIdPattern.test(id)) {
|
|
110
|
+
return createResultError(op, "retention reconciliation active project IDs are invalid");
|
|
111
|
+
}
|
|
112
|
+
if (activeProjectIds.includes(id)) {
|
|
113
|
+
return createResultError(op, "retention reconciliation active project IDs must be unique");
|
|
114
|
+
}
|
|
115
|
+
activeProjectIds.push(id);
|
|
116
|
+
}
|
|
117
|
+
const now = input.now ?? Date.now();
|
|
118
|
+
if (typeof now !== "number" || !Number.isSafeInteger(now) || now < 0) {
|
|
119
|
+
return createResultError(op, "retention reconciliation time is invalid");
|
|
120
|
+
}
|
|
121
|
+
if (input.stillCurrent !== undefined && typeof input.stillCurrent !== "function") {
|
|
122
|
+
return createResultError(op, "retention reconciliation current-state guard is invalid");
|
|
123
|
+
}
|
|
124
|
+
if (input.filesystem !== undefined &&
|
|
125
|
+
(typeof input.filesystem !== "object" ||
|
|
126
|
+
input.filesystem === null ||
|
|
127
|
+
Array.isArray(input.filesystem) ||
|
|
128
|
+
typeof input.filesystem.syncDirectory !== "function")) {
|
|
129
|
+
return createResultError(op, "retention reconciliation filesystem is invalid");
|
|
130
|
+
}
|
|
131
|
+
const stillCurrent = typeof input.stillCurrent === "function" ? input.stillCurrent : undefined;
|
|
132
|
+
const filesystem = input.filesystem;
|
|
133
|
+
return createResult({
|
|
134
|
+
root: rootR.output,
|
|
135
|
+
activeProjectIds,
|
|
136
|
+
now,
|
|
137
|
+
stillCurrent: stillCurrent ?? (() => true),
|
|
138
|
+
filesystem: filesystem ?? retentionFileSystemDefault,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return createResultError(op, "retention reconciliation options are invalid");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async function directoryOpenRelative(parent, name, path, rootAnchor = false) {
|
|
146
|
+
if (!descriptorTraversalAvailable)
|
|
147
|
+
return retentionError("descriptor-relative access is unavailable", path);
|
|
148
|
+
return projectAccessLogOpenat2({
|
|
149
|
+
directoryFd: parent.fd,
|
|
150
|
+
name,
|
|
151
|
+
flags: descriptorDirectoryFlags,
|
|
152
|
+
path,
|
|
153
|
+
rootAnchor,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async function rootDirectoryOpen(root) {
|
|
157
|
+
if (!descriptorTraversalAvailable)
|
|
158
|
+
return retentionError("descriptor-relative access is unavailable", root);
|
|
159
|
+
let current;
|
|
160
|
+
let retained = false;
|
|
161
|
+
let currentPath = "/";
|
|
162
|
+
try {
|
|
163
|
+
current = await open("/", descriptorDirectoryFlags);
|
|
164
|
+
const parts = root.split("/").filter((value) => value.length > 0);
|
|
165
|
+
if (parts.length === 0) {
|
|
166
|
+
const rootR = await directoryOpenRelative(current, ".", root, true);
|
|
167
|
+
await fileHandleClose(current);
|
|
168
|
+
current = undefined;
|
|
169
|
+
if (!rootR.success)
|
|
170
|
+
return rootR;
|
|
171
|
+
if (rootR.data === undefined)
|
|
172
|
+
return createResult(undefined);
|
|
173
|
+
current = rootR.data;
|
|
174
|
+
}
|
|
175
|
+
for (const [index, part] of parts.entries()) {
|
|
176
|
+
// Mounts before the configured root are allowed so roots on a separate filesystem still work. The root itself
|
|
177
|
+
// and every descendant are opened with RESOLVE_NO_XDEV.
|
|
178
|
+
const nextR = await directoryOpenRelative(current, part, join(currentPath, part), index < parts.length - 1);
|
|
179
|
+
await fileHandleClose(current);
|
|
180
|
+
current = undefined;
|
|
181
|
+
if (!nextR.success)
|
|
182
|
+
return nextR;
|
|
183
|
+
if (nextR.data === undefined)
|
|
184
|
+
return createResult(undefined);
|
|
185
|
+
current = nextR.data;
|
|
186
|
+
currentPath = join(currentPath, part);
|
|
187
|
+
}
|
|
188
|
+
retained = true;
|
|
189
|
+
return createResult(current);
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
if (errorCode(error) === "ENOENT")
|
|
193
|
+
return createResult(undefined);
|
|
194
|
+
return retentionError("retention root could not be opened", root);
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
if (!retained)
|
|
198
|
+
await fileHandleClose(current);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async function directoryEntriesRead(directory, path, budget, maximumEntries = maximumProjectEntries) {
|
|
202
|
+
let entriesDirectory;
|
|
203
|
+
try {
|
|
204
|
+
entriesDirectory = await opendir(descriptorChildPath(directory, "."));
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return retentionError("retention directory could not be read", path);
|
|
208
|
+
}
|
|
209
|
+
const names = [];
|
|
210
|
+
try {
|
|
211
|
+
while (true) {
|
|
212
|
+
const entry = await entriesDirectory.read();
|
|
213
|
+
if (entry === null)
|
|
214
|
+
break;
|
|
215
|
+
names.push(entry.name);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
return retentionError("retention directory could not be read", path);
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
try {
|
|
223
|
+
await entriesDirectory.close();
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// The read result is already determined; a close failure must not leak an exception.
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const entries = [];
|
|
230
|
+
for (const name of names) {
|
|
231
|
+
budget.entries += 1;
|
|
232
|
+
if (budget.entries > maximumWorkEntries || entries.length >= maximumEntries) {
|
|
233
|
+
return retentionError("retention directory entry limit exceeded", path);
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
entries.push({ name, stat: await lstat(descriptorChildPath(directory, name)) });
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return retentionError("retention directory changed while being inspected", path);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
entries.sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
|
|
243
|
+
return createResult(entries);
|
|
244
|
+
}
|
|
245
|
+
function metadataParse(value) {
|
|
246
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
247
|
+
return undefined;
|
|
248
|
+
if (Object.getPrototypeOf(value) !== Object.prototype)
|
|
249
|
+
return undefined;
|
|
250
|
+
const version = value.version;
|
|
251
|
+
const state = value.state;
|
|
252
|
+
if (version !== 1 || (state !== "active" && state !== "inactive" && state !== "quarantined"))
|
|
253
|
+
return undefined;
|
|
254
|
+
const keys = Object.keys(value);
|
|
255
|
+
if (state === "active") {
|
|
256
|
+
if (keys.length !== 2 || !keys.includes("version") || !keys.includes("state"))
|
|
257
|
+
return undefined;
|
|
258
|
+
return { version: 1, state: "active" };
|
|
259
|
+
}
|
|
260
|
+
if (state === "quarantined") {
|
|
261
|
+
if (keys.length !== 4 ||
|
|
262
|
+
!keys.includes("version") ||
|
|
263
|
+
!keys.includes("state") ||
|
|
264
|
+
!keys.includes("inactiveAt") ||
|
|
265
|
+
!keys.includes("quarantinedAt")) {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
const inactiveAt = value.inactiveAt;
|
|
269
|
+
const quarantinedAt = value.quarantinedAt;
|
|
270
|
+
if (typeof inactiveAt !== "number" ||
|
|
271
|
+
!Number.isSafeInteger(inactiveAt) ||
|
|
272
|
+
inactiveAt < 0 ||
|
|
273
|
+
typeof quarantinedAt !== "number" ||
|
|
274
|
+
!Number.isSafeInteger(quarantinedAt) ||
|
|
275
|
+
quarantinedAt < 0 ||
|
|
276
|
+
quarantinedAt < inactiveAt) {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
return { version: 1, state: "quarantined", inactiveAt, quarantinedAt };
|
|
280
|
+
}
|
|
281
|
+
if (keys.length !== 3 || !keys.includes("version") || !keys.includes("state") || !keys.includes("inactiveAt")) {
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
284
|
+
const inactiveAt = value.inactiveAt;
|
|
285
|
+
if (typeof inactiveAt !== "number" || !Number.isSafeInteger(inactiveAt) || inactiveAt < 0)
|
|
286
|
+
return undefined;
|
|
287
|
+
return { version: 1, state: "inactive", inactiveAt };
|
|
288
|
+
}
|
|
289
|
+
function quarantineLogFileKnown(name) {
|
|
290
|
+
return name === "access.jsonl" || archiveNamePattern.test(name);
|
|
291
|
+
}
|
|
292
|
+
function quarantineGraceExpired(quarantinedAt, now) {
|
|
293
|
+
return quarantinedAt <= now && now - quarantinedAt >= quarantineGraceMs;
|
|
294
|
+
}
|
|
295
|
+
async function metadataRead(directory) {
|
|
296
|
+
const path = descriptorChildPath(directory, metadataName);
|
|
297
|
+
let listedStat;
|
|
298
|
+
try {
|
|
299
|
+
listedStat = await lstat(path);
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
if (errorCode(error) === "ENOENT")
|
|
303
|
+
return { kind: "missing" };
|
|
304
|
+
return { kind: "unavailable" };
|
|
305
|
+
}
|
|
306
|
+
if (listedStat.isSymbolicLink() || !listedStat.isFile() || listedStat.size > metadataMaximumBytes) {
|
|
307
|
+
return { kind: "malformed" };
|
|
308
|
+
}
|
|
309
|
+
let handle;
|
|
310
|
+
try {
|
|
311
|
+
const openR = await projectAccessLogOpenat2({
|
|
312
|
+
directoryFd: directory.fd,
|
|
313
|
+
name: metadataName,
|
|
314
|
+
flags: descriptorFileFlags,
|
|
315
|
+
path,
|
|
316
|
+
});
|
|
317
|
+
if (!openR.success)
|
|
318
|
+
return { kind: openR.errorMessage.includes("symbolic link") ? "malformed" : "unavailable" };
|
|
319
|
+
if (openR.data === undefined)
|
|
320
|
+
return { kind: "unavailable" };
|
|
321
|
+
handle = openR.data;
|
|
322
|
+
const openedStat = await handle.stat();
|
|
323
|
+
if (!openedStat.isFile() || !statSameObject(listedStat, openedStat) || openedStat.size > metadataMaximumBytes) {
|
|
324
|
+
return { kind: "malformed" };
|
|
325
|
+
}
|
|
326
|
+
const data = Buffer.alloc(metadataMaximumBytes + 1);
|
|
327
|
+
const readR = await handle.read(data, 0, data.length, 0);
|
|
328
|
+
if (readR.bytesRead !== openedStat.size || readR.bytesRead > metadataMaximumBytes)
|
|
329
|
+
return { kind: "malformed" };
|
|
330
|
+
let text;
|
|
331
|
+
try {
|
|
332
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(data.subarray(0, readR.bytesRead));
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
return { kind: "malformed" };
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
const parsed = metadataParse(JSON.parse(text));
|
|
339
|
+
return parsed === undefined ? { kind: "malformed" } : { kind: "valid", data: parsed };
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return { kind: "malformed" };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
return { kind: "unavailable" };
|
|
347
|
+
}
|
|
348
|
+
finally {
|
|
349
|
+
await fileHandleClose(handle);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async function metadataTemporaryFileCleanup(directory, name, expectedStat) {
|
|
353
|
+
if (name === undefined)
|
|
354
|
+
return true;
|
|
355
|
+
if (expectedStat === undefined)
|
|
356
|
+
return false;
|
|
357
|
+
const path = descriptorChildPath(directory, name);
|
|
358
|
+
let handle;
|
|
359
|
+
try {
|
|
360
|
+
const openR = await projectAccessLogOpenat2({
|
|
361
|
+
directoryFd: directory.fd,
|
|
362
|
+
name,
|
|
363
|
+
flags: descriptorFileFlags,
|
|
364
|
+
path,
|
|
365
|
+
});
|
|
366
|
+
if (!openR.success)
|
|
367
|
+
return false;
|
|
368
|
+
if (openR.data === undefined) {
|
|
369
|
+
try {
|
|
370
|
+
await lstat(path);
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
return errorCode(error) === "ENOENT";
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
handle = openR.data;
|
|
378
|
+
const currentStat = await handle.stat();
|
|
379
|
+
if (!currentStat.isFile() || !statSameObject(currentStat, expectedStat))
|
|
380
|
+
return false;
|
|
381
|
+
await fileHandleClose(handle);
|
|
382
|
+
handle = undefined;
|
|
383
|
+
const listedStat = await lstat(path);
|
|
384
|
+
if (listedStat.isSymbolicLink() || !listedStat.isFile() || !statSameObject(listedStat, expectedStat))
|
|
385
|
+
return false;
|
|
386
|
+
try {
|
|
387
|
+
await unlink(path);
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
return errorCode(error) === "ENOENT";
|
|
391
|
+
}
|
|
392
|
+
try {
|
|
393
|
+
await lstat(path);
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
if (errorCode(error) !== "ENOENT")
|
|
398
|
+
return false;
|
|
399
|
+
try {
|
|
400
|
+
await directory.sync();
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
return errorCode(error) === "ENOENT";
|
|
410
|
+
}
|
|
411
|
+
finally {
|
|
412
|
+
await fileHandleClose(handle);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
function metadataTemporaryFileNameValid(name) {
|
|
416
|
+
return metadataTemporaryNamePattern.test(name);
|
|
417
|
+
}
|
|
418
|
+
function metadataTemporaryFileOwned(stat, directoryDevice) {
|
|
419
|
+
if (!stat.isFile() ||
|
|
420
|
+
stat.isSymbolicLink() ||
|
|
421
|
+
stat.dev !== directoryDevice ||
|
|
422
|
+
stat.nlink !== 1 ||
|
|
423
|
+
stat.size > metadataMaximumBytes) {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
if ((stat.mode & 0o7777) !== 0o600)
|
|
427
|
+
return false;
|
|
428
|
+
if (typeof process.getuid === "function" && stat.uid !== process.getuid())
|
|
429
|
+
return false;
|
|
430
|
+
if (typeof process.getgid === "function" && stat.gid !== process.getgid())
|
|
431
|
+
return false;
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
function metadataTemporaryTextPrefixValid(text) {
|
|
435
|
+
const active = '{"version":1,"state":"active"}';
|
|
436
|
+
const inactive = '{"version":1,"state":"inactive","inactiveAt":';
|
|
437
|
+
const quarantined = '{"version":1,"state":"quarantined","inactiveAt":';
|
|
438
|
+
if (active.startsWith(text))
|
|
439
|
+
return true;
|
|
440
|
+
if (text === "")
|
|
441
|
+
return true;
|
|
442
|
+
for (const prefix of [inactive, quarantined]) {
|
|
443
|
+
if (text === prefix.slice(0, text.length) && text.length < prefix.length)
|
|
444
|
+
return true;
|
|
445
|
+
if (!text.startsWith(prefix))
|
|
446
|
+
continue;
|
|
447
|
+
const remainder = text.slice(prefix.length);
|
|
448
|
+
if (/^\d*$/.test(remainder))
|
|
449
|
+
return true;
|
|
450
|
+
if (prefix !== quarantined)
|
|
451
|
+
continue;
|
|
452
|
+
const quarantineMarker = ',"quarantinedAt":';
|
|
453
|
+
if (quarantineMarker.startsWith(remainder))
|
|
454
|
+
return true;
|
|
455
|
+
if (!remainder.startsWith(quarantineMarker))
|
|
456
|
+
continue;
|
|
457
|
+
if (/^,\"quarantinedAt\":\d*$/.test(remainder))
|
|
458
|
+
return true;
|
|
459
|
+
}
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
async function metadataTemporaryFileContentsValid(handle, size) {
|
|
463
|
+
const data = Buffer.alloc(metadataMaximumBytes + 1);
|
|
464
|
+
const readR = await handle.read(data, 0, data.length, 0);
|
|
465
|
+
if (readR.bytesRead !== size || readR.bytesRead > metadataMaximumBytes)
|
|
466
|
+
return false;
|
|
467
|
+
let text;
|
|
468
|
+
try {
|
|
469
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(data.subarray(0, readR.bytesRead));
|
|
470
|
+
}
|
|
471
|
+
catch {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
if (metadataTemporaryTextPrefixValid(text))
|
|
475
|
+
return true;
|
|
476
|
+
try {
|
|
477
|
+
return metadataParse(JSON.parse(text)) !== undefined;
|
|
478
|
+
}
|
|
479
|
+
catch {
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
async function metadataTemporaryFileCandidateExists(directory, path, budget) {
|
|
484
|
+
const namesR = await metadataTemporaryDirectoryNamesRead(directory, path, budget);
|
|
485
|
+
if (!namesR.success)
|
|
486
|
+
return namesR;
|
|
487
|
+
const names = namesR.data;
|
|
488
|
+
return createResult(names.some(metadataTemporaryFileNameValid));
|
|
489
|
+
}
|
|
490
|
+
async function metadataTemporaryDirectoryNamesRead(directory, path, budget, directoryName = ".") {
|
|
491
|
+
if (directoryName !== ".") {
|
|
492
|
+
return retentionError("retention directory child name is invalid", path);
|
|
493
|
+
}
|
|
494
|
+
const entriesR = await directoryEntriesRead(directory, path, budget);
|
|
495
|
+
if (!entriesR.success)
|
|
496
|
+
return entriesR;
|
|
497
|
+
return createResult(entriesR.data.map((entry) => entry.name));
|
|
498
|
+
}
|
|
499
|
+
async function metadataTemporaryFilesCleanup(directory, path, budget, filesystem) {
|
|
500
|
+
const directoryStat = await directory.stat();
|
|
501
|
+
const namesR = await metadataTemporaryDirectoryNamesRead(directory, path, budget);
|
|
502
|
+
if (!namesR.success)
|
|
503
|
+
return namesR;
|
|
504
|
+
const names = [...namesR.data];
|
|
505
|
+
const temporaryEntries = [];
|
|
506
|
+
for (const name of names) {
|
|
507
|
+
if (!metadataTemporaryFileNameValid(name))
|
|
508
|
+
continue;
|
|
509
|
+
try {
|
|
510
|
+
temporaryEntries.push({ name, stat: await lstat(descriptorChildPath(directory, name)) });
|
|
511
|
+
}
|
|
512
|
+
catch {
|
|
513
|
+
return retentionError("retention directory changed while being inspected", path);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (temporaryEntries.length > metadataTemporaryMaximumFiles) {
|
|
517
|
+
return createResult({ removed: 0, empty: names.length === 0 });
|
|
518
|
+
}
|
|
519
|
+
let removed = 0;
|
|
520
|
+
for (const entry of temporaryEntries) {
|
|
521
|
+
if (!metadataTemporaryFileOwned(entry.stat, directoryStat.dev))
|
|
522
|
+
continue;
|
|
523
|
+
const entryPath = descriptorChildPath(directory, entry.name);
|
|
524
|
+
let handle;
|
|
525
|
+
try {
|
|
526
|
+
const openR = await projectAccessLogOpenat2({
|
|
527
|
+
directoryFd: directory.fd,
|
|
528
|
+
name: entry.name,
|
|
529
|
+
flags: descriptorFileFlags,
|
|
530
|
+
path: entryPath,
|
|
531
|
+
});
|
|
532
|
+
if (!openR.success || openR.data === undefined)
|
|
533
|
+
continue;
|
|
534
|
+
handle = openR.data;
|
|
535
|
+
const openedStat = await handle.stat();
|
|
536
|
+
if (!metadataTemporaryFileOwned(openedStat, directoryStat.dev) ||
|
|
537
|
+
!statSameObject(openedStat, entry.stat) ||
|
|
538
|
+
!(await metadataTemporaryFileContentsValid(handle, openedStat.size))) {
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
catch {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
finally {
|
|
546
|
+
await fileHandleClose(handle);
|
|
547
|
+
}
|
|
548
|
+
let currentStat;
|
|
549
|
+
try {
|
|
550
|
+
currentStat = await lstat(entryPath);
|
|
551
|
+
}
|
|
552
|
+
catch {
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
if (!metadataTemporaryFileOwned(currentStat, directoryStat.dev) || !statSameObject(currentStat, entry.stat))
|
|
556
|
+
continue;
|
|
557
|
+
try {
|
|
558
|
+
await unlink(entryPath);
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
if (errorCode(error) !== "ENOENT")
|
|
562
|
+
return retentionError("retention metadata temporary file could not be removed", path);
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
try {
|
|
566
|
+
await lstat(entryPath);
|
|
567
|
+
return retentionError("retention metadata temporary file removal became ambiguous", path);
|
|
568
|
+
}
|
|
569
|
+
catch (error) {
|
|
570
|
+
if (errorCode(error) !== "ENOENT") {
|
|
571
|
+
return retentionError("retention metadata temporary file removal could not be verified", path);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
removed += 1;
|
|
575
|
+
}
|
|
576
|
+
if (removed > 0) {
|
|
577
|
+
try {
|
|
578
|
+
await filesystem.syncDirectory(directory, "metadata-namespace");
|
|
579
|
+
}
|
|
580
|
+
catch {
|
|
581
|
+
return retentionError("retention metadata temporary file removal could not be made durable", path);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (removed === 0)
|
|
585
|
+
return createResult({ removed, empty: names.length === 0 });
|
|
586
|
+
const finalNamesR = await metadataTemporaryDirectoryNamesRead(directory, path, budget);
|
|
587
|
+
if (!finalNamesR.success)
|
|
588
|
+
return finalNamesR;
|
|
589
|
+
return createResult({ removed, empty: finalNamesR.data.length === 0 });
|
|
590
|
+
}
|
|
591
|
+
async function metadataWrite(directory, data, stillCurrent = () => true) {
|
|
592
|
+
if (!descriptorTraversalAvailable)
|
|
593
|
+
return false;
|
|
594
|
+
const serialized = JSON.stringify(data);
|
|
595
|
+
const encoded = Buffer.from(serialized, "utf8");
|
|
596
|
+
if (encoded.byteLength > metadataMaximumBytes)
|
|
597
|
+
return false;
|
|
598
|
+
let handle;
|
|
599
|
+
let temporaryPath;
|
|
600
|
+
let temporaryName;
|
|
601
|
+
let temporaryStat;
|
|
602
|
+
let success = false;
|
|
603
|
+
try {
|
|
604
|
+
for (let attempt = 0; attempt < metadataTemporaryCreateAttempts; attempt += 1) {
|
|
605
|
+
const candidateName = `${metadataTemporaryNamePrefix}${randomUUID()}`;
|
|
606
|
+
const candidatePath = descriptorChildPath(directory, candidateName);
|
|
607
|
+
const openR = await projectAccessLogOpenat2({
|
|
608
|
+
directoryFd: directory.fd,
|
|
609
|
+
name: candidateName,
|
|
610
|
+
flags: constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollowFlag,
|
|
611
|
+
mode: 0o600,
|
|
612
|
+
path: candidatePath,
|
|
613
|
+
});
|
|
614
|
+
if (!openR.success) {
|
|
615
|
+
if (openR.errorMessage.includes("existing entry"))
|
|
616
|
+
continue;
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
if (openR.data === undefined)
|
|
620
|
+
return false;
|
|
621
|
+
handle = openR.data;
|
|
622
|
+
temporaryPath = candidatePath;
|
|
623
|
+
temporaryName = candidateName;
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
if (handle === undefined || temporaryPath === undefined || temporaryName === undefined)
|
|
627
|
+
return false;
|
|
628
|
+
temporaryStat = await handle.stat();
|
|
629
|
+
if (!temporaryStat.isFile())
|
|
630
|
+
return false;
|
|
631
|
+
let offset = 0;
|
|
632
|
+
while (offset < encoded.byteLength) {
|
|
633
|
+
const writeR = await handle.write(encoded, offset, encoded.byteLength - offset, offset);
|
|
634
|
+
if (writeR.bytesWritten <= 0)
|
|
635
|
+
return false;
|
|
636
|
+
offset += writeR.bytesWritten;
|
|
637
|
+
}
|
|
638
|
+
const writtenStat = await handle.stat();
|
|
639
|
+
if (!writtenStat.isFile() ||
|
|
640
|
+
writtenStat.size !== encoded.byteLength ||
|
|
641
|
+
!statSameObject(writtenStat, temporaryStat)) {
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
await handle.sync();
|
|
645
|
+
await fileHandleClose(handle);
|
|
646
|
+
handle = undefined;
|
|
647
|
+
const currentR = await projectAccessLogOpenat2({
|
|
648
|
+
directoryFd: directory.fd,
|
|
649
|
+
name: temporaryName,
|
|
650
|
+
flags: descriptorFileFlags,
|
|
651
|
+
path: temporaryPath,
|
|
652
|
+
});
|
|
653
|
+
if (!currentR.success || currentR.data === undefined)
|
|
654
|
+
return false;
|
|
655
|
+
const currentHandle = currentR.data;
|
|
656
|
+
try {
|
|
657
|
+
const currentStat = await currentHandle.stat();
|
|
658
|
+
if (!currentStat.isFile() || !statSameObject(currentStat, temporaryStat))
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
finally {
|
|
662
|
+
await fileHandleClose(currentHandle);
|
|
663
|
+
}
|
|
664
|
+
if (!stillCurrent())
|
|
665
|
+
return false;
|
|
666
|
+
await rename(temporaryPath, descriptorChildPath(directory, metadataName));
|
|
667
|
+
temporaryPath = undefined;
|
|
668
|
+
temporaryName = undefined;
|
|
669
|
+
await directory.sync();
|
|
670
|
+
success = true;
|
|
671
|
+
}
|
|
672
|
+
catch {
|
|
673
|
+
// The previous metadata path is untouched until the verified temporary file is renamed over it.
|
|
674
|
+
}
|
|
675
|
+
finally {
|
|
676
|
+
await fileHandleClose(handle);
|
|
677
|
+
if (!(await metadataTemporaryFileCleanup(directory, temporaryName, temporaryStat)))
|
|
678
|
+
success = false;
|
|
679
|
+
}
|
|
680
|
+
return success;
|
|
681
|
+
}
|
|
682
|
+
async function projectDirectoryOpen(projects, project, projectsDevice) {
|
|
683
|
+
const path = descriptorChildPath(projects, project.id);
|
|
684
|
+
let handle;
|
|
685
|
+
try {
|
|
686
|
+
const listedStat = await lstat(path);
|
|
687
|
+
if (!listedStat.isDirectory() || listedStat.isSymbolicLink() || !statSameObject(listedStat, project.stat))
|
|
688
|
+
return undefined;
|
|
689
|
+
if (listedStat.dev !== projectsDevice)
|
|
690
|
+
return undefined;
|
|
691
|
+
const openR = await projectAccessLogOpenat2({
|
|
692
|
+
directoryFd: projects.fd,
|
|
693
|
+
name: project.id,
|
|
694
|
+
flags: descriptorDirectoryFlags,
|
|
695
|
+
path,
|
|
696
|
+
});
|
|
697
|
+
if (!openR.success || openR.data === undefined)
|
|
698
|
+
return undefined;
|
|
699
|
+
handle = openR.data;
|
|
700
|
+
const openedStat = await handle.stat();
|
|
701
|
+
if (!openedStat.isDirectory() || !statSameObject(openedStat, project.stat) || openedStat.dev !== projectsDevice) {
|
|
702
|
+
await fileHandleClose(handle);
|
|
703
|
+
return undefined;
|
|
704
|
+
}
|
|
705
|
+
const retained = handle;
|
|
706
|
+
handle = undefined;
|
|
707
|
+
return retained;
|
|
708
|
+
}
|
|
709
|
+
catch {
|
|
710
|
+
await fileHandleClose(handle);
|
|
711
|
+
return undefined;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
async function quarantineDirectoryOpen(root, device, create, filesystem) {
|
|
715
|
+
const path = descriptorChildPath(root, quarantineDirectoryName);
|
|
716
|
+
if (create) {
|
|
717
|
+
let created = false;
|
|
718
|
+
try {
|
|
719
|
+
await mkdir(path, 0o700);
|
|
720
|
+
created = true;
|
|
721
|
+
}
|
|
722
|
+
catch (error) {
|
|
723
|
+
if (errorCode(error) !== "EEXIST") {
|
|
724
|
+
return retentionError("retention quarantine directory could not be created", path);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
if (created) {
|
|
728
|
+
try {
|
|
729
|
+
await filesystem.syncDirectory(root, "quarantine-namespace");
|
|
730
|
+
}
|
|
731
|
+
catch {
|
|
732
|
+
return retentionError("retention quarantine directory creation could not be made durable", path);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
const directoryR = await directoryOpenRelative(root, quarantineDirectoryName, path);
|
|
737
|
+
if (!directoryR.success)
|
|
738
|
+
return directoryR;
|
|
739
|
+
if (directoryR.data === undefined)
|
|
740
|
+
return createResult(undefined);
|
|
741
|
+
let directoryStat;
|
|
742
|
+
try {
|
|
743
|
+
directoryStat = await directoryR.data.stat();
|
|
744
|
+
}
|
|
745
|
+
catch {
|
|
746
|
+
await fileHandleClose(directoryR.data);
|
|
747
|
+
return retentionError("retention quarantine directory could not be inspected", path);
|
|
748
|
+
}
|
|
749
|
+
if (!directoryStat.isDirectory() || directoryStat.dev !== device || (directoryStat.mode & 0o077) !== 0) {
|
|
750
|
+
await fileHandleClose(directoryR.data);
|
|
751
|
+
return retentionError("retention quarantine directory is not restrictive", path);
|
|
752
|
+
}
|
|
753
|
+
return directoryR;
|
|
754
|
+
}
|
|
755
|
+
async function projectDirectoryVerifyFlat(directory, path, budget) {
|
|
756
|
+
const entriesR = await directoryEntriesRead(directory, path, budget);
|
|
757
|
+
if (!entriesR.success)
|
|
758
|
+
return entriesR;
|
|
759
|
+
// Caddy's access-log directory is flat. Refuse unexpected child directories and special files rather than
|
|
760
|
+
// recursively traversing a mount or a race-prone tree.
|
|
761
|
+
for (const entry of entriesR.data) {
|
|
762
|
+
if (entry.stat.isDirectory() || (!entry.stat.isFile() && !entry.stat.isSymbolicLink()))
|
|
763
|
+
return createResult(false);
|
|
764
|
+
}
|
|
765
|
+
for (const entry of entriesR.data) {
|
|
766
|
+
const entryPath = descriptorChildPath(directory, entry.name);
|
|
767
|
+
let currentStat;
|
|
768
|
+
try {
|
|
769
|
+
currentStat = await lstat(entryPath);
|
|
770
|
+
}
|
|
771
|
+
catch {
|
|
772
|
+
return createResult(false);
|
|
773
|
+
}
|
|
774
|
+
if (currentStat.isSymbolicLink())
|
|
775
|
+
continue;
|
|
776
|
+
if (!currentStat.isFile() || !statSameObject(currentStat, entry.stat))
|
|
777
|
+
return createResult(false);
|
|
778
|
+
let file;
|
|
779
|
+
try {
|
|
780
|
+
const openR = await projectAccessLogOpenat2({
|
|
781
|
+
directoryFd: directory.fd,
|
|
782
|
+
name: entry.name,
|
|
783
|
+
flags: descriptorFileFlags,
|
|
784
|
+
path: entryPath,
|
|
785
|
+
});
|
|
786
|
+
if (!openR.success || openR.data === undefined)
|
|
787
|
+
return createResult(false);
|
|
788
|
+
file = openR.data;
|
|
789
|
+
const openedStat = await file.stat();
|
|
790
|
+
if (!openedStat.isFile() || !statSameObject(openedStat, entry.stat))
|
|
791
|
+
return createResult(false);
|
|
792
|
+
}
|
|
793
|
+
catch {
|
|
794
|
+
return createResult(false);
|
|
795
|
+
}
|
|
796
|
+
finally {
|
|
797
|
+
await fileHandleClose(file);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return createResult(true);
|
|
801
|
+
}
|
|
802
|
+
async function projectDirectoryQuarantine(projects, project, projectsDevice, budget, quarantine, now, inactiveAt, stillCurrent, filesystem) {
|
|
803
|
+
const directory = await projectDirectoryOpen(projects, project, projectsDevice);
|
|
804
|
+
if (directory === undefined)
|
|
805
|
+
return createResult(false);
|
|
806
|
+
const projectPath = descriptorChildPath(projects, project.id);
|
|
807
|
+
const quarantinePath = descriptorChildPath(quarantine, project.id);
|
|
808
|
+
try {
|
|
809
|
+
const verifiedR = await projectDirectoryVerifyFlat(directory, projectPath, budget);
|
|
810
|
+
if (!verifiedR.success || !verifiedR.data)
|
|
811
|
+
return verifiedR;
|
|
812
|
+
let currentProjectStat;
|
|
813
|
+
try {
|
|
814
|
+
currentProjectStat = await lstat(projectPath);
|
|
815
|
+
}
|
|
816
|
+
catch {
|
|
817
|
+
return createResult(false);
|
|
818
|
+
}
|
|
819
|
+
if (!currentProjectStat.isDirectory() ||
|
|
820
|
+
currentProjectStat.isSymbolicLink() ||
|
|
821
|
+
!statSameObject(currentProjectStat, project.stat) ||
|
|
822
|
+
currentProjectStat.dev !== projectsDevice) {
|
|
823
|
+
return createResult(false);
|
|
824
|
+
}
|
|
825
|
+
const openProjectStat = await directory.stat();
|
|
826
|
+
if (!openProjectStat.isDirectory() ||
|
|
827
|
+
!statSameObject(openProjectStat, project.stat) ||
|
|
828
|
+
openProjectStat.dev !== projectsDevice) {
|
|
829
|
+
return createResult(false);
|
|
830
|
+
}
|
|
831
|
+
try {
|
|
832
|
+
await lstat(quarantinePath);
|
|
833
|
+
return createResult(false);
|
|
834
|
+
}
|
|
835
|
+
catch (error) {
|
|
836
|
+
if (errorCode(error) !== "ENOENT")
|
|
837
|
+
return createResult(false);
|
|
838
|
+
}
|
|
839
|
+
let currentOpenProjectStat;
|
|
840
|
+
try {
|
|
841
|
+
currentOpenProjectStat = await directory.stat();
|
|
842
|
+
}
|
|
843
|
+
catch {
|
|
844
|
+
return createResult(false);
|
|
845
|
+
}
|
|
846
|
+
if (!statSameObject(currentOpenProjectStat, project.stat) || currentOpenProjectStat.dev !== projectsDevice) {
|
|
847
|
+
return createResult(false);
|
|
848
|
+
}
|
|
849
|
+
const currentMetadata = await metadataRead(directory);
|
|
850
|
+
if (currentMetadata.kind !== "valid" ||
|
|
851
|
+
currentMetadata.data.state !== "inactive" ||
|
|
852
|
+
currentMetadata.data.inactiveAt !== inactiveAt) {
|
|
853
|
+
return createResult(false);
|
|
854
|
+
}
|
|
855
|
+
// Re-open the source with openat2 immediately before the namespace transition. This closes the earlier
|
|
856
|
+
// verification window, but renameat2 still accepts a source name rather than an inode-bound descriptor.
|
|
857
|
+
// Linux has no native inode-bound directory rename, so a replacement can still win the tiny gap after this
|
|
858
|
+
// check and before renameat2. The post-rename check must therefore fail closed and leave the target quarantined.
|
|
859
|
+
const preRenameDirectory = await projectDirectoryOpen(projects, project, projectsDevice);
|
|
860
|
+
if (preRenameDirectory === undefined)
|
|
861
|
+
return createResult(false);
|
|
862
|
+
await fileHandleClose(preRenameDirectory);
|
|
863
|
+
if (!stillCurrent())
|
|
864
|
+
return createResult(false);
|
|
865
|
+
await filesystem.beforeQuarantineRename?.();
|
|
866
|
+
if (!directoryRenameNoReplace(projects, project.id, quarantine, project.id))
|
|
867
|
+
return createResult(false);
|
|
868
|
+
// Re-open the quarantine target before fsync, metadata writes, or any later cleanup. A source-name replacement
|
|
869
|
+
// may have been moved by renameat2 despite the earlier openat2 verification. Never move an unverified target
|
|
870
|
+
// back into the live projects namespace.
|
|
871
|
+
await filesystem.afterQuarantineRename?.();
|
|
872
|
+
const moved = await projectDirectoryOpen(quarantine, project, projectsDevice);
|
|
873
|
+
if (moved === undefined)
|
|
874
|
+
return createResult(false);
|
|
875
|
+
try {
|
|
876
|
+
try {
|
|
877
|
+
await filesystem.syncDirectory(projects, "quarantine-rename-source");
|
|
878
|
+
}
|
|
879
|
+
catch {
|
|
880
|
+
return retentionError("retention quarantine source rename could not be made durable", project.id);
|
|
881
|
+
}
|
|
882
|
+
try {
|
|
883
|
+
await filesystem.syncDirectory(quarantine, "quarantine-rename-destination");
|
|
884
|
+
}
|
|
885
|
+
catch {
|
|
886
|
+
return retentionError("retention quarantine destination rename could not be made durable", project.id);
|
|
887
|
+
}
|
|
888
|
+
const movedStat = await moved.stat();
|
|
889
|
+
if (!movedStat.isDirectory() || !statSameObject(movedStat, project.stat) || movedStat.dev !== projectsDevice) {
|
|
890
|
+
return createResult(false);
|
|
891
|
+
}
|
|
892
|
+
const movedMetadata = await metadataRead(moved);
|
|
893
|
+
if (movedMetadata.kind !== "valid" ||
|
|
894
|
+
movedMetadata.data.state !== "inactive" ||
|
|
895
|
+
movedMetadata.data.inactiveAt !== inactiveAt) {
|
|
896
|
+
return createResult(false);
|
|
897
|
+
}
|
|
898
|
+
return createResult(await metadataWrite(moved, { version: 1, state: "quarantined", inactiveAt, quarantinedAt: now }, stillCurrent));
|
|
899
|
+
}
|
|
900
|
+
finally {
|
|
901
|
+
await fileHandleClose(moved);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
finally {
|
|
905
|
+
await fileHandleClose(directory);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
async function quarantineDirectoryCrashCleanup(quarantine, project, quarantineDevice, budget, filesystem, removeEmpty) {
|
|
909
|
+
const childR = await directoryOpenRelative(quarantine, project.id, descriptorChildPath(quarantine, project.id));
|
|
910
|
+
if (!childR.success || childR.data === undefined)
|
|
911
|
+
return createResult(false);
|
|
912
|
+
let hasTemporaryFile = false;
|
|
913
|
+
try {
|
|
914
|
+
const namesR = await metadataTemporaryDirectoryNamesRead(childR.data, descriptorChildPath(quarantine, project.id), budget);
|
|
915
|
+
if (!namesR.success)
|
|
916
|
+
return namesR;
|
|
917
|
+
hasTemporaryFile = namesR.data.some(metadataTemporaryFileNameValid);
|
|
918
|
+
}
|
|
919
|
+
finally {
|
|
920
|
+
await fileHandleClose(childR.data);
|
|
921
|
+
}
|
|
922
|
+
if (!hasTemporaryFile)
|
|
923
|
+
return createResult(false);
|
|
924
|
+
const directory = await projectDirectoryOpen(quarantine, project, quarantineDevice);
|
|
925
|
+
if (directory === undefined)
|
|
926
|
+
return createResult(false);
|
|
927
|
+
const path = descriptorChildPath(quarantine, project.id);
|
|
928
|
+
try {
|
|
929
|
+
const cleanupR = await metadataTemporaryFilesCleanup(directory, path, budget, filesystem);
|
|
930
|
+
if (!cleanupR.success)
|
|
931
|
+
return cleanupR;
|
|
932
|
+
// An empty directory with no daemon-created temporary metadata is ambiguous: it may be an operator's
|
|
933
|
+
// lookalike. Only the observed removal of a validated daemon temporary proves this is a crash-left cleanup
|
|
934
|
+
// remainder.
|
|
935
|
+
if (!removeEmpty || cleanupR.data.removed === 0 || !cleanupR.data.empty)
|
|
936
|
+
return createResult(false);
|
|
937
|
+
const confirmedDirectory = await projectDirectoryOpen(quarantine, project, quarantineDevice);
|
|
938
|
+
if (confirmedDirectory === undefined)
|
|
939
|
+
return createResult(false);
|
|
940
|
+
try {
|
|
941
|
+
const confirmedEntriesR = await directoryEntriesRead(confirmedDirectory, path, budget);
|
|
942
|
+
if (!confirmedEntriesR.success)
|
|
943
|
+
return confirmedEntriesR;
|
|
944
|
+
if (confirmedEntriesR.data.length !== 0)
|
|
945
|
+
return createResult(false);
|
|
946
|
+
const confirmedStat = await confirmedDirectory.stat();
|
|
947
|
+
if (!confirmedStat.isDirectory() ||
|
|
948
|
+
!statSameObject(confirmedStat, project.stat) ||
|
|
949
|
+
confirmedStat.dev !== quarantineDevice) {
|
|
950
|
+
return createResult(false);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
finally {
|
|
954
|
+
await fileHandleClose(confirmedDirectory);
|
|
955
|
+
}
|
|
956
|
+
try {
|
|
957
|
+
await rmdir(path);
|
|
958
|
+
}
|
|
959
|
+
catch (error) {
|
|
960
|
+
if (errorCode(error) === "ENOENT")
|
|
961
|
+
return createResult(false);
|
|
962
|
+
return retentionError("crash-left quarantine directory could not be removed", path);
|
|
963
|
+
}
|
|
964
|
+
try {
|
|
965
|
+
await lstat(path);
|
|
966
|
+
return retentionError("crash-left quarantine directory removal became ambiguous", path);
|
|
967
|
+
}
|
|
968
|
+
catch (error) {
|
|
969
|
+
if (errorCode(error) !== "ENOENT") {
|
|
970
|
+
return retentionError("crash-left quarantine directory removal could not be verified", path);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
try {
|
|
974
|
+
await filesystem.syncDirectory(quarantine, "quarantine-namespace");
|
|
975
|
+
}
|
|
976
|
+
catch {
|
|
977
|
+
return retentionError("crash-left quarantine directory removal could not be made durable", path);
|
|
978
|
+
}
|
|
979
|
+
return createResult(true);
|
|
980
|
+
}
|
|
981
|
+
finally {
|
|
982
|
+
await fileHandleClose(directory);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
async function quarantineDirectoryCleanup(quarantine, project, quarantineDevice, budget, now, filesystem) {
|
|
986
|
+
const directory = await projectDirectoryOpen(quarantine, project, quarantineDevice);
|
|
987
|
+
if (directory === undefined)
|
|
988
|
+
return createResult(false);
|
|
989
|
+
const path = descriptorChildPath(quarantine, project.id);
|
|
990
|
+
try {
|
|
991
|
+
const directoryStat = await directory.stat();
|
|
992
|
+
if (!directoryStat.isDirectory() ||
|
|
993
|
+
!statSameObject(directoryStat, project.stat) ||
|
|
994
|
+
directoryStat.dev !== quarantineDevice) {
|
|
995
|
+
return createResult(false);
|
|
996
|
+
}
|
|
997
|
+
const metadata = await metadataRead(directory);
|
|
998
|
+
if (metadata.kind !== "valid" || metadata.data.state !== "quarantined")
|
|
999
|
+
return createResult(false);
|
|
1000
|
+
if (!quarantineGraceExpired(metadata.data.quarantinedAt, now))
|
|
1001
|
+
return createResult(false);
|
|
1002
|
+
const entriesR = await directoryEntriesRead(directory, path, budget);
|
|
1003
|
+
if (!entriesR.success)
|
|
1004
|
+
return entriesR;
|
|
1005
|
+
if (entriesR.data.length === 0)
|
|
1006
|
+
return createResult(false);
|
|
1007
|
+
for (const entry of entriesR.data) {
|
|
1008
|
+
if (!entry.stat.isFile() ||
|
|
1009
|
+
entry.stat.isSymbolicLink() ||
|
|
1010
|
+
entry.stat.dev !== quarantineDevice ||
|
|
1011
|
+
(entry.name !== metadataName && !quarantineLogFileKnown(entry.name))) {
|
|
1012
|
+
return createResult(false);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
const confirmedMetadata = await metadataRead(directory);
|
|
1016
|
+
if (confirmedMetadata.kind !== "valid" ||
|
|
1017
|
+
confirmedMetadata.data.state !== "quarantined" ||
|
|
1018
|
+
confirmedMetadata.data.inactiveAt !== metadata.data.inactiveAt ||
|
|
1019
|
+
confirmedMetadata.data.quarantinedAt !== metadata.data.quarantinedAt ||
|
|
1020
|
+
!quarantineGraceExpired(confirmedMetadata.data.quarantinedAt, now)) {
|
|
1021
|
+
return createResult(false);
|
|
1022
|
+
}
|
|
1023
|
+
const confirmedDirectoryStat = await directory.stat();
|
|
1024
|
+
if (!confirmedDirectoryStat.isDirectory() ||
|
|
1025
|
+
!statSameObject(confirmedDirectoryStat, directoryStat) ||
|
|
1026
|
+
confirmedDirectoryStat.dev !== quarantineDevice) {
|
|
1027
|
+
return createResult(false);
|
|
1028
|
+
}
|
|
1029
|
+
const confirmedEntriesR = await directoryEntriesRead(directory, path, budget);
|
|
1030
|
+
if (!confirmedEntriesR.success)
|
|
1031
|
+
return confirmedEntriesR;
|
|
1032
|
+
if (confirmedEntriesR.data.length !== entriesR.data.length ||
|
|
1033
|
+
confirmedEntriesR.data.some((entry, index) => {
|
|
1034
|
+
const original = entriesR.data[index];
|
|
1035
|
+
return (original === undefined ||
|
|
1036
|
+
entry.name !== original.name ||
|
|
1037
|
+
!statSameObject(entry.stat, original.stat) ||
|
|
1038
|
+
entry.stat.dev !== original.stat.dev);
|
|
1039
|
+
})) {
|
|
1040
|
+
return createResult(false);
|
|
1041
|
+
}
|
|
1042
|
+
const entriesToRemove = [...entriesR.data].sort((left, right) => {
|
|
1043
|
+
if (left.name === metadataName)
|
|
1044
|
+
return 1;
|
|
1045
|
+
if (right.name === metadataName)
|
|
1046
|
+
return -1;
|
|
1047
|
+
return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
|
|
1048
|
+
});
|
|
1049
|
+
for (const entry of entriesToRemove) {
|
|
1050
|
+
let currentStat;
|
|
1051
|
+
try {
|
|
1052
|
+
currentStat = await lstat(descriptorChildPath(directory, entry.name));
|
|
1053
|
+
}
|
|
1054
|
+
catch {
|
|
1055
|
+
return createResult(false);
|
|
1056
|
+
}
|
|
1057
|
+
if (!currentStat.isFile() ||
|
|
1058
|
+
currentStat.isSymbolicLink() ||
|
|
1059
|
+
currentStat.dev !== quarantineDevice ||
|
|
1060
|
+
!statSameObject(currentStat, entry.stat)) {
|
|
1061
|
+
return createResult(false);
|
|
1062
|
+
}
|
|
1063
|
+
const candidateR = await projectAccessLogOpenat2({
|
|
1064
|
+
directoryFd: directory.fd,
|
|
1065
|
+
name: entry.name,
|
|
1066
|
+
flags: descriptorFileFlags,
|
|
1067
|
+
path: descriptorChildPath(directory, entry.name),
|
|
1068
|
+
});
|
|
1069
|
+
if (!candidateR.success || candidateR.data === undefined)
|
|
1070
|
+
return createResult(false);
|
|
1071
|
+
try {
|
|
1072
|
+
const candidateStat = await candidateR.data.stat();
|
|
1073
|
+
if (!candidateStat.isFile() ||
|
|
1074
|
+
!statSameObject(candidateStat, entry.stat) ||
|
|
1075
|
+
candidateStat.dev !== quarantineDevice) {
|
|
1076
|
+
return createResult(false);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
finally {
|
|
1080
|
+
await fileHandleClose(candidateR.data);
|
|
1081
|
+
}
|
|
1082
|
+
try {
|
|
1083
|
+
await unlink(descriptorChildPath(directory, entry.name));
|
|
1084
|
+
}
|
|
1085
|
+
catch {
|
|
1086
|
+
return createResult(false);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
const finalDirectoryStat = await directory.stat();
|
|
1090
|
+
if (!finalDirectoryStat.isDirectory() ||
|
|
1091
|
+
!statSameObject(finalDirectoryStat, directoryStat) ||
|
|
1092
|
+
finalDirectoryStat.dev !== quarantineDevice) {
|
|
1093
|
+
return createResult(false);
|
|
1094
|
+
}
|
|
1095
|
+
const finalEntriesR = await directoryEntriesRead(directory, path, budget);
|
|
1096
|
+
if (!finalEntriesR.success)
|
|
1097
|
+
return finalEntriesR;
|
|
1098
|
+
if (finalEntriesR.data.length !== 0)
|
|
1099
|
+
return createResult(false);
|
|
1100
|
+
const directoryCandidateR = await projectAccessLogOpenat2({
|
|
1101
|
+
directoryFd: quarantine.fd,
|
|
1102
|
+
name: project.id,
|
|
1103
|
+
flags: descriptorDirectoryFlags,
|
|
1104
|
+
path,
|
|
1105
|
+
});
|
|
1106
|
+
if (!directoryCandidateR.success || directoryCandidateR.data === undefined)
|
|
1107
|
+
return createResult(false);
|
|
1108
|
+
try {
|
|
1109
|
+
const candidateStat = await directoryCandidateR.data.stat();
|
|
1110
|
+
if (!candidateStat.isDirectory() ||
|
|
1111
|
+
!statSameObject(candidateStat, directoryStat) ||
|
|
1112
|
+
candidateStat.dev !== quarantineDevice) {
|
|
1113
|
+
return createResult(false);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
finally {
|
|
1117
|
+
await fileHandleClose(directoryCandidateR.data);
|
|
1118
|
+
}
|
|
1119
|
+
try {
|
|
1120
|
+
await rmdir(path);
|
|
1121
|
+
}
|
|
1122
|
+
catch {
|
|
1123
|
+
return createResult(false);
|
|
1124
|
+
}
|
|
1125
|
+
try {
|
|
1126
|
+
await lstat(path);
|
|
1127
|
+
return createResult(false);
|
|
1128
|
+
}
|
|
1129
|
+
catch (error) {
|
|
1130
|
+
if (errorCode(error) !== "ENOENT")
|
|
1131
|
+
return createResult(false);
|
|
1132
|
+
try {
|
|
1133
|
+
await filesystem.syncDirectory(quarantine, "quarantine-namespace");
|
|
1134
|
+
}
|
|
1135
|
+
catch {
|
|
1136
|
+
return retentionError("quarantine directory removal could not be made durable", path);
|
|
1137
|
+
}
|
|
1138
|
+
return createResult(true);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
finally {
|
|
1142
|
+
await fileHandleClose(directory);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
async function projectAccessLogRetentionReconcileRun(options) {
|
|
1146
|
+
const { root, activeProjectIds, now, stillCurrent, filesystem } = options;
|
|
1147
|
+
const active = new Set(activeProjectIds);
|
|
1148
|
+
const rootR = await rootDirectoryOpen(root);
|
|
1149
|
+
if (!rootR.success)
|
|
1150
|
+
return rootR;
|
|
1151
|
+
if (rootR.data === undefined)
|
|
1152
|
+
return createResult(true);
|
|
1153
|
+
const rootDirectory = rootR.data;
|
|
1154
|
+
let projectsDirectory;
|
|
1155
|
+
let quarantineDirectory;
|
|
1156
|
+
let quarantineDevice;
|
|
1157
|
+
try {
|
|
1158
|
+
const rootStat = await rootDirectory.stat();
|
|
1159
|
+
const projectsR = await directoryOpenRelative(rootDirectory, "projects", posix.join(root, "projects"));
|
|
1160
|
+
if (!projectsR.success)
|
|
1161
|
+
return projectsR;
|
|
1162
|
+
if (projectsR.data === undefined)
|
|
1163
|
+
return createResult(true);
|
|
1164
|
+
projectsDirectory = projectsR.data;
|
|
1165
|
+
const projects = projectsDirectory;
|
|
1166
|
+
const projectsStat = await projects.stat();
|
|
1167
|
+
// A mounted projects directory is outside the configured root boundary for this reconciliation.
|
|
1168
|
+
if (projectsStat.dev !== rootStat.dev)
|
|
1169
|
+
return createResult(true);
|
|
1170
|
+
const budget = { entries: 0 };
|
|
1171
|
+
const quarantineR = await quarantineDirectoryOpen(rootDirectory, projectsStat.dev, false, filesystem);
|
|
1172
|
+
if (!quarantineR.success)
|
|
1173
|
+
return quarantineR;
|
|
1174
|
+
quarantineDirectory = quarantineR.data;
|
|
1175
|
+
const quarantineProjects = [];
|
|
1176
|
+
if (quarantineDirectory !== undefined) {
|
|
1177
|
+
const quarantineEntriesR = await directoryEntriesRead(quarantineDirectory, posix.join(root, quarantineDirectoryName), budget);
|
|
1178
|
+
if (!quarantineEntriesR.success)
|
|
1179
|
+
return quarantineEntriesR;
|
|
1180
|
+
quarantineDevice = (await quarantineDirectory.stat()).dev;
|
|
1181
|
+
for (const entry of quarantineEntriesR.data) {
|
|
1182
|
+
if (!projectIdPattern.test(entry.name) || !entry.stat.isDirectory() || entry.stat.isSymbolicLink())
|
|
1183
|
+
continue;
|
|
1184
|
+
if (entry.stat.dev !== quarantineDevice)
|
|
1185
|
+
continue;
|
|
1186
|
+
quarantineProjects.push({ id: entry.name, stat: entry.stat });
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
const entriesR = await directoryEntriesRead(projects, posix.join(root, "projects"), budget);
|
|
1190
|
+
if (!entriesR.success)
|
|
1191
|
+
return entriesR;
|
|
1192
|
+
const liveProjectEntryNames = new Set();
|
|
1193
|
+
const projectDirectories = [];
|
|
1194
|
+
for (const entry of entriesR.data) {
|
|
1195
|
+
if (!projectIdPattern.test(entry.name))
|
|
1196
|
+
continue;
|
|
1197
|
+
liveProjectEntryNames.add(entry.name);
|
|
1198
|
+
if (!entry.stat.isDirectory() || entry.stat.isSymbolicLink())
|
|
1199
|
+
continue;
|
|
1200
|
+
if (entry.stat.dev !== projectsStat.dev)
|
|
1201
|
+
continue;
|
|
1202
|
+
projectDirectories.push({ id: entry.name, stat: entry.stat });
|
|
1203
|
+
}
|
|
1204
|
+
// A rename can be interrupted after the live directory moves and before its state is changed. Adopt only a
|
|
1205
|
+
// quarantine directory that still contains the verified inactive metadata carried by that live directory.
|
|
1206
|
+
for (const quarantinedProject of quarantineProjects) {
|
|
1207
|
+
if (quarantineDirectory === undefined)
|
|
1208
|
+
continue;
|
|
1209
|
+
const crashCleanupR = await quarantineDirectoryCrashCleanup(quarantineDirectory, quarantinedProject, projectsStat.dev, budget, filesystem, !active.has(quarantinedProject.id) && !liveProjectEntryNames.has(quarantinedProject.id));
|
|
1210
|
+
if (!crashCleanupR.success)
|
|
1211
|
+
return crashCleanupR;
|
|
1212
|
+
if (crashCleanupR.data)
|
|
1213
|
+
continue;
|
|
1214
|
+
if (active.has(quarantinedProject.id))
|
|
1215
|
+
continue;
|
|
1216
|
+
if (liveProjectEntryNames.has(quarantinedProject.id))
|
|
1217
|
+
continue;
|
|
1218
|
+
const directory = await projectDirectoryOpen(quarantineDirectory, quarantinedProject, projectsStat.dev);
|
|
1219
|
+
if (directory === undefined)
|
|
1220
|
+
continue;
|
|
1221
|
+
try {
|
|
1222
|
+
const verifiedR = await projectDirectoryVerifyFlat(directory, descriptorChildPath(quarantineDirectory, quarantinedProject.id), budget);
|
|
1223
|
+
if (!verifiedR.success)
|
|
1224
|
+
return verifiedR;
|
|
1225
|
+
if (!verifiedR.data)
|
|
1226
|
+
continue;
|
|
1227
|
+
const metadata = await metadataRead(directory);
|
|
1228
|
+
if (metadata.kind !== "valid" || metadata.data.state !== "inactive")
|
|
1229
|
+
continue;
|
|
1230
|
+
if (metadata.data.inactiveAt > now || now - metadata.data.inactiveAt < retentionWindowMs)
|
|
1231
|
+
continue;
|
|
1232
|
+
const confirmedMetadata = await metadataRead(directory);
|
|
1233
|
+
if (confirmedMetadata.kind !== "valid" ||
|
|
1234
|
+
confirmedMetadata.data.state !== "inactive" ||
|
|
1235
|
+
confirmedMetadata.data.inactiveAt !== metadata.data.inactiveAt) {
|
|
1236
|
+
continue;
|
|
1237
|
+
}
|
|
1238
|
+
const adopted = await metadataWrite(directory, {
|
|
1239
|
+
version: 1,
|
|
1240
|
+
state: "quarantined",
|
|
1241
|
+
inactiveAt: confirmedMetadata.data.inactiveAt,
|
|
1242
|
+
quarantinedAt: now,
|
|
1243
|
+
}, stillCurrent);
|
|
1244
|
+
if (!adopted)
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
finally {
|
|
1248
|
+
await fileHandleClose(directory);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
if (quarantineDirectory !== undefined && quarantineDevice !== undefined) {
|
|
1252
|
+
for (const quarantinedProject of quarantineProjects) {
|
|
1253
|
+
const cleanedR = await quarantineDirectoryCleanup(quarantineDirectory, quarantinedProject, quarantineDevice, budget, now, filesystem);
|
|
1254
|
+
if (!cleanedR.success)
|
|
1255
|
+
return cleanedR;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
for (const project of projectDirectories) {
|
|
1259
|
+
const directory = await projectDirectoryOpen(projects, project, projectsStat.dev);
|
|
1260
|
+
if (directory === undefined)
|
|
1261
|
+
continue;
|
|
1262
|
+
let metadata;
|
|
1263
|
+
try {
|
|
1264
|
+
const temporaryPath = descriptorChildPath(projects, project.id);
|
|
1265
|
+
const temporaryCandidateR = await metadataTemporaryFileCandidateExists(directory, temporaryPath, budget);
|
|
1266
|
+
if (!temporaryCandidateR.success)
|
|
1267
|
+
return temporaryCandidateR;
|
|
1268
|
+
const temporaryCleanupR = temporaryCandidateR.data
|
|
1269
|
+
? await metadataTemporaryFilesCleanup(directory, temporaryPath, budget, filesystem)
|
|
1270
|
+
: createResult({ removed: 0, empty: false });
|
|
1271
|
+
if (!temporaryCleanupR.success)
|
|
1272
|
+
return temporaryCleanupR;
|
|
1273
|
+
metadata = await metadataRead(directory);
|
|
1274
|
+
}
|
|
1275
|
+
finally {
|
|
1276
|
+
await fileHandleClose(directory);
|
|
1277
|
+
}
|
|
1278
|
+
if (active.has(project.id)) {
|
|
1279
|
+
if (metadata.kind !== "valid" || metadata.data.state !== "active") {
|
|
1280
|
+
const activeDirectory = await projectDirectoryOpen(projects, project, projectsStat.dev);
|
|
1281
|
+
if (activeDirectory === undefined)
|
|
1282
|
+
continue;
|
|
1283
|
+
let activeWritten = false;
|
|
1284
|
+
try {
|
|
1285
|
+
if (!stillCurrent())
|
|
1286
|
+
continue;
|
|
1287
|
+
activeWritten = await metadataWrite(activeDirectory, { version: 1, state: "active" }, stillCurrent);
|
|
1288
|
+
}
|
|
1289
|
+
finally {
|
|
1290
|
+
await fileHandleClose(activeDirectory);
|
|
1291
|
+
}
|
|
1292
|
+
if (!activeWritten)
|
|
1293
|
+
continue;
|
|
1294
|
+
}
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
if (metadata.kind === "unavailable" || metadata.kind === "malformed")
|
|
1298
|
+
continue;
|
|
1299
|
+
if (metadata.kind === "missing" || (metadata.kind === "valid" && metadata.data.state === "active")) {
|
|
1300
|
+
const inactiveDirectory = await projectDirectoryOpen(projects, project, projectsStat.dev);
|
|
1301
|
+
if (inactiveDirectory === undefined)
|
|
1302
|
+
continue;
|
|
1303
|
+
let written = false;
|
|
1304
|
+
try {
|
|
1305
|
+
if (!stillCurrent())
|
|
1306
|
+
continue;
|
|
1307
|
+
written = await metadataWrite(inactiveDirectory, { version: 1, state: "inactive", inactiveAt: now }, stillCurrent);
|
|
1308
|
+
}
|
|
1309
|
+
finally {
|
|
1310
|
+
await fileHandleClose(inactiveDirectory);
|
|
1311
|
+
}
|
|
1312
|
+
if (!written)
|
|
1313
|
+
continue;
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
if (metadata.kind !== "valid" || metadata.data.state !== "inactive")
|
|
1317
|
+
continue;
|
|
1318
|
+
if (metadata.data.inactiveAt > now || now - metadata.data.inactiveAt < retentionWindowMs)
|
|
1319
|
+
continue;
|
|
1320
|
+
if (quarantineDirectory === undefined) {
|
|
1321
|
+
const quarantineCreateR = await quarantineDirectoryOpen(rootDirectory, projectsStat.dev, true, filesystem);
|
|
1322
|
+
if (!quarantineCreateR.success)
|
|
1323
|
+
return quarantineCreateR;
|
|
1324
|
+
quarantineDirectory = quarantineCreateR.data;
|
|
1325
|
+
if (quarantineDirectory === undefined)
|
|
1326
|
+
continue;
|
|
1327
|
+
}
|
|
1328
|
+
if (!stillCurrent())
|
|
1329
|
+
continue;
|
|
1330
|
+
const quarantinedR = await projectDirectoryQuarantine(projects, project, projectsStat.dev, budget, quarantineDirectory, now, metadata.data.inactiveAt, stillCurrent, filesystem);
|
|
1331
|
+
if (!quarantinedR.success)
|
|
1332
|
+
return quarantinedR;
|
|
1333
|
+
if (!quarantinedR.data)
|
|
1334
|
+
continue;
|
|
1335
|
+
}
|
|
1336
|
+
return createResult(true);
|
|
1337
|
+
}
|
|
1338
|
+
catch {
|
|
1339
|
+
return retentionError("retention reconciliation failed", root);
|
|
1340
|
+
}
|
|
1341
|
+
finally {
|
|
1342
|
+
await fileHandleClose(quarantineDirectory);
|
|
1343
|
+
await fileHandleClose(projectsDirectory);
|
|
1344
|
+
await fileHandleClose(rootDirectory);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
export function projectAccessLogRetentionReconcile(options) {
|
|
1348
|
+
const optionsR = retentionOptionsNormalize(options);
|
|
1349
|
+
if (!optionsR.success)
|
|
1350
|
+
return Promise.resolve(optionsR);
|
|
1351
|
+
const run = reconciliationFlight.then(async () => {
|
|
1352
|
+
try {
|
|
1353
|
+
return await projectAccessLogRetentionReconcileRun({
|
|
1354
|
+
...optionsR.data,
|
|
1355
|
+
stillCurrent: optionsR.data.stillCurrent ?? (() => true),
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
catch {
|
|
1359
|
+
return retentionError("retention reconciliation failed", optionsR.data.root);
|
|
1360
|
+
}
|
|
1361
|
+
});
|
|
1362
|
+
reconciliationFlight = run.then(() => undefined, () => undefined);
|
|
1363
|
+
return run;
|
|
1364
|
+
}
|
|
1365
|
+
//# sourceMappingURL=projectAccessLogRetentionReconcile.js.map
|