@neuralis/brain-core 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -1417
- package/app/README.md +4 -4
- package/app/cards/FilesystemCardShell.tsx +42 -4
- package/app/cards/FilesystemChangeCard.tsx +34 -11
- package/app/cards/README.md +6 -5
- package/app/cards/diffUtils.ts +99 -1
- package/app/filesystem/FilesystemHost.tsx +24 -2
- package/app/filesystem/README.md +1 -1
- package/app/filesystem/api/README.md +3 -3
- package/app/filesystem/api/index.ts +38 -14
- package/app/filesystem/api/projectPackages.ts +13 -102
- package/app/filesystem/domain/types.ts +30 -10
- package/app/filesystem/hooks/README.md +4 -4
- package/app/filesystem/hooks/useDiscoverableSources.ts +19 -30
- package/app/filesystem/hooks/useFilesystemSSE.ts +42 -2
- package/app/filesystem/host/README.md +6 -4
- package/app/filesystem/host/buildFilesystemHostValue.ts +28 -2
- package/app/filesystem/host/installFilesystemHostComponents.tsx +1 -1
- package/app/filesystem/lib/sourceKindForm.ts +210 -27
- package/app/filesystem/lib/treeVisualState.tsx +98 -4
- package/app/filesystem/store/README.md +1 -0
- package/app/filesystem/store/filesystemStore.ts +99 -8
- package/app/filesystem/store/gitSlice.ts +5 -0
- package/app/filesystem/store/helpers.ts +17 -0
- package/app/filesystem/store/listSlice.ts +8 -0
- package/app/filesystem/ui/CodeEditor.tsx +18 -3
- package/app/filesystem/ui/DiscoverDock.tsx +5 -1
- package/app/filesystem/ui/FileEditor.tsx +15 -10
- package/app/filesystem/ui/FileTree.tsx +75 -24
- package/app/filesystem/ui/FilesystemWidget.tsx +10 -2
- package/app/filesystem/ui/FolderPicker.tsx +251 -0
- package/app/filesystem/ui/GitControlPanel.tsx +7 -2
- package/app/filesystem/ui/PackagesPanel.tsx +52 -374
- package/app/filesystem/ui/PendingChangesPanel.tsx +1 -1
- package/app/filesystem/ui/PolicyEditor.tsx +109 -24
- package/app/filesystem/ui/README.md +30 -23
- package/app/filesystem/ui/RawMediaPreview.tsx +58 -0
- package/app/filesystem/ui/SourceBranchHeader.tsx +4 -4
- package/app/filesystem/ui/SourcesPanel.tsx +502 -342
- package/app/filesystem/ui/Toolbar.tsx +1 -2
- package/app/filesystem/ui/VectorHealthPanel.tsx +2 -2
- package/app/shared/filesystem.png +0 -0
- package/dist/app/host.js +58 -46
- package/dist/scripts/sourceRootPairV1.d.ts +47 -0
- package/dist/scripts/sourceRootPairV1.d.ts.map +1 -0
- package/dist/scripts/sourceRootPairV1.js +147 -0
- package/dist/scripts/sourceRootPairV1.js.map +1 -0
- package/dist/scripts/sourceToFolderV1.d.ts +56 -0
- package/dist/scripts/sourceToFolderV1.d.ts.map +1 -0
- package/dist/scripts/sourceToFolderV1.js +152 -0
- package/dist/scripts/sourceToFolderV1.js.map +1 -0
- package/dist/scripts/sourceToHostV1.d.ts +56 -0
- package/dist/scripts/sourceToHostV1.d.ts.map +1 -0
- package/dist/scripts/sourceToHostV1.js +132 -0
- package/dist/scripts/sourceToHostV1.js.map +1 -0
- package/dist/src/channels/filesystem.d.ts +1 -1
- package/dist/src/channels/filesystem.js +1 -1
- package/dist/src/connectors/AppSourceConfigStore.d.ts +17 -3
- package/dist/src/connectors/AppSourceConfigStore.d.ts.map +1 -1
- package/dist/src/connectors/AppSourceConfigStore.js +46 -6
- package/dist/src/connectors/AppSourceConfigStore.js.map +1 -1
- package/dist/src/connectors/HostConnector.d.ts +201 -0
- package/dist/src/connectors/HostConnector.d.ts.map +1 -0
- package/dist/src/connectors/HostConnector.js +903 -0
- package/dist/src/connectors/HostConnector.js.map +1 -0
- package/dist/src/connectors/inProcessTransport.d.ts +131 -0
- package/dist/src/connectors/inProcessTransport.d.ts.map +1 -0
- package/dist/src/connectors/inProcessTransport.js +447 -0
- package/dist/src/connectors/inProcessTransport.js.map +1 -0
- package/dist/src/domain/access/callerPermissions.d.ts +29 -0
- package/dist/src/domain/access/callerPermissions.d.ts.map +1 -1
- package/dist/src/domain/access/callerPermissions.js +85 -5
- package/dist/src/domain/access/callerPermissions.js.map +1 -1
- package/dist/src/domain/access/nativeLocalFence.d.ts +65 -0
- package/dist/src/domain/access/nativeLocalFence.d.ts.map +1 -0
- package/dist/src/domain/access/nativeLocalFence.js +171 -0
- package/dist/src/domain/access/nativeLocalFence.js.map +1 -0
- package/dist/src/domain/access/uriPermission.js +3 -3
- package/dist/src/domain/access/uriPermission.js.map +1 -1
- package/dist/src/domain/byteRange.d.ts +15 -0
- package/dist/src/domain/byteRange.d.ts.map +1 -0
- package/dist/src/domain/byteRange.js +30 -0
- package/dist/src/domain/byteRange.js.map +1 -0
- package/dist/src/domain/defaultPermissions.d.ts.map +1 -1
- package/dist/src/domain/defaultPermissions.js +29 -0
- package/dist/src/domain/defaultPermissions.js.map +1 -1
- package/dist/src/domain/mime.d.ts +11 -19
- package/dist/src/domain/mime.d.ts.map +1 -1
- package/dist/src/domain/mime.js +13 -102
- package/dist/src/domain/mime.js.map +1 -1
- package/dist/src/domain/paths.d.ts.map +1 -1
- package/dist/src/domain/paths.js +5 -3
- package/dist/src/domain/paths.js.map +1 -1
- package/dist/src/domain/scopeAccessCtx.d.ts +2 -2
- package/dist/src/domain/scopeAccessCtx.js +2 -2
- package/dist/src/domain/sourceConfig.d.ts +52 -19
- package/dist/src/domain/sourceConfig.d.ts.map +1 -1
- package/dist/src/domain/sourceConfig.js +103 -19
- package/dist/src/domain/sourceConfig.js.map +1 -1
- package/dist/src/domain/sourcePackages.d.ts +8 -8
- package/dist/src/domain/sourcePackages.d.ts.map +1 -1
- package/dist/src/domain/sourceRootPair.d.ts +88 -0
- package/dist/src/domain/sourceRootPair.d.ts.map +1 -0
- package/dist/src/domain/sourceRootPair.js +108 -0
- package/dist/src/domain/sourceRootPair.js.map +1 -0
- package/dist/src/domain/syncTypes.d.ts +8 -1
- package/dist/src/domain/syncTypes.d.ts.map +1 -1
- package/dist/src/domain/syncTypes.js +1 -0
- package/dist/src/domain/syncTypes.js.map +1 -1
- package/dist/src/domain/types.d.ts +32 -2
- package/dist/src/domain/types.d.ts.map +1 -1
- package/dist/src/domain/uri.d.ts.map +1 -1
- package/dist/src/domain/uri.js +3 -2
- package/dist/src/domain/uri.js.map +1 -1
- package/dist/src/embeddings/clients/GeminiEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/GeminiEmbedder.js +2 -5
- package/dist/src/embeddings/clients/GeminiEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/OpenAIEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/OpenAIEmbedder.js +2 -3
- package/dist/src/embeddings/clients/OpenAIEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/QwenEmbedder.d.ts +2 -0
- package/dist/src/embeddings/clients/QwenEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/QwenEmbedder.js +10 -2
- package/dist/src/embeddings/clients/QwenEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.d.ts +2 -0
- package/dist/src/embeddings/clients/VoyageEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.js +8 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.js.map +1 -1
- package/dist/src/embeddings/factory.d.ts +5 -3
- package/dist/src/embeddings/factory.d.ts.map +1 -1
- package/dist/src/embeddings/factory.js +7 -3
- package/dist/src/embeddings/factory.js.map +1 -1
- package/dist/src/embeddings/models.d.ts +1 -1
- package/dist/src/embeddings/models.d.ts.map +1 -1
- package/dist/src/embeddings/retry.js +1 -1
- package/dist/src/embeddings/retry.js.map +1 -1
- package/dist/src/embeddings/types.d.ts +6 -0
- package/dist/src/embeddings/types.d.ts.map +1 -1
- package/dist/src/embeddings/types.js +11 -0
- package/dist/src/embeddings/types.js.map +1 -1
- package/dist/src/events/pending.d.ts +1 -1
- package/dist/src/events/pending.js +1 -1
- package/dist/src/git/GitRunner.d.ts +110 -30
- package/dist/src/git/GitRunner.d.ts.map +1 -1
- package/dist/src/git/GitRunner.js +511 -199
- package/dist/src/git/GitRunner.js.map +1 -1
- package/dist/src/git/GitWatchRegistry.d.ts +41 -35
- package/dist/src/git/GitWatchRegistry.d.ts.map +1 -1
- package/dist/src/git/GitWatchRegistry.js +61 -79
- package/dist/src/git/GitWatchRegistry.js.map +1 -1
- package/dist/src/git/gitPlace.d.ts +61 -0
- package/dist/src/git/gitPlace.d.ts.map +1 -0
- package/dist/src/git/gitPlace.js +74 -0
- package/dist/src/git/gitPlace.js.map +1 -0
- package/dist/src/git/sourceGitControl.d.ts +33 -21
- package/dist/src/git/sourceGitControl.d.ts.map +1 -1
- package/dist/src/git/sourceGitControl.js +211 -95
- package/dist/src/git/sourceGitControl.js.map +1 -1
- package/dist/src/git/sourceGitStatus.js +1 -1
- package/dist/src/git/sourceGitStatus.js.map +1 -1
- package/dist/src/git/untrackedStats.js +1 -1
- package/dist/src/git/untrackedStats.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lifecycle.d.ts +9 -12
- package/dist/src/lifecycle.d.ts.map +1 -1
- package/dist/src/lifecycle.js +2 -1
- package/dist/src/lifecycle.js.map +1 -1
- package/dist/src/routes/approve.d.ts +1 -1
- package/dist/src/routes/approve.js +1 -1
- package/dist/src/routes/events.d.ts +1 -1
- package/dist/src/routes/events.js +1 -1
- package/dist/src/routes/git.d.ts +7 -7
- package/dist/src/routes/git.d.ts.map +1 -1
- package/dist/src/routes/git.js +201 -72
- package/dist/src/routes/git.js.map +1 -1
- package/dist/src/routes/health.d.ts +6 -6
- package/dist/src/routes/health.js +12 -12
- package/dist/src/routes/helpers/sourceNotConfigured.d.ts +1 -1
- package/dist/src/routes/helpers/sourceNotConfigured.js +1 -1
- package/dist/src/routes/helpers/uriGuard.d.ts +1 -1
- package/dist/src/routes/helpers/uriGuard.d.ts.map +1 -1
- package/dist/src/routes/helpers/uriGuard.js +3 -2
- package/dist/src/routes/helpers/uriGuard.js.map +1 -1
- package/dist/src/routes/helpers.d.ts +11 -4
- package/dist/src/routes/helpers.d.ts.map +1 -1
- package/dist/src/routes/helpers.js +13 -6
- package/dist/src/routes/helpers.js.map +1 -1
- package/dist/src/routes/list.d.ts +1 -1
- package/dist/src/routes/list.d.ts.map +1 -1
- package/dist/src/routes/list.js +3 -4
- package/dist/src/routes/list.js.map +1 -1
- package/dist/src/routes/pending.d.ts +4 -4
- package/dist/src/routes/pending.js +9 -9
- package/dist/src/routes/policies.d.ts +10 -8
- package/dist/src/routes/policies.d.ts.map +1 -1
- package/dist/src/routes/policies.js +31 -25
- package/dist/src/routes/policies.js.map +1 -1
- package/dist/src/routes/raw.d.ts +1 -1
- package/dist/src/routes/raw.d.ts.map +1 -1
- package/dist/src/routes/raw.js +66 -12
- package/dist/src/routes/raw.js.map +1 -1
- package/dist/src/routes/read.d.ts +1 -1
- package/dist/src/routes/read.js +1 -1
- package/dist/src/routes/search.d.ts +1 -1
- package/dist/src/routes/search.js +1 -1
- package/dist/src/routes/sources.d.ts +63 -6
- package/dist/src/routes/sources.d.ts.map +1 -1
- package/dist/src/routes/sources.js +494 -382
- package/dist/src/routes/sources.js.map +1 -1
- package/dist/src/routes/upload.d.ts +1 -1
- package/dist/src/routes/upload.js +1 -1
- package/dist/src/routes/write.d.ts +2 -2
- package/dist/src/routes/write.js +2 -2
- package/dist/src/services/BridgeService.d.ts +21 -35
- package/dist/src/services/BridgeService.d.ts.map +1 -1
- package/dist/src/services/BridgeService.js +42 -88
- package/dist/src/services/BridgeService.js.map +1 -1
- package/dist/src/services/FilesystemService.d.ts +4 -3
- package/dist/src/services/FilesystemService.d.ts.map +1 -1
- package/dist/src/services/FilesystemService.js +112 -34
- package/dist/src/services/FilesystemService.js.map +1 -1
- package/dist/src/services/FilesystemUiService.d.ts +4 -1
- package/dist/src/services/FilesystemUiService.d.ts.map +1 -1
- package/dist/src/services/FilesystemUiService.js +66 -25
- package/dist/src/services/FilesystemUiService.js.map +1 -1
- package/dist/src/services/SyncScheduler.d.ts +12 -4
- package/dist/src/services/SyncScheduler.d.ts.map +1 -1
- package/dist/src/services/SyncScheduler.js +37 -8
- package/dist/src/services/SyncScheduler.js.map +1 -1
- package/dist/src/services/baselineRepair.d.ts +13 -3
- package/dist/src/services/baselineRepair.d.ts.map +1 -1
- package/dist/src/services/baselineRepair.js +13 -3
- package/dist/src/services/baselineRepair.js.map +1 -1
- package/dist/src/services/declaredSources.d.ts +132 -43
- package/dist/src/services/declaredSources.d.ts.map +1 -1
- package/dist/src/services/declaredSources.js +118 -45
- package/dist/src/services/declaredSources.js.map +1 -1
- package/dist/src/store/dataFormats.d.ts +17 -2
- package/dist/src/store/dataFormats.d.ts.map +1 -1
- package/dist/src/store/dataFormats.js +18 -3
- package/dist/src/store/dataFormats.js.map +1 -1
- package/dist/src/sync/DeltaSyncRunner.d.ts.map +1 -1
- package/dist/src/sync/DeltaSyncRunner.js +144 -4
- package/dist/src/sync/DeltaSyncRunner.js.map +1 -1
- package/dist/src/sync/SyncJobQueue.d.ts +7 -2
- package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
- package/dist/src/sync/SyncJobQueue.js +16 -10
- package/dist/src/sync/SyncJobQueue.js.map +1 -1
- package/dist/src/sync/SyncWatchService.d.ts +21 -4
- package/dist/src/sync/SyncWatchService.d.ts.map +1 -1
- package/dist/src/sync/SyncWatchService.js +115 -10
- package/dist/src/sync/SyncWatchService.js.map +1 -1
- package/dist/src/sync/categoryInference.d.ts +1 -1
- package/dist/src/sync/categoryInference.js +1 -1
- package/dist/src/tools/execCtx.d.ts +2 -2
- package/dist/src/tools/execCtx.js +2 -2
- package/dist/src/tools/fs_read.d.ts.map +1 -1
- package/dist/src/tools/fs_read.js +5 -0
- package/dist/src/tools/fs_read.js.map +1 -1
- package/dist/src/usecases/admitSourceRoot.d.ts +65 -0
- package/dist/src/usecases/admitSourceRoot.d.ts.map +1 -0
- package/dist/src/usecases/admitSourceRoot.js +85 -0
- package/dist/src/usecases/admitSourceRoot.js.map +1 -0
- package/dist/src/usecases/browseSourceFolders.d.ts +85 -0
- package/dist/src/usecases/browseSourceFolders.d.ts.map +1 -0
- package/dist/src/usecases/browseSourceFolders.js +210 -0
- package/dist/src/usecases/browseSourceFolders.js.map +1 -0
- package/dist/src/usecases/createDeclaredSources.d.ts +13 -2
- package/dist/src/usecases/createDeclaredSources.d.ts.map +1 -1
- package/dist/src/usecases/createDeclaredSources.js +39 -0
- package/dist/src/usecases/createDeclaredSources.js.map +1 -1
- package/dist/src/usecases/embeddingBacklog.js +1 -1
- package/dist/src/usecases/embeddingBacklog.js.map +1 -1
- package/dist/src/usecases/list.d.ts.map +1 -1
- package/dist/src/usecases/list.js +83 -26
- package/dist/src/usecases/list.js.map +1 -1
- package/dist/src/usecases/listAttachableDevices.d.ts +13 -0
- package/dist/src/usecases/listAttachableDevices.d.ts.map +1 -0
- package/dist/src/usecases/listAttachableDevices.js +10 -0
- package/dist/src/usecases/listAttachableDevices.js.map +1 -0
- package/dist/src/usecases/listSourcePackages.d.ts.map +1 -1
- package/dist/src/usecases/listSourcePackages.js +2 -5
- package/dist/src/usecases/listSourcePackages.js.map +1 -1
- package/dist/src/usecases/purgeExcludedPoints.d.ts.map +1 -1
- package/dist/src/usecases/purgeExcludedPoints.js +3 -2
- package/dist/src/usecases/purgeExcludedPoints.js.map +1 -1
- package/dist/src/usecases/readFiles.d.ts.map +1 -1
- package/dist/src/usecases/readFiles.js +99 -1
- package/dist/src/usecases/readFiles.js.map +1 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.d.ts +1 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.d.ts.map +1 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.js +2 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.js.map +1 -1
- package/dist/src/usecases/revokePrincipal.d.ts +7 -5
- package/dist/src/usecases/revokePrincipal.d.ts.map +1 -1
- package/dist/src/usecases/revokePrincipal.js +29 -7
- package/dist/src/usecases/revokePrincipal.js.map +1 -1
- package/dist/src/usecases/scheduleSourceSync.d.ts +7 -0
- package/dist/src/usecases/scheduleSourceSync.d.ts.map +1 -1
- package/dist/src/usecases/scheduleSourceSync.js +6 -5
- package/dist/src/usecases/scheduleSourceSync.js.map +1 -1
- package/dist/src/usecases/syncPointWrites.d.ts +2 -0
- package/dist/src/usecases/syncPointWrites.d.ts.map +1 -1
- package/dist/src/usecases/syncPointWrites.js +5 -1
- package/dist/src/usecases/syncPointWrites.js.map +1 -1
- package/dist/src/usecases/triggerSourceSync.d.ts +46 -0
- package/dist/src/usecases/triggerSourceSync.d.ts.map +1 -0
- package/dist/src/usecases/triggerSourceSync.js +75 -0
- package/dist/src/usecases/triggerSourceSync.js.map +1 -0
- package/dist/src/usecases/uploadBinary.d.ts +2 -1
- package/dist/src/usecases/uploadBinary.d.ts.map +1 -1
- package/dist/src/usecases/uploadBinary.js +2 -2
- package/dist/src/usecases/uploadBinary.js.map +1 -1
- package/dist/src/usecases/vector/endpointGuard.d.ts +1 -1
- package/dist/src/usecases/vector/endpointGuard.js +1 -1
- package/dist/src/usecases/vectorMaintenance.js +1 -1
- package/dist/src/usecases/vectorMaintenance.js.map +1 -1
- package/dist/src/usecases/write/content.js +1 -1
- package/dist/src/vector/qdrantClient.d.ts +1 -1
- package/dist/src/vector/qdrantClient.js +1 -1
- package/dist/src/wiring.d.ts +3 -0
- package/dist/src/wiring.d.ts.map +1 -1
- package/dist/src/wiring.js +72 -6
- package/dist/src/wiring.js.map +1 -1
- package/dist/tools/fs_list.json +1 -1
- package/dist/tools/fs_read.json +1 -1
- package/dist/tools/fs_search.json +1 -1
- package/dist/tools/fs_write.json +1 -1
- package/instructions/brain-model.md +1 -1
- package/package.json +212 -114
- package/rules/brain-rules.md +2 -2
- package/skills/brain-start/SKILL.md +1 -1
- package/skills/connect-business-data/SKILL.md +3 -3
- package/skills/create-package/SKILL.md +26 -26
- package/skills/create-package/references/config-and-credentials.md +16 -13
- package/skills/create-package/references/connectors-and-uri-policies.md +39 -25
- package/skills/create-package/references/manifest-and-discovery.md +12 -12
- package/skills/create-package/references/runtime-and-build.md +19 -19
- package/skills/create-package/references/skills-and-context.md +36 -20
- package/skills/create-package/references/surfaces-and-design.md +16 -16
- package/skills/create-package/references/team-and-workflows.md +2 -2
- package/skills/create-package/references/test-and-ship.md +21 -21
- package/skills/create-package/references/tools-and-schemas.md +5 -5
- package/skills/create-package/scripts/{check-package.sh → check-package.mjs} +79 -65
- package/skills/create-package/scripts/{verify-loaded.sh → verify-loaded.mjs} +156 -162
- package/skills/git/SKILL.md +53 -51
- package/skills/manage-files/SKILL.md +22 -25
- package/skills/manage-sources/SKILL.md +128 -87
- package/skills/manage-uri-policy/SKILL.md +18 -15
- package/skills/organize/SKILL.md +1 -1
- package/skills/sync/SKILL.md +3 -3
- package/tools/fs_list.json +1 -1
- package/tools/fs_read.json +1 -1
- package/tools/fs_search.json +1 -1
- package/tools/fs_write.json +1 -1
- package/workflows/sources-digest.json +1 -1
- package/dist/src/connectors/LocalDiskConnector.d.ts +0 -171
- package/dist/src/connectors/LocalDiskConnector.d.ts.map +0 -1
- package/dist/src/connectors/LocalDiskConnector.js +0 -1233
- package/dist/src/connectors/LocalDiskConnector.js.map +0 -1
- package/docs/drive-overview.md +0 -59
- package/skills/manage-files/scripts/copy.sh +0 -7
- package/skills/manage-files/scripts/create.sh +0 -7
- package/skills/manage-files/scripts/mkdir.sh +0 -7
- package/skills/manage-files/scripts/modify.sh +0 -7
- package/skills/manage-files/scripts/upload.sh +0 -16
- package/skills/manage-files/scripts/write.sh +0 -29
- package/skills/manage-sources/scripts/reembed.sh +0 -23
package/dist/src/domain/mime.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Two jobs live here, and they are deliberately different layers:
|
|
5
5
|
*
|
|
6
6
|
* 1. **Resolution** (`inferMimeTypeFromFilename`, `looksTextByMime`) — what a
|
|
7
|
-
* file's type honestly IS
|
|
8
|
-
*
|
|
7
|
+
* file's type honestly IS, so the serve path and the store path answer from
|
|
8
|
+
* the same table. The extension tables themselves are the kernel's
|
|
9
|
+
* (`@neuralis/package-system/web-common`), re-exported below.
|
|
9
10
|
* 2. **Response policy** (`classifyResponseMime`, `buildRawResponseHeaders`) —
|
|
10
11
|
* what the byte lane is allowed to tell a BROWSER to do with those bytes.
|
|
11
12
|
*
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
*
|
|
17
18
|
* ## The rule the policy encodes
|
|
18
19
|
*
|
|
19
|
-
* A member with `
|
|
20
|
+
* A member with `files.write` can put arbitrary bytes at a URI another member
|
|
20
21
|
* can read. If the byte lane then serves those bytes as a DOCUMENT on the app
|
|
21
22
|
* origin (`content-type: image/svg+xml` + `content-disposition: inline`), the
|
|
22
23
|
* document's script runs with the READER's session. That is a stored-XSS
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
* multipart part type), by the write engine's create lane (the caller's
|
|
68
69
|
* `fields.metadata`), and by its `fields` verb (a metadata PATCH — historically
|
|
69
70
|
* the least guarded of the three, because the deleted `modify` route excluded
|
|
70
|
-
* `set_fields` from the uri-policy check). All three are `
|
|
71
|
+
* `set_fields` from the uri-policy check). All three are `files.write`. `normalizeStoredMimeType` and
|
|
71
72
|
* `normalizeNodeMetadataMime` below close all three; each one left open keeps
|
|
72
73
|
* the classification input caller-controlled. The first round of this fix closed
|
|
73
74
|
* only ONE, the architect's review found the second, and the live run found the
|
|
@@ -79,8 +80,10 @@
|
|
|
79
80
|
* `FilesystemUiService` excludes the active-document class at that one site for
|
|
80
81
|
* exactly this reason — the body is JSON and the wire should say so.
|
|
81
82
|
*/
|
|
82
|
-
import { matchesMagic, MIN_MAGIC_BYTES } from '@neuralis/package-system/web-common';
|
|
83
|
+
import { inferMimeTypeFromFilename, matchesMagic, MIN_MAGIC_BYTES } from '@neuralis/package-system/web-common';
|
|
83
84
|
import { sanitizeFilename } from './paths.js';
|
|
85
|
+
// The extension tables are the kernel's (`web-common/fileMime.ts`) — agent-core's device connector reads them too.
|
|
86
|
+
export { binaryMimeTypeForPath, inferMimeTypeFromFilename } from '@neuralis/package-system/web-common';
|
|
84
87
|
/** Longest mime essence we will echo; anything longer is treated as garbage. */
|
|
85
88
|
const MAX_MIME_ESSENCE_LENGTH = 255;
|
|
86
89
|
/** `type/subtype` in RFC 9110 token characters, nothing else. */
|
|
@@ -89,51 +92,6 @@ export function looksTextByMime(mimeType) {
|
|
|
89
92
|
const mime = String(mimeType || '').toLowerCase();
|
|
90
93
|
return mime.startsWith('text/') || mime === 'application/json' || mime.endsWith('+json');
|
|
91
94
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Extension → mime, for files whose stored metadata carries no type.
|
|
94
|
-
*
|
|
95
|
-
* The five document extensions at the end are NOT decoration: they make the
|
|
96
|
-
* extension agree with `classifyResponseMime`'s active-document set, so an
|
|
97
|
-
* `.html` or `.xml` file reports what it is instead of `application/octet-stream`
|
|
98
|
-
* and is classified on its merits. Both land on `attachment` either way — this
|
|
99
|
-
* only removes a lie from the wire.
|
|
100
|
-
*/
|
|
101
|
-
export function inferMimeTypeFromFilename(filename) {
|
|
102
|
-
const lower = filename.toLowerCase();
|
|
103
|
-
if (lower.endsWith('.png'))
|
|
104
|
-
return 'image/png';
|
|
105
|
-
if (lower.endsWith('.jpg') || lower.endsWith('.jpeg'))
|
|
106
|
-
return 'image/jpeg';
|
|
107
|
-
if (lower.endsWith('.webp'))
|
|
108
|
-
return 'image/webp';
|
|
109
|
-
if (lower.endsWith('.gif'))
|
|
110
|
-
return 'image/gif';
|
|
111
|
-
if (lower.endsWith('.svg'))
|
|
112
|
-
return 'image/svg+xml';
|
|
113
|
-
if (lower.endsWith('.mp4'))
|
|
114
|
-
return 'video/mp4';
|
|
115
|
-
if (lower.endsWith('.webm'))
|
|
116
|
-
return 'video/webm';
|
|
117
|
-
if (lower.endsWith('.mp3'))
|
|
118
|
-
return 'audio/mpeg';
|
|
119
|
-
if (lower.endsWith('.wav'))
|
|
120
|
-
return 'audio/wav';
|
|
121
|
-
if (lower.endsWith('.json'))
|
|
122
|
-
return 'application/json; charset=utf-8';
|
|
123
|
-
if (lower.endsWith('.md'))
|
|
124
|
-
return 'text/markdown; charset=utf-8';
|
|
125
|
-
if (lower.endsWith('.txt'))
|
|
126
|
-
return 'text/plain; charset=utf-8';
|
|
127
|
-
if (lower.endsWith('.html') || lower.endsWith('.htm'))
|
|
128
|
-
return 'text/html; charset=utf-8';
|
|
129
|
-
if (lower.endsWith('.xhtml'))
|
|
130
|
-
return 'application/xhtml+xml';
|
|
131
|
-
if (lower.endsWith('.xml'))
|
|
132
|
-
return 'text/xml; charset=utf-8';
|
|
133
|
-
if (lower.endsWith('.xsl') || lower.endsWith('.xslt'))
|
|
134
|
-
return 'application/xslt+xml';
|
|
135
|
-
return 'application/octet-stream';
|
|
136
|
-
}
|
|
137
95
|
/**
|
|
138
96
|
* Lowercase `type/subtype`, parameters dropped, syntactically validated.
|
|
139
97
|
* Returns `null` for anything absent, over-long or not token-shaped — the
|
|
@@ -252,9 +210,10 @@ export function buildRawResponseHeaders(input) {
|
|
|
252
210
|
*
|
|
253
211
|
* **SCOPE, measured live — the magic-byte check governs the STORED value, and
|
|
254
212
|
* on a non-brain source it does NOT reach the wire.** `loadRawBytes` returns
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
213
|
+
* the connector's type for `sourceKind !== 'brain'` whenever the connector can
|
|
214
|
+
* tell (anything but `application/octet-stream`, the contract's "cannot
|
|
215
|
+
* tell"), so the local connector's own extension-derived type wins over the
|
|
216
|
+
* persisted metadata at serve time. HTML bytes stored as `application/octet-stream` under the name
|
|
258
217
|
* `x.png` are therefore SERVED `image/png`. That is bounded and not a hole: the
|
|
259
218
|
* classification still runs on the extension, so `.svg`/`.html`/`.xml` stay
|
|
260
219
|
* `attachment`, and a mislabelled raster is inert under the globally-present
|
|
@@ -280,7 +239,7 @@ export function normalizeStoredMimeType(declared, filename, bytes) {
|
|
|
280
239
|
*
|
|
281
240
|
* `metadata.mimeType` has THREE writers — the byte lane (the multipart part
|
|
282
241
|
* type), the write engine's create lane and its `fields` verb. All are
|
|
283
|
-
* `
|
|
242
|
+
* `files.write`, a MEMBER default on the seeded `data` source, and the field is
|
|
284
243
|
* the FIRST thing `loadRawBytes` reads — i.e. the input the byte lane's
|
|
285
244
|
* classifier rules on. Normalizing only one writer leaves that input
|
|
286
245
|
* caller-controlled, so all three go through here. The `fields` verb
|
|
@@ -300,52 +259,4 @@ export function normalizeNodeMetadataMime(metadata, filename) {
|
|
|
300
259
|
bag.mimeType = normalizeStoredMimeType(typeof bag.mimeType === 'string' ? bag.mimeType : undefined, filename);
|
|
301
260
|
return bag;
|
|
302
261
|
}
|
|
303
|
-
const BINARY_READ_MIME_BY_EXTENSION = new Map([
|
|
304
|
-
['.wasm', 'application/wasm'],
|
|
305
|
-
['.png', 'image/png'],
|
|
306
|
-
['.jpg', 'image/jpeg'],
|
|
307
|
-
['.jpeg', 'image/jpeg'],
|
|
308
|
-
['.gif', 'image/gif'],
|
|
309
|
-
['.webp', 'image/webp'],
|
|
310
|
-
['.ico', 'image/x-icon'],
|
|
311
|
-
['.bmp', 'image/bmp'],
|
|
312
|
-
['.mp4', 'video/mp4'],
|
|
313
|
-
['.webm', 'video/webm'],
|
|
314
|
-
['.avi', 'video/x-msvideo'],
|
|
315
|
-
['.mov', 'video/quicktime'],
|
|
316
|
-
['.mkv', 'video/x-matroska'],
|
|
317
|
-
['.mp3', 'audio/mpeg'],
|
|
318
|
-
['.wav', 'audio/wav'],
|
|
319
|
-
['.ogg', 'audio/ogg'],
|
|
320
|
-
['.flac', 'audio/flac'],
|
|
321
|
-
['.aac', 'audio/aac'],
|
|
322
|
-
['.m4a', 'audio/mp4'],
|
|
323
|
-
['.zip', 'application/zip'],
|
|
324
|
-
['.tar', 'application/x-tar'],
|
|
325
|
-
['.gz', 'application/gzip'],
|
|
326
|
-
['.bz2', 'application/x-bzip2'],
|
|
327
|
-
['.7z', 'application/x-7z-compressed'],
|
|
328
|
-
['.rar', 'application/vnd.rar'],
|
|
329
|
-
['.pdf', 'application/pdf'],
|
|
330
|
-
['.doc', 'application/msword'],
|
|
331
|
-
['.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
|
|
332
|
-
['.xls', 'application/vnd.ms-excel'],
|
|
333
|
-
['.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
|
|
334
|
-
['.ppt', 'application/vnd.ms-powerpoint'],
|
|
335
|
-
['.pptx', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'],
|
|
336
|
-
['.exe', 'application/octet-stream'],
|
|
337
|
-
['.dll', 'application/octet-stream'],
|
|
338
|
-
['.so', 'application/octet-stream'],
|
|
339
|
-
['.dylib', 'application/octet-stream'],
|
|
340
|
-
['.ttf', 'font/ttf'],
|
|
341
|
-
['.otf', 'font/otf'],
|
|
342
|
-
['.woff', 'font/woff'],
|
|
343
|
-
['.woff2', 'font/woff2'],
|
|
344
|
-
['.eot', 'application/vnd.ms-fontobject'],
|
|
345
|
-
]);
|
|
346
|
-
export function binaryMimeTypeForPath(filePath) {
|
|
347
|
-
const name = filePath.slice(filePath.lastIndexOf('/') + 1);
|
|
348
|
-
const dot = name.lastIndexOf('.');
|
|
349
|
-
return dot > 0 ? BINARY_READ_MIME_BY_EXTENSION.get(name.slice(dot).toLowerCase()) : undefined;
|
|
350
|
-
}
|
|
351
262
|
//# sourceMappingURL=mime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mime.js","sourceRoot":"","sources":["../../../src/domain/mime.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mime.js","sourceRoot":"","sources":["../../../src/domain/mime.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/domain/paths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/domain/paths.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAYxD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAUrD;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE;IAAE,YAAY,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GACjD,MAAM,GAAG,SAAS,CAUpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D"}
|
package/dist/src/domain/paths.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hasDotDotSegment } from '@neuralis/package-system/paths';
|
|
1
2
|
import { BrainError } from './BrainError.js';
|
|
2
3
|
export function normalizeFolderPath(raw) {
|
|
3
4
|
const value = typeof raw === 'string' ? raw.trim() : '';
|
|
@@ -5,8 +6,8 @@ export function normalizeFolderPath(raw) {
|
|
|
5
6
|
return '/';
|
|
6
7
|
const withLeading = value.startsWith('/') ? value : `/${value}`;
|
|
7
8
|
const collapsed = withLeading.replace(/\/{2,}/g, '/');
|
|
8
|
-
if (collapsed
|
|
9
|
-
throw new BrainError({ code: 'INPUT_ERROR', message: 'folder_path may not contain ..', status: 400 });
|
|
9
|
+
if (hasDotDotSegment(collapsed)) {
|
|
10
|
+
throw new BrainError({ code: 'INPUT_ERROR', message: 'folder_path may not contain a .. segment', status: 400 });
|
|
10
11
|
}
|
|
11
12
|
if (collapsed.length > 512) {
|
|
12
13
|
throw new BrainError({ code: 'INPUT_ERROR', message: 'folder_path is too long', status: 400 });
|
|
@@ -20,7 +21,8 @@ export function sanitizeFilename(raw) {
|
|
|
20
21
|
const cleaned = value.replace(/\0/g, '').replace(/[\\]/g, '/');
|
|
21
22
|
const base = cleaned.split('/').pop() ?? '';
|
|
22
23
|
const safe = base.replace(/[^a-zA-Z0-9._ -]/g, '-').replace(/\s+/g, ' ').trim();
|
|
23
|
-
|
|
24
|
+
// `.` and `..` name the folder itself or its parent, never a file.
|
|
25
|
+
if (!safe || safe === '.' || safe === '..')
|
|
24
26
|
return '';
|
|
25
27
|
if (safe.length > 200)
|
|
26
28
|
return safe.slice(0, 200);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/domain/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,CAAC;IACvB,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;IAChE,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACtD,IAAI,
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/domain/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,8 +17,8 @@ export declare function scopeAccessCtxFromExecution(ctx: ExecutionContext): Scop
|
|
|
17
17
|
* Synthesize the per-record owner scope used by the pending-change floor.
|
|
18
18
|
* `canAccessScope` does NOT isolate per-user on a project-kind source (true for
|
|
19
19
|
* every member), so a `{kind:'user', userId}` scope makes the ONE shared
|
|
20
|
-
* predicate yield exactly "own record OR a `
|
|
21
|
-
* `
|
|
20
|
+
* predicate yield exactly "own record OR a `files.readOthers` /
|
|
21
|
+
* `files.writeOthers` HOLDER" — the grant decides, not the role NAME (D-A removed
|
|
22
22
|
* `canAccessScope`'s role-name conjunct, so a custom role granted the feature
|
|
23
23
|
* passes exactly like the seeded `owner`/`admin`). The `' __no_owner__'`
|
|
24
24
|
* sentinel (a leading space ⇒ an impossible real userId) fences an ownerless
|
|
@@ -23,8 +23,8 @@ export function scopeAccessCtxFromExecution(ctx) {
|
|
|
23
23
|
* Synthesize the per-record owner scope used by the pending-change floor.
|
|
24
24
|
* `canAccessScope` does NOT isolate per-user on a project-kind source (true for
|
|
25
25
|
* every member), so a `{kind:'user', userId}` scope makes the ONE shared
|
|
26
|
-
* predicate yield exactly "own record OR a `
|
|
27
|
-
* `
|
|
26
|
+
* predicate yield exactly "own record OR a `files.readOthers` /
|
|
27
|
+
* `files.writeOthers` HOLDER" — the grant decides, not the role NAME (D-A removed
|
|
28
28
|
* `canAccessScope`'s role-name conjunct, so a custom role granted the feature
|
|
29
29
|
* passes exactly like the seeded `owner`/`admin`). The `' __no_owner__'`
|
|
30
30
|
* sentinel (a leading space ⇒ an impossible real userId) fences an ownerless
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Credentials never live in `connection.config`; they live in
|
|
9
9
|
* `CredentialStore`, keyed on `(projectId, source)`.
|
|
10
10
|
*/
|
|
11
|
-
import type { ConnectorHierarchicalPermissions, SourceScope, SourceKindRegistry } from '@neuralis/package-system/contracts';
|
|
11
|
+
import type { ConnectorHierarchicalPermissions, SourceScope, ScopeOrigin, SourceKindRegistry } from '@neuralis/package-system/contracts';
|
|
12
12
|
/**
|
|
13
13
|
* Open-shape source connection. Every source connector package declares
|
|
14
14
|
* its `config` schema via `PackageConnector.configSchema` — the loader
|
|
@@ -201,19 +201,21 @@ export type SourceConfig = {
|
|
|
201
201
|
*/
|
|
202
202
|
execGrantRepairVersion?: number;
|
|
203
203
|
/**
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* `
|
|
214
|
-
* '
|
|
204
|
+
* The folders of this source that are watched for PACKAGES (the package-LOAD
|
|
205
|
+
* axis): each entry is a path RELATIVE to the source root (`''` = the whole
|
|
206
|
+
* source, `tools/pkgs` = that folder), and each is scanned the way the project
|
|
207
|
+
* `_packages/` drop-zone is — file-watched, loaded under the same guards
|
|
208
|
+
* (`untrusted`, reserved-id ban, trust-escalation guard; DISCOVERY IS NOT
|
|
209
|
+
* EXECUTION). ADDITIVE and orthogonal to the markdown source-package path.
|
|
210
|
+
* Deny-by-default (absent or empty ⇒ none). Valid on the `host` kind only
|
|
211
|
+
* (brain/webtop have no filesystem to scan); the WRITE is owner/admin-effective
|
|
212
|
+
* on create and PATCH (it is a code-LOAD surface). Distinct from
|
|
213
|
+
* `sync.alwaysActive` / `resolveAlwaysActive` (the SYNC-axis pin). A device
|
|
214
|
+
* folder's packages load from the app's own disk when the device is this
|
|
215
|
+
* machine (a loopback device, a native host), and over the device link
|
|
216
|
+
* otherwise — read, never copied here.
|
|
215
217
|
*/
|
|
216
|
-
|
|
218
|
+
packageFolders?: string[];
|
|
217
219
|
createdAt: string;
|
|
218
220
|
updatedAt: string;
|
|
219
221
|
createdBy: string;
|
|
@@ -232,22 +234,45 @@ export type ValidationResult = {
|
|
|
232
234
|
*/
|
|
233
235
|
export declare function setSourceKindRegistry(registry: SourceKindRegistry | null): void;
|
|
234
236
|
export declare function validateSourceConfig(cfg: unknown): ValidationResult;
|
|
237
|
+
/**
|
|
238
|
+
* `packageFolders`: a list of source-RELATIVE folders — each the kernel's ONE
|
|
239
|
+
* `isPackageFolderPath` (`''` for the whole source, or `/`-separated segments
|
|
240
|
+
* with no `.`/`..`, no empty segment, no backslash, no leading slash or drive:
|
|
241
|
+
* an absolute path would name a folder outside the source, the one thing a
|
|
242
|
+
* package folder must never do), at most `MAX_PACKAGE_FOLDERS`, no duplicates;
|
|
243
|
+
* on the `host` kind only.
|
|
244
|
+
*/
|
|
245
|
+
export declare function validatePackageFolders(value: unknown, connection: unknown): string[];
|
|
235
246
|
/**
|
|
236
247
|
* Resolve the effective `enabled` value for a config, defaulting `undefined`
|
|
237
248
|
* to `true`. The string `'auto'` is returned as-is; the caller must consult
|
|
238
249
|
* the connector's `isRunning(slug)` probe to decide.
|
|
239
250
|
*/
|
|
240
|
-
export declare function resolveEnabledState(config: SourceConfig): SourceEnabledState;
|
|
251
|
+
export declare function resolveEnabledState(config: Pick<SourceConfig, 'enabled'>): SourceEnabledState;
|
|
241
252
|
/**
|
|
242
|
-
* The `users[]`
|
|
243
|
-
*
|
|
244
|
-
*
|
|
253
|
+
* The two grant-only subject rules — `users[]` (kernel `validatePolicyUsersRule`)
|
|
254
|
+
* and `priority`, the caller's role priority, n or stronger (kernel
|
|
255
|
+
* `validatePolicyPriorityRule`) — over every path rule of a CALLER-supplied
|
|
256
|
+
* permissions payload: the route ingress (create, PATCH, the policy patch) AND
|
|
257
|
+
* the service floor below it (`BridgeService` create/update). Both are SHAPE
|
|
258
|
+
* rules, so they need no session. Deliberately NOT part of
|
|
245
259
|
* `validateSourceConfig`: the store's READERS run that too, and there one
|
|
246
260
|
* invalid persisted row would drop the whole source (every data route 404s,
|
|
247
261
|
* the shell gate denies everything), while the evaluator already makes such a
|
|
248
262
|
* row match nothing.
|
|
249
263
|
*/
|
|
250
|
-
export declare function
|
|
264
|
+
export declare function validatePermissionsGrantOnlyRules(perms: unknown): string[];
|
|
265
|
+
/**
|
|
266
|
+
* The role NAMES of a CALLER-supplied payload's path rules: every `roles[]`
|
|
267
|
+
* entry is a role of the caller's project (`SessionContext.rolePriorities`;
|
|
268
|
+
* without a map, only the built-in names). The only subject check that needs a
|
|
269
|
+
* session — `priority` is a number and its shape rule lives in
|
|
270
|
+
* {@link validatePermissionsGrantOnlyRules}. A name the stored config already carries
|
|
271
|
+
* (`existing`) passes, so resending a rule whose role was deleted later is not
|
|
272
|
+
* blocked — that row matches nobody. Write ingress only, for the reason
|
|
273
|
+
* {@link validatePermissionsGrantOnlyRules} gives.
|
|
274
|
+
*/
|
|
275
|
+
export declare function validatePermissionsSubjectRules(perms: unknown, rolePriorities: Record<string, number> | undefined, existing?: ConnectorHierarchicalPermissions | null): string[];
|
|
251
276
|
/**
|
|
252
277
|
* Effective `alwaysActive` pin: explicit value wins; package-content sources
|
|
253
278
|
* (`data`, `packages`) are pinned by default.
|
|
@@ -334,7 +359,7 @@ export declare class SourceDisabledError extends Error {
|
|
|
334
359
|
* reader sees, including sources attached long before it shipped. (The declared
|
|
335
360
|
* `seed:'auto'` sources are a deliberate exception — `repairDeclaredSources`
|
|
336
361
|
* backfills their blank descriptions once per repair version, so the persisted
|
|
337
|
-
* config of a
|
|
362
|
+
* config of a native source is authored, not empty. This chain covers the
|
|
338
363
|
* remainder: hand-added sources, and any description a human has cleared.)
|
|
339
364
|
*
|
|
340
365
|
* Order: what the owner wrote > what the package DECLARED for this source >
|
|
@@ -347,4 +372,12 @@ export declare function resolveSourceDescription(input: {
|
|
|
347
372
|
declaredDescription?: string | null | undefined;
|
|
348
373
|
kindDescription?: string | null | undefined;
|
|
349
374
|
}): string | null;
|
|
375
|
+
/**
|
|
376
|
+
* The plane a stored source's scope lives on — `canAccessScope`'s `origin`. A
|
|
377
|
+
* USER-scope source on a device serves its owner alone, so every gate that
|
|
378
|
+
* reads a source config's `scope` passes this; a `recordOwnerScope` gate has
|
|
379
|
+
* no connection and passes nothing (`test/domain/scopeOriginSweep.test.ts`
|
|
380
|
+
* counts both kinds).
|
|
381
|
+
*/
|
|
382
|
+
export declare function sourceScopeOrigin(connection: SourceConnection): ScopeOrigin;
|
|
350
383
|
//# sourceMappingURL=sourceConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sourceConfig.d.ts","sourceRoot":"","sources":["../../../src/domain/sourceConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,gCAAgC,EAChC,WAAW,
|
|
1
|
+
{"version":3,"file":"sourceConfig.d.ts","sourceRoot":"","sources":["../../../src/domain/sourceConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* - Credentials never live in `connection.config`; they live in
|
|
9
9
|
* `CredentialStore`, keyed on `(projectId, source)`.
|
|
10
10
|
*/
|
|
11
|
-
import { validatePolicyFloorRule, validatePolicyUsersRule } from '@neuralis/package-system/policies';
|
|
12
|
-
import {
|
|
11
|
+
import { validatePolicyFloorRule, validatePolicyPriorityRule, validatePolicyUsersRule } from '@neuralis/package-system/policies';
|
|
12
|
+
import { BUILTIN_ROLE_PRIORITY } from '@neuralis/package-system/access';
|
|
13
|
+
import { HOST_SOURCE_KIND, MAX_PACKAGE_FOLDERS, isPackageFolderPath, isSourceScope, sourcePlane } from '@neuralis/package-system/contracts';
|
|
13
14
|
const SOURCE_PATTERN = /^[a-z][a-z0-9-]{0,199}$/;
|
|
14
15
|
let sourceKindRegistry = null;
|
|
15
16
|
/**
|
|
@@ -49,20 +50,57 @@ export function validateSourceConfig(cfg) {
|
|
|
49
50
|
errors.push('enabled must be a boolean or "auto" if provided.');
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
|
-
if (c.
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
if (c.packageFolders !== undefined) {
|
|
54
|
+
errors.push(...validatePackageFolders(c.packageFolders, c.connection));
|
|
55
|
+
}
|
|
56
|
+
errors.push(...validateFolderTransport(c.connection));
|
|
57
|
+
return errors.length === 0 ? { ok: true } : { ok: false, errors };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `packageFolders`: a list of source-RELATIVE folders — each the kernel's ONE
|
|
61
|
+
* `isPackageFolderPath` (`''` for the whole source, or `/`-separated segments
|
|
62
|
+
* with no `.`/`..`, no empty segment, no backslash, no leading slash or drive:
|
|
63
|
+
* an absolute path would name a folder outside the source, the one thing a
|
|
64
|
+
* package folder must never do), at most `MAX_PACKAGE_FOLDERS`, no duplicates;
|
|
65
|
+
* on the `host` kind only.
|
|
66
|
+
*/
|
|
67
|
+
export function validatePackageFolders(value, connection) {
|
|
68
|
+
if (!Array.isArray(value))
|
|
69
|
+
return ['packageFolders must be an array of folder paths if provided.'];
|
|
70
|
+
const errors = [];
|
|
71
|
+
if (value.length > MAX_PACKAGE_FOLDERS)
|
|
72
|
+
errors.push(`packageFolders holds at most ${MAX_PACKAGE_FOLDERS} folders.`);
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
for (const entry of value) {
|
|
75
|
+
if (!isPackageFolderPath(entry)) {
|
|
76
|
+
errors.push('packageFolders entries must be folders relative to the source root ("" for the whole source), without "." or ".." segments.');
|
|
77
|
+
break;
|
|
55
78
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const kind = c.connection?.kind;
|
|
60
|
-
if (kind !== 'local') {
|
|
61
|
-
errors.push('recognizesPackages may only be true when connection.kind is "local".');
|
|
62
|
-
}
|
|
79
|
+
if (seen.has(entry)) {
|
|
80
|
+
errors.push('packageFolders must not repeat a folder.');
|
|
81
|
+
break;
|
|
63
82
|
}
|
|
83
|
+
seen.add(entry);
|
|
64
84
|
}
|
|
65
|
-
|
|
85
|
+
const kind = connection?.kind;
|
|
86
|
+
if (value.length > 0 && kind !== HOST_SOURCE_KIND) {
|
|
87
|
+
errors.push(`packageFolders may only be set when connection.kind is "${HOST_SOURCE_KIND}".`);
|
|
88
|
+
}
|
|
89
|
+
return errors;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The folder kind's device transport: a stored `device` makes `root` a path ON
|
|
93
|
+
* that device, so it must be absolute there (`/…`, or `C:\…` on a Windows
|
|
94
|
+
* device). The kind schema already refuses `device` beside `hostRoot`.
|
|
95
|
+
*/
|
|
96
|
+
function validateFolderTransport(connection) {
|
|
97
|
+
const c = connection;
|
|
98
|
+
if (c?.kind !== HOST_SOURCE_KIND || !c.config || sourcePlane(HOST_SOURCE_KIND, c.config) !== 'device')
|
|
99
|
+
return [];
|
|
100
|
+
const root = c.config.root;
|
|
101
|
+
return typeof root === 'string' && /^(\/|[A-Za-z]:[\\/])/.test(root)
|
|
102
|
+
? []
|
|
103
|
+
: ['connection.config.root must be an absolute path on the device when connection.config.device is set.'];
|
|
66
104
|
}
|
|
67
105
|
/**
|
|
68
106
|
* Resolve the effective `enabled` value for a config, defaulting `undefined`
|
|
@@ -172,19 +210,55 @@ function validateHierarchicalPermissions(perms) {
|
|
|
172
210
|
return errors;
|
|
173
211
|
}
|
|
174
212
|
/**
|
|
175
|
-
* The `users[]`
|
|
176
|
-
*
|
|
177
|
-
*
|
|
213
|
+
* The two grant-only subject rules — `users[]` (kernel `validatePolicyUsersRule`)
|
|
214
|
+
* and `priority`, the caller's role priority, n or stronger (kernel
|
|
215
|
+
* `validatePolicyPriorityRule`) — over every path rule of a CALLER-supplied
|
|
216
|
+
* permissions payload: the route ingress (create, PATCH, the policy patch) AND
|
|
217
|
+
* the service floor below it (`BridgeService` create/update). Both are SHAPE
|
|
218
|
+
* rules, so they need no session. Deliberately NOT part of
|
|
178
219
|
* `validateSourceConfig`: the store's READERS run that too, and there one
|
|
179
220
|
* invalid persisted row would drop the whole source (every data route 404s,
|
|
180
221
|
* the shell gate denies everything), while the evaluator already makes such a
|
|
181
222
|
* row match nothing.
|
|
182
223
|
*/
|
|
183
|
-
export function
|
|
224
|
+
export function validatePermissionsGrantOnlyRules(perms) {
|
|
225
|
+
const paths = perms?.paths;
|
|
226
|
+
if (!Array.isArray(paths))
|
|
227
|
+
return [];
|
|
228
|
+
return paths.flatMap((rule, i) => [...validatePolicyUsersRule(rule), ...validatePolicyPriorityRule(rule)].map((error) => `permissions.paths[${i}].${error}`));
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* The role NAMES of a CALLER-supplied payload's path rules: every `roles[]`
|
|
232
|
+
* entry is a role of the caller's project (`SessionContext.rolePriorities`;
|
|
233
|
+
* without a map, only the built-in names). The only subject check that needs a
|
|
234
|
+
* session — `priority` is a number and its shape rule lives in
|
|
235
|
+
* {@link validatePermissionsGrantOnlyRules}. A name the stored config already carries
|
|
236
|
+
* (`existing`) passes, so resending a rule whose role was deleted later is not
|
|
237
|
+
* blocked — that row matches nobody. Write ingress only, for the reason
|
|
238
|
+
* {@link validatePermissionsGrantOnlyRules} gives.
|
|
239
|
+
*/
|
|
240
|
+
export function validatePermissionsSubjectRules(perms, rolePriorities, existing) {
|
|
184
241
|
const paths = perms?.paths;
|
|
185
242
|
if (!Array.isArray(paths))
|
|
186
243
|
return [];
|
|
187
|
-
|
|
244
|
+
const carried = new Set((existing?.paths ?? []).flatMap((rule) => rule.roles ?? []));
|
|
245
|
+
const known = (name) => carried.has(name)
|
|
246
|
+
|| (rolePriorities ? Object.hasOwn(rolePriorities, name) : Object.hasOwn(BUILTIN_ROLE_PRIORITY, name));
|
|
247
|
+
return paths.flatMap((rule, i) => {
|
|
248
|
+
if (!rule || typeof rule !== 'object' || Array.isArray(rule))
|
|
249
|
+
return [];
|
|
250
|
+
const record = rule;
|
|
251
|
+
const errors = [];
|
|
252
|
+
if (Array.isArray(record.roles)) {
|
|
253
|
+
for (const name of record.roles) {
|
|
254
|
+
if (typeof name !== 'string' || name === '')
|
|
255
|
+
errors.push('roles entries must be non-empty role names.');
|
|
256
|
+
else if (!known(name))
|
|
257
|
+
errors.push(`roles names "${name}", which is not a role of this project.`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return errors.map((error) => `permissions.paths[${i}].${error}`);
|
|
261
|
+
});
|
|
188
262
|
}
|
|
189
263
|
const MEDIA_LANE_KEYS = ['images', 'pdf', 'video', 'audio'];
|
|
190
264
|
function validateSyncConfig(sync) {
|
|
@@ -376,7 +450,7 @@ export class SourceDisabledError extends Error {
|
|
|
376
450
|
* reader sees, including sources attached long before it shipped. (The declared
|
|
377
451
|
* `seed:'auto'` sources are a deliberate exception — `repairDeclaredSources`
|
|
378
452
|
* backfills their blank descriptions once per repair version, so the persisted
|
|
379
|
-
* config of a
|
|
453
|
+
* config of a native source is authored, not empty. This chain covers the
|
|
380
454
|
* remainder: hand-added sources, and any description a human has cleared.)
|
|
381
455
|
*
|
|
382
456
|
* Order: what the owner wrote > what the package DECLARED for this source >
|
|
@@ -394,4 +468,14 @@ export function resolveSourceDescription(input) {
|
|
|
394
468
|
}
|
|
395
469
|
return null;
|
|
396
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* The plane a stored source's scope lives on — `canAccessScope`'s `origin`. A
|
|
473
|
+
* USER-scope source on a device serves its owner alone, so every gate that
|
|
474
|
+
* reads a source config's `scope` passes this; a `recordOwnerScope` gate has
|
|
475
|
+
* no connection and passes nothing (`test/domain/scopeOriginSweep.test.ts`
|
|
476
|
+
* counts both kinds).
|
|
477
|
+
*/
|
|
478
|
+
export function sourceScopeOrigin(connection) {
|
|
479
|
+
return { plane: sourcePlane(connection.kind, connection.config) };
|
|
480
|
+
}
|
|
397
481
|
//# sourceMappingURL=sourceConfig.js.map
|