@aigne/aos 0.2.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/LICENSE.md +26 -0
- package/dist/agent-dsl.cjs +116 -0
- package/dist/agent-dsl.d.cts +31 -0
- package/dist/agent-dsl.d.cts.map +1 -0
- package/dist/agent-dsl.d.mts +31 -0
- package/dist/agent-dsl.d.mts.map +1 -0
- package/dist/agent-dsl.mjs +115 -0
- package/dist/agent-dsl.mjs.map +1 -0
- package/dist/arc-compat.cjs +125 -0
- package/dist/arc-compat.d.cts +17 -0
- package/dist/arc-compat.d.cts.map +1 -0
- package/dist/arc-compat.d.mts +17 -0
- package/dist/arc-compat.d.mts.map +1 -0
- package/dist/arc-compat.mjs +123 -0
- package/dist/arc-compat.mjs.map +1 -0
- package/dist/auto-surface/compiler.cjs +36 -0
- package/dist/auto-surface/compiler.d.cts +7 -0
- package/dist/auto-surface/compiler.d.cts.map +1 -0
- package/dist/auto-surface/compiler.d.mts +7 -0
- package/dist/auto-surface/compiler.d.mts.map +1 -0
- package/dist/auto-surface/compiler.mjs +37 -0
- package/dist/auto-surface/compiler.mjs.map +1 -0
- package/dist/auto-surface/definition-dsl.cjs +333 -0
- package/dist/auto-surface/definition-dsl.d.cts +41 -0
- package/dist/auto-surface/definition-dsl.d.cts.map +1 -0
- package/dist/auto-surface/definition-dsl.d.mts +41 -0
- package/dist/auto-surface/definition-dsl.d.mts.map +1 -0
- package/dist/auto-surface/definition-dsl.mjs +332 -0
- package/dist/auto-surface/definition-dsl.mjs.map +1 -0
- package/dist/auto-surface/fragments.cjs +177 -0
- package/dist/auto-surface/fragments.d.cts +23 -0
- package/dist/auto-surface/fragments.d.cts.map +1 -0
- package/dist/auto-surface/fragments.d.mts +23 -0
- package/dist/auto-surface/fragments.d.mts.map +1 -0
- package/dist/auto-surface/fragments.mjs +175 -0
- package/dist/auto-surface/fragments.mjs.map +1 -0
- package/dist/auto-surface/index.d.mts +9 -0
- package/dist/auto-surface/layering.cjs +43 -0
- package/dist/auto-surface/layering.d.cts +7 -0
- package/dist/auto-surface/layering.d.cts.map +1 -0
- package/dist/auto-surface/layering.d.mts +7 -0
- package/dist/auto-surface/layering.d.mts.map +1 -0
- package/dist/auto-surface/layering.mjs +43 -0
- package/dist/auto-surface/layering.mjs.map +1 -0
- package/dist/auto-surface/projection.cjs +11 -0
- package/dist/auto-surface/projection.d.cts +11 -0
- package/dist/auto-surface/projection.d.cts.map +1 -0
- package/dist/auto-surface/projection.d.mts +11 -0
- package/dist/auto-surface/projection.d.mts.map +1 -0
- package/dist/auto-surface/projection.mjs +12 -0
- package/dist/auto-surface/projection.mjs.map +1 -0
- package/dist/auto-surface/projectors/settings-shell.cjs +114 -0
- package/dist/auto-surface/projectors/settings-shell.d.cts +10 -0
- package/dist/auto-surface/projectors/settings-shell.d.cts.map +1 -0
- package/dist/auto-surface/projectors/settings-shell.d.mts +10 -0
- package/dist/auto-surface/projectors/settings-shell.d.mts.map +1 -0
- package/dist/auto-surface/projectors/settings-shell.mjs +114 -0
- package/dist/auto-surface/projectors/settings-shell.mjs.map +1 -0
- package/dist/auto-surface/scenario.cjs +38 -0
- package/dist/auto-surface/scenario.d.cts +31 -0
- package/dist/auto-surface/scenario.d.cts.map +1 -0
- package/dist/auto-surface/scenario.d.mts +31 -0
- package/dist/auto-surface/scenario.d.mts.map +1 -0
- package/dist/auto-surface/scenario.mjs +37 -0
- package/dist/auto-surface/scenario.mjs.map +1 -0
- package/dist/auto-surface/types.cjs +9 -0
- package/dist/auto-surface/types.d.cts +153 -0
- package/dist/auto-surface/types.d.cts.map +1 -0
- package/dist/auto-surface/types.d.mts +153 -0
- package/dist/auto-surface/types.d.mts.map +1 -0
- package/dist/auto-surface/types.mjs +9 -0
- package/dist/auto-surface/types.mjs.map +1 -0
- package/dist/auto-surface/value-dsl.cjs +80 -0
- package/dist/auto-surface/value-dsl.d.cts +24 -0
- package/dist/auto-surface/value-dsl.d.cts.map +1 -0
- package/dist/auto-surface/value-dsl.d.mts +24 -0
- package/dist/auto-surface/value-dsl.d.mts.map +1 -0
- package/dist/auto-surface/value-dsl.mjs +79 -0
- package/dist/auto-surface/value-dsl.mjs.map +1 -0
- package/dist/blocklet/activation.cjs +94 -0
- package/dist/blocklet/activation.d.cts +30 -0
- package/dist/blocklet/activation.d.cts.map +1 -0
- package/dist/blocklet/activation.d.mts +30 -0
- package/dist/blocklet/activation.d.mts.map +1 -0
- package/dist/blocklet/activation.mjs +94 -0
- package/dist/blocklet/activation.mjs.map +1 -0
- package/dist/blocklet/did-space-registry.cjs +282 -0
- package/dist/blocklet/did-space-registry.d.cts +82 -0
- package/dist/blocklet/did-space-registry.d.cts.map +1 -0
- package/dist/blocklet/did-space-registry.d.mts +82 -0
- package/dist/blocklet/did-space-registry.d.mts.map +1 -0
- package/dist/blocklet/did-space-registry.mjs +281 -0
- package/dist/blocklet/did-space-registry.mjs.map +1 -0
- package/dist/blocklet/handlers.cjs +66 -0
- package/dist/blocklet/handlers.d.cts +16 -0
- package/dist/blocklet/handlers.d.cts.map +1 -0
- package/dist/blocklet/handlers.d.mts +16 -0
- package/dist/blocklet/handlers.d.mts.map +1 -0
- package/dist/blocklet/handlers.mjs +65 -0
- package/dist/blocklet/handlers.mjs.map +1 -0
- package/dist/blocklet/index.d.mts +7 -0
- package/dist/blocklet/manifest.d.cts +2 -0
- package/dist/blocklet/manifest.d.mts +2 -0
- package/dist/blocklet/manifest.mjs +3 -0
- package/dist/blocklet/registry.cjs +447 -0
- package/dist/blocklet/registry.d.cts +197 -0
- package/dist/blocklet/registry.d.cts.map +1 -0
- package/dist/blocklet/registry.d.mts +197 -0
- package/dist/blocklet/registry.d.mts.map +1 -0
- package/dist/blocklet/registry.mjs +441 -0
- package/dist/blocklet/registry.mjs.map +1 -0
- package/dist/blocklet/static-render.cjs +183 -0
- package/dist/blocklet/static-render.d.cts +55 -0
- package/dist/blocklet/static-render.d.cts.map +1 -0
- package/dist/blocklet/static-render.d.mts +55 -0
- package/dist/blocklet/static-render.d.mts.map +1 -0
- package/dist/blocklet/static-render.mjs +181 -0
- package/dist/blocklet/static-render.mjs.map +1 -0
- package/dist/blocklet/types.d.cts +70 -0
- package/dist/blocklet/types.d.cts.map +1 -0
- package/dist/blocklet/types.d.mts +70 -0
- package/dist/blocklet/types.d.mts.map +1 -0
- package/dist/devices/chain.cjs +127 -0
- package/dist/devices/chain.d.cts +48 -0
- package/dist/devices/chain.d.cts.map +1 -0
- package/dist/devices/chain.d.mts +48 -0
- package/dist/devices/chain.d.mts.map +1 -0
- package/dist/devices/chain.mjs +125 -0
- package/dist/devices/chain.mjs.map +1 -0
- package/dist/dsl-shared.cjs +290 -0
- package/dist/dsl-shared.d.cts +54 -0
- package/dist/dsl-shared.d.cts.map +1 -0
- package/dist/dsl-shared.d.mts +54 -0
- package/dist/dsl-shared.d.mts.map +1 -0
- package/dist/dsl-shared.mjs +287 -0
- package/dist/dsl-shared.mjs.map +1 -0
- package/dist/http/afs-mcp.cjs +85 -0
- package/dist/http/afs-mcp.d.cts +14 -0
- package/dist/http/afs-mcp.d.cts.map +1 -0
- package/dist/http/afs-mcp.d.mts +14 -0
- package/dist/http/afs-mcp.d.mts.map +1 -0
- package/dist/http/afs-mcp.mjs +86 -0
- package/dist/http/afs-mcp.mjs.map +1 -0
- package/dist/http/afs-raw.cjs +264 -0
- package/dist/http/afs-raw.d.cts +31 -0
- package/dist/http/afs-raw.d.cts.map +1 -0
- package/dist/http/afs-raw.d.mts +31 -0
- package/dist/http/afs-raw.d.mts.map +1 -0
- package/dist/http/afs-raw.mjs +264 -0
- package/dist/http/afs-raw.mjs.map +1 -0
- package/dist/http/afs-rest.cjs +30 -0
- package/dist/http/afs-rest.d.cts +21 -0
- package/dist/http/afs-rest.d.cts.map +1 -0
- package/dist/http/afs-rest.d.mts +21 -0
- package/dist/http/afs-rest.d.mts.map +1 -0
- package/dist/http/afs-rest.mjs +31 -0
- package/dist/http/afs-rest.mjs.map +1 -0
- package/dist/http/afs-rpc-wire.cjs +271 -0
- package/dist/http/afs-rpc-wire.d.cts +195 -0
- package/dist/http/afs-rpc-wire.d.cts.map +1 -0
- package/dist/http/afs-rpc-wire.d.mts +195 -0
- package/dist/http/afs-rpc-wire.d.mts.map +1 -0
- package/dist/http/afs-rpc-wire.mjs +262 -0
- package/dist/http/afs-rpc-wire.mjs.map +1 -0
- package/dist/http/afs-rpc.cjs +729 -0
- package/dist/http/afs-rpc.d.cts +103 -0
- package/dist/http/afs-rpc.d.cts.map +1 -0
- package/dist/http/afs-rpc.d.mts +103 -0
- package/dist/http/afs-rpc.d.mts.map +1 -0
- package/dist/http/afs-rpc.mjs +729 -0
- package/dist/http/afs-rpc.mjs.map +1 -0
- package/dist/http/afs-upload.cjs +116 -0
- package/dist/http/afs-upload.d.cts +40 -0
- package/dist/http/afs-upload.d.cts.map +1 -0
- package/dist/http/afs-upload.d.mts +40 -0
- package/dist/http/afs-upload.d.mts.map +1 -0
- package/dist/http/afs-upload.mjs +116 -0
- package/dist/http/afs-upload.mjs.map +1 -0
- package/dist/http/aup-client.cjs +60 -0
- package/dist/http/aup-client.d.cts +22 -0
- package/dist/http/aup-client.d.cts.map +1 -0
- package/dist/http/aup-client.d.mts +22 -0
- package/dist/http/aup-client.d.mts.map +1 -0
- package/dist/http/aup-client.mjs +59 -0
- package/dist/http/aup-client.mjs.map +1 -0
- package/dist/http/aup-event.cjs +100 -0
- package/dist/http/aup-event.d.cts +38 -0
- package/dist/http/aup-event.d.cts.map +1 -0
- package/dist/http/aup-event.d.mts +38 -0
- package/dist/http/aup-event.d.mts.map +1 -0
- package/dist/http/aup-event.mjs +101 -0
- package/dist/http/aup-event.mjs.map +1 -0
- package/dist/http/auth-context.cjs +66 -0
- package/dist/http/auth-context.d.cts +64 -0
- package/dist/http/auth-context.d.cts.map +1 -0
- package/dist/http/auth-context.d.mts +64 -0
- package/dist/http/auth-context.d.mts.map +1 -0
- package/dist/http/auth-context.mjs +66 -0
- package/dist/http/auth-context.mjs.map +1 -0
- package/dist/http/csrf.cjs +50 -0
- package/dist/http/csrf.d.cts +8 -0
- package/dist/http/csrf.d.cts.map +1 -0
- package/dist/http/csrf.d.mts +8 -0
- package/dist/http/csrf.d.mts.map +1 -0
- package/dist/http/csrf.mjs +49 -0
- package/dist/http/csrf.mjs.map +1 -0
- package/dist/http/handlers.cjs +106 -0
- package/dist/http/handlers.d.cts +39 -0
- package/dist/http/handlers.d.cts.map +1 -0
- package/dist/http/handlers.d.mts +39 -0
- package/dist/http/handlers.d.mts.map +1 -0
- package/dist/http/handlers.mjs +104 -0
- package/dist/http/handlers.mjs.map +1 -0
- package/dist/http/index.d.mts +1 -0
- package/dist/http/ingest-facade.cjs +315 -0
- package/dist/http/ingest-facade.mjs +314 -0
- package/dist/http/ingest-facade.mjs.map +1 -0
- package/dist/http/raw-url.cjs +136 -0
- package/dist/http/raw-url.d.cts +54 -0
- package/dist/http/raw-url.d.cts.map +1 -0
- package/dist/http/raw-url.d.mts +54 -0
- package/dist/http/raw-url.d.mts.map +1 -0
- package/dist/http/raw-url.mjs +136 -0
- package/dist/http/raw-url.mjs.map +1 -0
- package/dist/http/request-context.cjs +178 -0
- package/dist/http/request-context.d.cts +76 -0
- package/dist/http/request-context.d.cts.map +1 -0
- package/dist/http/request-context.d.mts +76 -0
- package/dist/http/request-context.d.mts.map +1 -0
- package/dist/http/request-context.mjs +179 -0
- package/dist/http/request-context.mjs.map +1 -0
- package/dist/index.cjs +197 -0
- package/dist/index.d.cts +63 -0
- package/dist/index.d.mts +68 -0
- package/dist/index.mjs +61 -0
- package/dist/mcp/index.cjs +9 -0
- package/dist/mcp/index.d.cts +5 -0
- package/dist/mcp/index.d.mts +5 -0
- package/dist/mcp/index.mjs +6 -0
- package/dist/mcp/prompts.cjs +17 -0
- package/dist/mcp/prompts.d.cts +8 -0
- package/dist/mcp/prompts.d.cts.map +1 -0
- package/dist/mcp/prompts.d.mts +8 -0
- package/dist/mcp/prompts.d.mts.map +1 -0
- package/dist/mcp/prompts.mjs +17 -0
- package/dist/mcp/prompts.mjs.map +1 -0
- package/dist/mcp/resources.cjs +22 -0
- package/dist/mcp/resources.d.cts +8 -0
- package/dist/mcp/resources.d.cts.map +1 -0
- package/dist/mcp/resources.d.mts +8 -0
- package/dist/mcp/resources.d.mts.map +1 -0
- package/dist/mcp/resources.mjs +22 -0
- package/dist/mcp/resources.mjs.map +1 -0
- package/dist/mcp/server.cjs +51 -0
- package/dist/mcp/server.d.cts +20 -0
- package/dist/mcp/server.d.cts.map +1 -0
- package/dist/mcp/server.d.mts +20 -0
- package/dist/mcp/server.d.mts.map +1 -0
- package/dist/mcp/server.mjs +52 -0
- package/dist/mcp/server.mjs.map +1 -0
- package/dist/mcp/tools.cjs +218 -0
- package/dist/mcp/tools.d.cts +8 -0
- package/dist/mcp/tools.d.cts.map +1 -0
- package/dist/mcp/tools.d.mts +8 -0
- package/dist/mcp/tools.d.mts.map +1 -0
- package/dist/mcp/tools.mjs +219 -0
- package/dist/mcp/tools.mjs.map +1 -0
- package/dist/mcp/utils.cjs +75 -0
- package/dist/mcp/utils.mjs +69 -0
- package/dist/mcp/utils.mjs.map +1 -0
- package/dist/mount/index.cjs +4 -0
- package/dist/mount/index.d.cts +3 -0
- package/dist/mount/index.d.mts +3 -0
- package/dist/mount/index.mjs +3 -0
- package/dist/mount/materializer.cjs +167 -0
- package/dist/mount/materializer.d.cts +97 -0
- package/dist/mount/materializer.d.cts.map +1 -0
- package/dist/mount/materializer.d.mts +97 -0
- package/dist/mount/materializer.d.mts.map +1 -0
- package/dist/mount/materializer.mjs +167 -0
- package/dist/mount/materializer.mjs.map +1 -0
- package/dist/mount/types.d.cts +90 -0
- package/dist/mount/types.d.cts.map +1 -0
- package/dist/mount/types.d.mts +90 -0
- package/dist/mount/types.d.mts.map +1 -0
- package/dist/mount-config.cjs +61 -0
- package/dist/mount-config.d.cts +19 -0
- package/dist/mount-config.d.cts.map +1 -0
- package/dist/mount-config.d.mts +19 -0
- package/dist/mount-config.d.mts.map +1 -0
- package/dist/mount-config.mjs +61 -0
- package/dist/mount-config.mjs.map +1 -0
- package/dist/projectors/aup-projector.cjs +190 -0
- package/dist/projectors/aup-projector.d.cts +59 -0
- package/dist/projectors/aup-projector.d.cts.map +1 -0
- package/dist/projectors/aup-projector.d.mts +59 -0
- package/dist/projectors/aup-projector.d.mts.map +1 -0
- package/dist/projectors/aup-projector.mjs +188 -0
- package/dist/projectors/aup-projector.mjs.map +1 -0
- package/dist/projectors/index.cjs +6 -0
- package/dist/projectors/index.d.cts +2 -0
- package/dist/projectors/index.d.mts +2 -0
- package/dist/projectors/index.mjs +3 -0
- package/dist/scaffold/afs.cjs +195 -0
- package/dist/scaffold/afs.d.cts +16 -0
- package/dist/scaffold/afs.d.cts.map +1 -0
- package/dist/scaffold/afs.d.mts +16 -0
- package/dist/scaffold/afs.d.mts.map +1 -0
- package/dist/scaffold/afs.mjs +195 -0
- package/dist/scaffold/afs.mjs.map +1 -0
- package/dist/scaffold/composition.cjs +92 -0
- package/dist/scaffold/composition.d.cts +10 -0
- package/dist/scaffold/composition.d.cts.map +1 -0
- package/dist/scaffold/composition.d.mts +10 -0
- package/dist/scaffold/composition.d.mts.map +1 -0
- package/dist/scaffold/composition.mjs +92 -0
- package/dist/scaffold/composition.mjs.map +1 -0
- package/dist/scaffold/dsl-error.cjs +21 -0
- package/dist/scaffold/dsl-error.d.cts +11 -0
- package/dist/scaffold/dsl-error.d.cts.map +1 -0
- package/dist/scaffold/dsl-error.d.mts +11 -0
- package/dist/scaffold/dsl-error.d.mts.map +1 -0
- package/dist/scaffold/dsl-error.mjs +20 -0
- package/dist/scaffold/dsl-error.mjs.map +1 -0
- package/dist/scaffold/index.d.mts +12 -0
- package/dist/scaffold/manifest-dsl.cjs +188 -0
- package/dist/scaffold/manifest-dsl.d.cts +8 -0
- package/dist/scaffold/manifest-dsl.d.cts.map +1 -0
- package/dist/scaffold/manifest-dsl.d.mts +8 -0
- package/dist/scaffold/manifest-dsl.d.mts.map +1 -0
- package/dist/scaffold/manifest-dsl.mjs +188 -0
- package/dist/scaffold/manifest-dsl.mjs.map +1 -0
- package/dist/scaffold/module-dsl.cjs +284 -0
- package/dist/scaffold/module-dsl.d.cts +8 -0
- package/dist/scaffold/module-dsl.d.cts.map +1 -0
- package/dist/scaffold/module-dsl.d.mts +8 -0
- package/dist/scaffold/module-dsl.d.mts.map +1 -0
- package/dist/scaffold/module-dsl.mjs +284 -0
- package/dist/scaffold/module-dsl.mjs.map +1 -0
- package/dist/scaffold/resolver.cjs +156 -0
- package/dist/scaffold/resolver.d.cts +7 -0
- package/dist/scaffold/resolver.d.cts.map +1 -0
- package/dist/scaffold/resolver.d.mts +7 -0
- package/dist/scaffold/resolver.d.mts.map +1 -0
- package/dist/scaffold/resolver.mjs +156 -0
- package/dist/scaffold/resolver.mjs.map +1 -0
- package/dist/scaffold/runtime.cjs +24 -0
- package/dist/scaffold/runtime.d.cts +19 -0
- package/dist/scaffold/runtime.d.cts.map +1 -0
- package/dist/scaffold/runtime.d.mts +19 -0
- package/dist/scaffold/runtime.d.mts.map +1 -0
- package/dist/scaffold/runtime.mjs +25 -0
- package/dist/scaffold/runtime.mjs.map +1 -0
- package/dist/scaffold/shell-dsl.cjs +279 -0
- package/dist/scaffold/shell-dsl.d.cts +8 -0
- package/dist/scaffold/shell-dsl.d.cts.map +1 -0
- package/dist/scaffold/shell-dsl.d.mts +8 -0
- package/dist/scaffold/shell-dsl.d.mts.map +1 -0
- package/dist/scaffold/shell-dsl.mjs +279 -0
- package/dist/scaffold/shell-dsl.mjs.map +1 -0
- package/dist/scaffold/surface-dsl.cjs +182 -0
- package/dist/scaffold/surface-dsl.d.cts +8 -0
- package/dist/scaffold/surface-dsl.d.cts.map +1 -0
- package/dist/scaffold/surface-dsl.d.mts +8 -0
- package/dist/scaffold/surface-dsl.d.mts.map +1 -0
- package/dist/scaffold/surface-dsl.mjs +182 -0
- package/dist/scaffold/surface-dsl.mjs.map +1 -0
- package/dist/scaffold/surfaces.cjs +84 -0
- package/dist/scaffold/surfaces.d.cts +23 -0
- package/dist/scaffold/surfaces.d.cts.map +1 -0
- package/dist/scaffold/surfaces.d.mts +24 -0
- package/dist/scaffold/surfaces.d.mts.map +1 -0
- package/dist/scaffold/surfaces.mjs +84 -0
- package/dist/scaffold/surfaces.mjs.map +1 -0
- package/dist/scaffold/types.d.cts +264 -0
- package/dist/scaffold/types.d.cts.map +1 -0
- package/dist/scaffold/types.d.mts +265 -0
- package/dist/scaffold/types.d.mts.map +1 -0
- package/dist/scaffold/workspace-dsl.cjs +339 -0
- package/dist/scaffold/workspace-dsl.d.cts +49 -0
- package/dist/scaffold/workspace-dsl.d.cts.map +1 -0
- package/dist/scaffold/workspace-dsl.d.mts +49 -0
- package/dist/scaffold/workspace-dsl.d.mts.map +1 -0
- package/dist/scaffold/workspace-dsl.mjs +337 -0
- package/dist/scaffold/workspace-dsl.mjs.map +1 -0
- package/dist/scope/index.d.mts +3 -0
- package/dist/scope/read-blocklet-scope.cjs +29 -0
- package/dist/scope/read-blocklet-scope.d.cts +8 -0
- package/dist/scope/read-blocklet-scope.d.cts.map +1 -0
- package/dist/scope/read-blocklet-scope.d.mts +8 -0
- package/dist/scope/read-blocklet-scope.d.mts.map +1 -0
- package/dist/scope/read-blocklet-scope.mjs +30 -0
- package/dist/scope/read-blocklet-scope.mjs.map +1 -0
- package/dist/scope/resolve-scoped-afs.cjs +87 -0
- package/dist/scope/resolve-scoped-afs.d.cts +7 -0
- package/dist/scope/resolve-scoped-afs.d.cts.map +1 -0
- package/dist/scope/resolve-scoped-afs.d.mts +7 -0
- package/dist/scope/resolve-scoped-afs.d.mts.map +1 -0
- package/dist/scope/resolve-scoped-afs.mjs +88 -0
- package/dist/scope/resolve-scoped-afs.mjs.map +1 -0
- package/dist/scope/types.d.cts +25 -0
- package/dist/scope/types.d.cts.map +1 -0
- package/dist/scope/types.d.mts +25 -0
- package/dist/scope/types.d.mts.map +1 -0
- package/dist/session/backends.cjs +90 -0
- package/dist/session/backends.d.cts +35 -0
- package/dist/session/backends.d.cts.map +1 -0
- package/dist/session/backends.d.mts +35 -0
- package/dist/session/backends.d.mts.map +1 -0
- package/dist/session/backends.mjs +89 -0
- package/dist/session/backends.mjs.map +1 -0
- package/dist/session/replication-resolver.cjs +323 -0
- package/dist/session/replication-resolver.d.cts +71 -0
- package/dist/session/replication-resolver.d.cts.map +1 -0
- package/dist/session/replication-resolver.d.mts +71 -0
- package/dist/session/replication-resolver.d.mts.map +1 -0
- package/dist/session/replication-resolver.mjs +323 -0
- package/dist/session/replication-resolver.mjs.map +1 -0
- package/dist/session/role-level.cjs +36 -0
- package/dist/session/role-level.d.cts +24 -0
- package/dist/session/role-level.d.cts.map +1 -0
- package/dist/session/role-level.d.mts +24 -0
- package/dist/session/role-level.d.mts.map +1 -0
- package/dist/session/role-level.mjs +35 -0
- package/dist/session/role-level.mjs.map +1 -0
- package/dist/session/session-dir-providers.cjs +254 -0
- package/dist/session/session-dir-providers.d.cts +32 -0
- package/dist/session/session-dir-providers.d.cts.map +1 -0
- package/dist/session/session-dir-providers.d.mts +32 -0
- package/dist/session/session-dir-providers.d.mts.map +1 -0
- package/dist/session/session-dir-providers.mjs +252 -0
- package/dist/session/session-dir-providers.mjs.map +1 -0
- package/dist/session/session-id.cjs +20 -0
- package/dist/session/session-id.d.cts +15 -0
- package/dist/session/session-id.d.cts.map +1 -0
- package/dist/session/session-id.d.mts +15 -0
- package/dist/session/session-id.d.mts.map +1 -0
- package/dist/session/session-id.mjs +20 -0
- package/dist/session/session-id.mjs.map +1 -0
- package/dist/session/session-user-afs.cjs +899 -0
- package/dist/session/session-user-afs.d.cts +296 -0
- package/dist/session/session-user-afs.d.cts.map +1 -0
- package/dist/session/session-user-afs.d.mts +296 -0
- package/dist/session/session-user-afs.d.mts.map +1 -0
- package/dist/session/session-user-afs.mjs +896 -0
- package/dist/session/session-user-afs.mjs.map +1 -0
- package/dist/session/settings-cascade.cjs +69 -0
- package/dist/session/settings-cascade.d.cts +81 -0
- package/dist/session/settings-cascade.d.cts.map +1 -0
- package/dist/session/settings-cascade.d.mts +81 -0
- package/dist/session/settings-cascade.d.mts.map +1 -0
- package/dist/session/settings-cascade.mjs +69 -0
- package/dist/session/settings-cascade.mjs.map +1 -0
- package/dist/session/settings-resolver.cjs +770 -0
- package/dist/session/settings-resolver.d.cts +177 -0
- package/dist/session/settings-resolver.d.cts.map +1 -0
- package/dist/session/settings-resolver.d.mts +177 -0
- package/dist/session/settings-resolver.d.mts.map +1 -0
- package/dist/session/settings-resolver.mjs +771 -0
- package/dist/session/settings-resolver.mjs.map +1 -0
- package/dist/session/settings-schema-store.cjs +0 -0
- package/dist/session/settings-schema-store.d.cts +72 -0
- package/dist/session/settings-schema-store.d.cts.map +1 -0
- package/dist/session/settings-schema-store.d.mts +72 -0
- package/dist/session/settings-schema-store.d.mts.map +1 -0
- package/dist/session/settings-schema-store.mjs +0 -0
- package/dist/session/settings-schema-store.mjs.map +1 -0
- package/dist/system-mounts/index.cjs +14 -0
- package/dist/system-mounts/index.d.cts +6 -0
- package/dist/system-mounts/index.d.mts +6 -0
- package/dist/system-mounts/index.mjs +6 -0
- package/dist/system-mounts/install.cjs +101 -0
- package/dist/system-mounts/install.d.cts +36 -0
- package/dist/system-mounts/install.d.cts.map +1 -0
- package/dist/system-mounts/install.d.mts +37 -0
- package/dist/system-mounts/install.d.mts.map +1 -0
- package/dist/system-mounts/install.mjs +102 -0
- package/dist/system-mounts/install.mjs.map +1 -0
- package/dist/system-mounts/installers.cjs +247 -0
- package/dist/system-mounts/installers.d.cts +13 -0
- package/dist/system-mounts/installers.d.cts.map +1 -0
- package/dist/system-mounts/installers.d.mts +14 -0
- package/dist/system-mounts/installers.d.mts.map +1 -0
- package/dist/system-mounts/installers.mjs +244 -0
- package/dist/system-mounts/installers.mjs.map +1 -0
- package/dist/system-mounts/lists.cjs +122 -0
- package/dist/system-mounts/lists.d.cts +34 -0
- package/dist/system-mounts/lists.d.cts.map +1 -0
- package/dist/system-mounts/lists.d.mts +34 -0
- package/dist/system-mounts/lists.d.mts.map +1 -0
- package/dist/system-mounts/lists.mjs +122 -0
- package/dist/system-mounts/lists.mjs.map +1 -0
- package/dist/system-mounts/types.d.cts +124 -0
- package/dist/system-mounts/types.d.cts.map +1 -0
- package/dist/system-mounts/types.d.mts +125 -0
- package/dist/system-mounts/types.d.mts.map +1 -0
- package/dist/system-mounts/validate.cjs +56 -0
- package/dist/system-mounts/validate.d.cts +34 -0
- package/dist/system-mounts/validate.d.cts.map +1 -0
- package/dist/system-mounts/validate.d.mts +34 -0
- package/dist/system-mounts/validate.d.mts.map +1 -0
- package/dist/system-mounts/validate.mjs +56 -0
- package/dist/system-mounts/validate.mjs.map +1 -0
- package/dist/terminal-llm.cjs +90 -0
- package/dist/terminal-llm.d.cts +50 -0
- package/dist/terminal-llm.d.cts.map +1 -0
- package/dist/terminal-llm.d.mts +50 -0
- package/dist/terminal-llm.d.mts.map +1 -0
- package/dist/terminal-llm.mjs +90 -0
- package/dist/terminal-llm.mjs.map +1 -0
- package/dist/terminal-repl.cjs +371 -0
- package/dist/terminal-repl.d.cts +69 -0
- package/dist/terminal-repl.d.cts.map +1 -0
- package/dist/terminal-repl.d.mts +69 -0
- package/dist/terminal-repl.d.mts.map +1 -0
- package/dist/terminal-repl.mjs +370 -0
- package/dist/terminal-repl.mjs.map +1 -0
- package/dist/transport/idle-timer.cjs +136 -0
- package/dist/transport/idle-timer.d.cts +92 -0
- package/dist/transport/idle-timer.d.cts.map +1 -0
- package/dist/transport/idle-timer.d.mts +92 -0
- package/dist/transport/idle-timer.d.mts.map +1 -0
- package/dist/transport/idle-timer.mjs +132 -0
- package/dist/transport/idle-timer.mjs.map +1 -0
- package/dist/web-component-dsl.cjs +153 -0
- package/dist/web-component-dsl.d.cts +27 -0
- package/dist/web-component-dsl.d.cts.map +1 -0
- package/dist/web-component-dsl.d.mts +27 -0
- package/dist/web-component-dsl.d.mts.map +1 -0
- package/dist/web-component-dsl.mjs +152 -0
- package/dist/web-component-dsl.mjs.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,896 @@
|
|
|
1
|
+
import { ReplicationResolver, computeReplicationMountPrefix } from "./replication-resolver.mjs";
|
|
2
|
+
import { SettingsResolver } from "./settings-resolver.mjs";
|
|
3
|
+
import { joinURL } from "ufo";
|
|
4
|
+
import { AFSDependencyError, AFSForbiddenError, AFSNotFoundError, AFSUnsupportedError, AFSValidationError, enforceEffectGate, execReflexiveRootDataAction, isReflexiveRootDataAction, makeNsLog, rootActionEffect, toBatchEntryFailure } from "@aigne/afs";
|
|
5
|
+
|
|
6
|
+
//#region src/session/session-user-afs.ts
|
|
7
|
+
const log = makeNsLog("aos");
|
|
8
|
+
/**
|
|
9
|
+
* Concurrency cap for hydrating index-search results with their real
|
|
10
|
+
* `read()`-backed content (P5 search→index forward). Mirrors the existing
|
|
11
|
+
* `SEARCH_CONCURRENCY = 8` in `packages/core/src/afs.ts` — same fan-out
|
|
12
|
+
* shape (N paths → N reads), same bound (avoid pathological fan-out against
|
|
13
|
+
* the per-caller DID Space backend on a single search).
|
|
14
|
+
*/
|
|
15
|
+
const INDEX_SEARCH_HYDRATE_CONCURRENCY = 8;
|
|
16
|
+
/**
|
|
17
|
+
* Minimal concurrency-bounded map — same small helper duplicated at each of
|
|
18
|
+
* its other call sites (`packages/core/src/afs.ts`, `provider/base.ts`,
|
|
19
|
+
* `blocklet/data-seed.ts`, `aos/src/http/handlers.ts`); not exported from a
|
|
20
|
+
* shared module today, so this follows the existing convention rather than
|
|
21
|
+
* introducing a new one.
|
|
22
|
+
*/
|
|
23
|
+
async function mapWithConcurrency(items, concurrency, fn) {
|
|
24
|
+
const results = new Array(items.length);
|
|
25
|
+
let nextIndex = 0;
|
|
26
|
+
const workerCount = Math.min(Math.max(1, concurrency), items.length);
|
|
27
|
+
await Promise.all(Array.from({ length: workerCount }, async () => {
|
|
28
|
+
while (nextIndex < items.length) {
|
|
29
|
+
const index = nextIndex++;
|
|
30
|
+
results[index] = await fn(items[index], index);
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* STATIC full set of overlay prefixes a SessionUserAFS may mount — the
|
|
37
|
+
* anonymous-bearer denylist for signed raw URLs (afs-preview design §3).
|
|
38
|
+
*
|
|
39
|
+
* Deliberately NOT derived from an instance's `overlays` array: `/space` and
|
|
40
|
+
* `/instance/settings` are conditionally mounted, so per-instance derivation
|
|
41
|
+
* would drift with wiring. Fail-closed: an anonymous raw URL is refused for
|
|
42
|
+
* these prefixes even when the issuing session didn't mount them.
|
|
43
|
+
*
|
|
44
|
+
* KEEP IN SYNC with the constructor below — the unit test enumerates this
|
|
45
|
+
* set against the constructor's possible mounts, table-driven.
|
|
46
|
+
*/
|
|
47
|
+
const SESSION_OVERLAY_PREFIXES = [
|
|
48
|
+
"/user/index",
|
|
49
|
+
"/user",
|
|
50
|
+
"/tmp",
|
|
51
|
+
"/space",
|
|
52
|
+
"/instance/settings"
|
|
53
|
+
];
|
|
54
|
+
/**
|
|
55
|
+
* Whether a (sanitized) path falls under any session-private overlay prefix.
|
|
56
|
+
* Used by the raw-URL primitives to refuse anonymous bearer URLs for
|
|
57
|
+
* session-private content (issue-side denial + verify-side second defense).
|
|
58
|
+
*/
|
|
59
|
+
function isSessionPrivatePath(path) {
|
|
60
|
+
return SESSION_OVERLAY_PREFIXES.some((p) => path === p || path.startsWith(`${p}/`));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Guard the first-match-by-prefix invariant: no overlay may be preceded by
|
|
64
|
+
* another whose prefix is a proper prefix of it (which would swallow its
|
|
65
|
+
* paths). `/instance/settings` MUST come before any future `/instance` or `/`
|
|
66
|
+
* overlay. Extracted + exported so the ordering contract is unit-testable
|
|
67
|
+
* without reaching into the class. Throws on violation (a wiring bug).
|
|
68
|
+
*/
|
|
69
|
+
function assertOverlayOrder(prefixes) {
|
|
70
|
+
for (let i = 0; i < prefixes.length; i++) {
|
|
71
|
+
const current = prefixes[i];
|
|
72
|
+
if (current === void 0) continue;
|
|
73
|
+
for (let j = 0; j < i; j++) {
|
|
74
|
+
const earlier = prefixes[j];
|
|
75
|
+
if (earlier === void 0) continue;
|
|
76
|
+
const earlierAsDir = earlier === "/" ? "/" : `${earlier}/`;
|
|
77
|
+
if (current === earlier || current.startsWith(earlierAsDir)) throw new Error(`SessionUserAFS overlay order bug: "${earlier}" precedes and shadows "${current}" (first-match routing)`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Strip an overlay prefix → provider-relative path (always leading-slash). */
|
|
82
|
+
function subPath(normalized, prefix) {
|
|
83
|
+
if (normalized === prefix) return "/";
|
|
84
|
+
const rest = normalized.slice(prefix.length);
|
|
85
|
+
return rest.startsWith("/") ? rest : `/${rest}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Synthetic directory entry for an overlay root, mirroring a real mount root.
|
|
89
|
+
* `childrenCount: -1` (unknown) + `accessMode` live under `meta`, matching the
|
|
90
|
+
* shape a real mount returns in `list("/")` / `stat()`.
|
|
91
|
+
*/
|
|
92
|
+
function overlayRootEntry(overlay) {
|
|
93
|
+
return {
|
|
94
|
+
id: overlay.id,
|
|
95
|
+
path: overlay.prefix,
|
|
96
|
+
meta: {
|
|
97
|
+
childrenCount: -1,
|
|
98
|
+
accessMode: overlay.provider?.accessMode ?? "readwrite"
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
var SessionUserAFS = class {
|
|
103
|
+
name;
|
|
104
|
+
accessMode = "readwrite";
|
|
105
|
+
overlays;
|
|
106
|
+
/**
|
|
107
|
+
* Named reference to the settings resolver overlay (the overlay table only
|
|
108
|
+
* stores it anonymously) so `beginRender`/`endRender` can proxy to it —
|
|
109
|
+
* settings-layering §2.B render boundary.
|
|
110
|
+
*/
|
|
111
|
+
settingsResolver;
|
|
112
|
+
constructor(base, userProvider, tmpProvider, sessionId, settingsResolver = null, spaceProvider, indexProvider, replicationOverlays, indexSearchRequired = indexProvider != null) {
|
|
113
|
+
this.base = base;
|
|
114
|
+
this.indexSearchRequired = indexSearchRequired;
|
|
115
|
+
this.name = `session-user:${sessionId}`;
|
|
116
|
+
this.overlays = [];
|
|
117
|
+
if (indexProvider !== void 0) this.overlays.push({
|
|
118
|
+
prefix: "/user/index",
|
|
119
|
+
id: "user-index",
|
|
120
|
+
provider: indexProvider,
|
|
121
|
+
rootVisible: false
|
|
122
|
+
});
|
|
123
|
+
this.overlays.push({
|
|
124
|
+
prefix: "/user",
|
|
125
|
+
id: "user",
|
|
126
|
+
provider: userProvider,
|
|
127
|
+
rootVisible: true
|
|
128
|
+
}, {
|
|
129
|
+
prefix: "/tmp",
|
|
130
|
+
id: "tmp",
|
|
131
|
+
provider: tmpProvider,
|
|
132
|
+
rootVisible: true
|
|
133
|
+
});
|
|
134
|
+
if (spaceProvider !== void 0) this.overlays.push({
|
|
135
|
+
prefix: "/space",
|
|
136
|
+
id: "space",
|
|
137
|
+
provider: spaceProvider,
|
|
138
|
+
rootVisible: true
|
|
139
|
+
});
|
|
140
|
+
this.settingsResolver = settingsResolver;
|
|
141
|
+
if (settingsResolver) this.overlays.push({
|
|
142
|
+
prefix: "/instance/settings",
|
|
143
|
+
id: "instance-settings",
|
|
144
|
+
provider: settingsResolver,
|
|
145
|
+
rootVisible: false
|
|
146
|
+
});
|
|
147
|
+
for (const ro of replicationOverlays ?? []) this.overlays.push({
|
|
148
|
+
...ro,
|
|
149
|
+
rootVisible: false
|
|
150
|
+
});
|
|
151
|
+
assertOverlayOrder(this.overlays.map((o) => o.prefix));
|
|
152
|
+
}
|
|
153
|
+
/** Match a path against the overlay table. Returns the overlay + sub-path. */
|
|
154
|
+
matchOverlay(path) {
|
|
155
|
+
const normalized = path.startsWith("/") ? path : `/${path}`;
|
|
156
|
+
for (const overlay of this.overlays) if (normalized === overlay.prefix || normalized.startsWith(`${overlay.prefix}/`)) return {
|
|
157
|
+
overlay,
|
|
158
|
+
sub: subPath(normalized, overlay.prefix)
|
|
159
|
+
};
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
/** Overlays that are actually backed (provider present). */
|
|
163
|
+
get activeOverlays() {
|
|
164
|
+
return this.overlays.filter((o) => o.provider != null);
|
|
165
|
+
}
|
|
166
|
+
/** Backed AND root-level overlays — the ones surfaced at `/` / in getMounts. */
|
|
167
|
+
get rootOverlays() {
|
|
168
|
+
return this.overlays.filter((o) => o.provider != null && o.rootVisible);
|
|
169
|
+
}
|
|
170
|
+
rejectMissing(path) {
|
|
171
|
+
throw new AFSNotFoundError(path);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Whether a write context originates from an untrusted network client.
|
|
175
|
+
* `callerOrigin` is a host-stamped, unforgeable marker (strip + trusted reset,
|
|
176
|
+
* see FORGEABLE_CONTEXT_FIELDS); internal code (seeding / cron / agent /
|
|
177
|
+
* operator CLI) carries no `callerOrigin`. Mirrors the reflexive effect gate's
|
|
178
|
+
* network check (`exec-effect-gate.ts`).
|
|
179
|
+
*/
|
|
180
|
+
isNetworkOrigin(context) {
|
|
181
|
+
return context?.callerOrigin === "network";
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Caller-origin base-write gate (instance-write-authz §5.1). A network client
|
|
185
|
+
* may never bare-write a BASE-fallthrough path — any path NOT matched by an
|
|
186
|
+
* overlay (`/instance/<non-mediated>`, `/packages`, `/dev`, `/registry`, `/`).
|
|
187
|
+
* Authorized `/instance` writes must go through a resolver overlay
|
|
188
|
+
* (`/instance/settings` → SettingsResolver, future `/instance/app` →
|
|
189
|
+
* ReplicationResolver — each carries its own role/minRole gate) or internal
|
|
190
|
+
* trusted code (`callerOrigin: undefined`).
|
|
191
|
+
*
|
|
192
|
+
* Called ONLY on the base-fallthrough branch (overlay-matched paths never
|
|
193
|
+
* reach here). STRICTER than the effect gate: it rejects AUTHENTICATED network
|
|
194
|
+
* callers too (the effect gate lets `caller.did` through) — that authed-but-
|
|
195
|
+
* network reflexive base write is exactly Finding 1's live path.
|
|
196
|
+
*/
|
|
197
|
+
forbiddenBaseWrite(path) {
|
|
198
|
+
return new AFSForbiddenError(path, "network clients cannot write base paths; use a resolver overlay or internal code");
|
|
199
|
+
}
|
|
200
|
+
enforceBaseWriteGate(path, context) {
|
|
201
|
+
if (this.isNetworkOrigin(context)) throw this.forbiddenBaseWrite(path);
|
|
202
|
+
}
|
|
203
|
+
/** Re-prefix a provider-relative path back into the overlay namespace. */
|
|
204
|
+
reprefix(prefix, childPath) {
|
|
205
|
+
return childPath === "/" ? prefix : joinURL(prefix, childPath);
|
|
206
|
+
}
|
|
207
|
+
async list(path, options) {
|
|
208
|
+
const match = this.matchOverlay(path);
|
|
209
|
+
if (match) {
|
|
210
|
+
const { overlay, sub } = match;
|
|
211
|
+
if (!overlay.provider?.list) this.rejectMissing(path);
|
|
212
|
+
const result$1 = await overlay.provider.list(sub, options);
|
|
213
|
+
return {
|
|
214
|
+
...result$1,
|
|
215
|
+
data: (result$1.data ?? []).map((e) => ({
|
|
216
|
+
...e,
|
|
217
|
+
path: this.reprefix(overlay.prefix, e.path)
|
|
218
|
+
}))
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
const result = await this.base.list(path, options);
|
|
222
|
+
if ((path.startsWith("/") ? path : `/${path}`) === "/") {
|
|
223
|
+
const existing = new Set((result.data ?? []).map((e) => e.path));
|
|
224
|
+
const injected = this.rootOverlays.filter((o) => !existing.has(o.prefix)).map((o) => overlayRootEntry(o));
|
|
225
|
+
if (injected.length) return {
|
|
226
|
+
...result,
|
|
227
|
+
data: [...result.data ?? [], ...injected]
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
async read(path, options) {
|
|
233
|
+
options = this.withSelfContext(options);
|
|
234
|
+
const match = this.matchOverlay(path);
|
|
235
|
+
if (match) {
|
|
236
|
+
if (!match.overlay.provider?.read) this.rejectMissing(path);
|
|
237
|
+
return match.overlay.provider.read(match.sub, options);
|
|
238
|
+
}
|
|
239
|
+
if (!this.base.read) throw new Error("base.read not supported");
|
|
240
|
+
return this.base.read(path, options);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Overlay-dispatch for `presignRead` (preview-r2-direct §5a.2 / T1.2). Same
|
|
244
|
+
* routing as `read`: a matched overlay whose provider implements `presignRead`
|
|
245
|
+
* gets the sub-path; a base-fallthrough path (or an overlay provider without
|
|
246
|
+
* the capability) → `null` (fail-soft → the raw handler serves bytes itself).
|
|
247
|
+
*
|
|
248
|
+
* The meta-only ACL and the `null`-on-everything fail-soft live DEEPER (the
|
|
249
|
+
* `/user` overlay provider is a `ProjectionProvider` → core `AFS` (globalAFS),
|
|
250
|
+
* where the authoritative meta guard runs — §5a.2 "routing to the root
|
|
251
|
+
* computation"); this layer only forwards.
|
|
252
|
+
*
|
|
253
|
+
* This is the HANDLER-FACING surface (`scoped.afs`), so it owns the §5a.5
|
|
254
|
+
* "NEVER throws to the handler" guarantee end-to-end: a deeper layer that
|
|
255
|
+
* throws (e.g. a read-disabled `ProjectionProvider.checkOp("read")` →
|
|
256
|
+
* `AFSAccessModeError`) is caught here → `null` → the raw handler serves bytes
|
|
257
|
+
* itself (and the worker-serve read then re-applies that same gate). No URL
|
|
258
|
+
* can leak past a read-disabled / failing projection.
|
|
259
|
+
*/
|
|
260
|
+
async presignRead(path, opts) {
|
|
261
|
+
try {
|
|
262
|
+
const match = this.matchOverlay(path);
|
|
263
|
+
if (match) {
|
|
264
|
+
const provider = match.overlay.provider;
|
|
265
|
+
if (typeof provider?.presignRead !== "function") return null;
|
|
266
|
+
return await provider.presignRead(match.sub, opts) ?? null;
|
|
267
|
+
}
|
|
268
|
+
if (typeof this.base.presignRead !== "function") return null;
|
|
269
|
+
return await this.base.presignRead(path, opts) ?? null;
|
|
270
|
+
} catch {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async write(path, content, options) {
|
|
275
|
+
options = this.withSelfContext(options);
|
|
276
|
+
const match = this.matchOverlay(path);
|
|
277
|
+
if (match) {
|
|
278
|
+
if (!match.overlay.provider?.write) this.rejectMissing(path);
|
|
279
|
+
return match.overlay.provider.write(match.sub, content, options);
|
|
280
|
+
}
|
|
281
|
+
this.enforceBaseWriteGate(path, options?.context);
|
|
282
|
+
if (!this.base.write) throw new Error("base.write not supported");
|
|
283
|
+
return this.base.write(path, content, options);
|
|
284
|
+
}
|
|
285
|
+
async delete(path, options) {
|
|
286
|
+
options = this.withSelfContext(options);
|
|
287
|
+
const match = this.matchOverlay(path);
|
|
288
|
+
if (match) {
|
|
289
|
+
if (!match.overlay.provider?.delete) this.rejectMissing(path);
|
|
290
|
+
return match.overlay.provider.delete(match.sub, options);
|
|
291
|
+
}
|
|
292
|
+
this.enforceBaseWriteGate(path, options?.context);
|
|
293
|
+
if (!this.base.delete) throw new Error("base.delete not supported");
|
|
294
|
+
return this.base.delete(path, options);
|
|
295
|
+
}
|
|
296
|
+
/** Plan contiguous runs of entry indices by overlay identity (null = base). */
|
|
297
|
+
planOverlayRuns(paths) {
|
|
298
|
+
const runs = [];
|
|
299
|
+
for (let i = 0; i < paths.length; i++) {
|
|
300
|
+
const overlay = this.matchOverlay(paths[i])?.overlay ?? null;
|
|
301
|
+
const last = runs[runs.length - 1];
|
|
302
|
+
if (last && last.overlay === overlay) last.indices.push(i);
|
|
303
|
+
else runs.push({
|
|
304
|
+
overlay,
|
|
305
|
+
indices: [i]
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return runs;
|
|
309
|
+
}
|
|
310
|
+
async batchWrite(entries, options) {
|
|
311
|
+
const ctx = this.withSelfContext(options ?? {}).context;
|
|
312
|
+
const results = new Array(entries.length);
|
|
313
|
+
for (const run of this.planOverlayRuns(entries.map((e) => e.path))) {
|
|
314
|
+
const provider = run.overlay?.provider;
|
|
315
|
+
if (run.overlay && provider && typeof provider.batchWrite === "function") {
|
|
316
|
+
const subEntries = run.indices.map((i) => ({
|
|
317
|
+
...entries[i],
|
|
318
|
+
path: subPath(entries[i].path, run.overlay.prefix),
|
|
319
|
+
options: {
|
|
320
|
+
...entries[i].options,
|
|
321
|
+
context: ctx
|
|
322
|
+
}
|
|
323
|
+
}));
|
|
324
|
+
try {
|
|
325
|
+
const r = await provider.batchWrite(subEntries, { context: ctx });
|
|
326
|
+
if (!Array.isArray(r?.results) || r.results.length !== subEntries.length) throw new Error(`Provider '${provider.name}' batchWrite returned ${r?.results?.length ?? 0} results for ${subEntries.length} entries`);
|
|
327
|
+
run.indices.forEach((i, j) => {
|
|
328
|
+
const entryResult = r.results[j];
|
|
329
|
+
const data = entryResult.data ? {
|
|
330
|
+
...entryResult.data,
|
|
331
|
+
path: this.reprefix(run.overlay.prefix, entryResult.data.path)
|
|
332
|
+
} : entryResult.data;
|
|
333
|
+
results[i] = {
|
|
334
|
+
...entryResult,
|
|
335
|
+
path: entries[i].path,
|
|
336
|
+
data
|
|
337
|
+
};
|
|
338
|
+
});
|
|
339
|
+
} catch (err) {
|
|
340
|
+
for (const i of run.indices) results[i] = toBatchEntryFailure(entries[i].path, err);
|
|
341
|
+
}
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (!run.overlay && typeof this.base.batchWrite === "function") {
|
|
345
|
+
if (this.isNetworkOrigin(ctx)) {
|
|
346
|
+
for (const i of run.indices) results[i] = toBatchEntryFailure(entries[i].path, this.forbiddenBaseWrite(entries[i].path));
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const baseEntries = run.indices.map((i) => entries[i]);
|
|
350
|
+
const r = await this.base.batchWrite(baseEntries, { context: ctx });
|
|
351
|
+
run.indices.forEach((i, j) => {
|
|
352
|
+
results[i] = r.results[j];
|
|
353
|
+
});
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
for (const i of run.indices) {
|
|
357
|
+
const entry = entries[i];
|
|
358
|
+
try {
|
|
359
|
+
const payload = entry.content ?? {};
|
|
360
|
+
if (entry.patches) payload.patches = entry.patches;
|
|
361
|
+
const res = await this.write(entry.path, payload, {
|
|
362
|
+
...entry.options,
|
|
363
|
+
mode: entry.mode ?? entry.options?.mode,
|
|
364
|
+
context: ctx
|
|
365
|
+
});
|
|
366
|
+
results[i] = {
|
|
367
|
+
path: entry.path,
|
|
368
|
+
success: true,
|
|
369
|
+
data: res.data
|
|
370
|
+
};
|
|
371
|
+
} catch (err) {
|
|
372
|
+
results[i] = toBatchEntryFailure(entry.path, err);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const succeeded = results.filter((r) => r?.success).length;
|
|
377
|
+
return {
|
|
378
|
+
results,
|
|
379
|
+
succeeded,
|
|
380
|
+
failed: results.length - succeeded
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
async batchDelete(entries, options) {
|
|
384
|
+
const ctx = this.withSelfContext(options ?? {}).context;
|
|
385
|
+
const results = new Array(entries.length);
|
|
386
|
+
for (const run of this.planOverlayRuns(entries.map((e) => e.path))) {
|
|
387
|
+
const provider = run.overlay?.provider;
|
|
388
|
+
if (run.overlay && provider && typeof provider.batchDelete === "function") {
|
|
389
|
+
const subEntries = run.indices.map((i) => ({
|
|
390
|
+
...entries[i],
|
|
391
|
+
path: subPath(entries[i].path, run.overlay.prefix),
|
|
392
|
+
options: {
|
|
393
|
+
...entries[i].options,
|
|
394
|
+
context: ctx
|
|
395
|
+
}
|
|
396
|
+
}));
|
|
397
|
+
try {
|
|
398
|
+
const r = await provider.batchDelete(subEntries, { context: ctx });
|
|
399
|
+
if (!Array.isArray(r?.results) || r.results.length !== subEntries.length) throw new Error(`Provider '${provider.name}' batchDelete returned ${r?.results?.length ?? 0} results for ${subEntries.length} entries`);
|
|
400
|
+
run.indices.forEach((i, j) => {
|
|
401
|
+
results[i] = {
|
|
402
|
+
...r.results[j],
|
|
403
|
+
path: entries[i].path
|
|
404
|
+
};
|
|
405
|
+
});
|
|
406
|
+
} catch (err) {
|
|
407
|
+
for (const i of run.indices) results[i] = toBatchEntryFailure(entries[i].path, err);
|
|
408
|
+
}
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
if (!run.overlay && typeof this.base.batchDelete === "function") {
|
|
412
|
+
if (this.isNetworkOrigin(ctx)) {
|
|
413
|
+
for (const i of run.indices) results[i] = toBatchEntryFailure(entries[i].path, this.forbiddenBaseWrite(entries[i].path));
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
const baseEntries = run.indices.map((i) => entries[i]);
|
|
417
|
+
const r = await this.base.batchDelete(baseEntries, { context: ctx });
|
|
418
|
+
run.indices.forEach((i, j) => {
|
|
419
|
+
results[i] = r.results[j];
|
|
420
|
+
});
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
for (const i of run.indices) {
|
|
424
|
+
const entry = entries[i];
|
|
425
|
+
try {
|
|
426
|
+
await this.delete(entry.path, {
|
|
427
|
+
...entry.options,
|
|
428
|
+
recursive: entry.recursive ?? entry.options?.recursive,
|
|
429
|
+
context: ctx
|
|
430
|
+
});
|
|
431
|
+
results[i] = {
|
|
432
|
+
path: entry.path,
|
|
433
|
+
success: true
|
|
434
|
+
};
|
|
435
|
+
} catch (err) {
|
|
436
|
+
results[i] = toBatchEntryFailure(entry.path, err);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const succeeded = results.filter((r) => r?.success).length;
|
|
441
|
+
return {
|
|
442
|
+
results,
|
|
443
|
+
succeeded,
|
|
444
|
+
failed: results.length - succeeded
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
async batchRead(entries, options) {
|
|
448
|
+
const ctx = this.withSelfContext(options ?? {}).context;
|
|
449
|
+
const results = [];
|
|
450
|
+
let succeeded = 0;
|
|
451
|
+
for (const entry of entries) try {
|
|
452
|
+
const res = await this.read(entry.path, {
|
|
453
|
+
...entry.options,
|
|
454
|
+
context: ctx
|
|
455
|
+
});
|
|
456
|
+
results.push({
|
|
457
|
+
path: entry.path,
|
|
458
|
+
success: true,
|
|
459
|
+
data: res.data
|
|
460
|
+
});
|
|
461
|
+
succeeded++;
|
|
462
|
+
} catch (err) {
|
|
463
|
+
results.push(toBatchEntryFailure(entry.path, err));
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
results,
|
|
467
|
+
succeeded,
|
|
468
|
+
failed: results.length - succeeded
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
async query(path, spec, options) {
|
|
472
|
+
const match = this.matchOverlay(path);
|
|
473
|
+
if (match) {
|
|
474
|
+
const { overlay, sub } = match;
|
|
475
|
+
if (!overlay.provider) this.rejectMissing(path);
|
|
476
|
+
if (!overlay.provider.query) throw new AFSUnsupportedError("query", `Provider for ${overlay.prefix} does not declare the collection query capability`);
|
|
477
|
+
const result = await overlay.provider.query(sub, spec, options);
|
|
478
|
+
if (!result?.entries?.length) return result;
|
|
479
|
+
return {
|
|
480
|
+
...result,
|
|
481
|
+
entries: result.entries.map((e) => ({
|
|
482
|
+
...e,
|
|
483
|
+
path: this.reprefix(overlay.prefix, e.path)
|
|
484
|
+
}))
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
if (!this.base.query) throw new AFSUnsupportedError("query", "base.query not supported");
|
|
488
|
+
return this.base.query(path, spec, options);
|
|
489
|
+
}
|
|
490
|
+
async stat(path, options) {
|
|
491
|
+
options = this.withSelfContext(options);
|
|
492
|
+
const match = this.matchOverlay(path);
|
|
493
|
+
if (match) {
|
|
494
|
+
const { overlay, sub } = match;
|
|
495
|
+
if (!overlay.provider) this.rejectMissing(path);
|
|
496
|
+
if (sub === "/") return { data: overlayRootEntry(overlay) };
|
|
497
|
+
if (!overlay.provider.stat) this.rejectMissing(path);
|
|
498
|
+
return overlay.provider.stat(sub, options);
|
|
499
|
+
}
|
|
500
|
+
if (!this.base.stat) throw new Error("base.stat not supported");
|
|
501
|
+
return this.base.stat(path, options);
|
|
502
|
+
}
|
|
503
|
+
async explain(path, options) {
|
|
504
|
+
const match = this.matchOverlay(path);
|
|
505
|
+
if (match) {
|
|
506
|
+
if (!match.overlay.provider?.explain) this.rejectMissing(path);
|
|
507
|
+
return match.overlay.provider.explain(match.sub, options);
|
|
508
|
+
}
|
|
509
|
+
if (!this.base.explain) throw new Error("base.explain not supported");
|
|
510
|
+
return this.base.explain(path, options);
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Find the `/user/index` overlay's backing provider, or undefined when
|
|
514
|
+
* unmounted (no `index:` manifest section) OR reserved-null (blocklet
|
|
515
|
+
* declares `index:` but this caller has no DID / no callerDid — see
|
|
516
|
+
* `createSessionView`'s `indexProvider` doc).
|
|
517
|
+
*/
|
|
518
|
+
findIndexOverlay() {
|
|
519
|
+
return this.overlays.find((o) => o.prefix === "/user/index" && o.provider != null);
|
|
520
|
+
}
|
|
521
|
+
isAfsValidationError(err) {
|
|
522
|
+
const error = err;
|
|
523
|
+
return error?.code === "AFS_VALIDATION_ERROR" || error?.name === "AFSValidationError";
|
|
524
|
+
}
|
|
525
|
+
isAfsDependencyError(err) {
|
|
526
|
+
const error = err;
|
|
527
|
+
return error?.code === "AFS_DEPENDENCY_MISSING" || error?.name === "AFSDependencyError";
|
|
528
|
+
}
|
|
529
|
+
searchDiagnostics(path, query, options) {
|
|
530
|
+
const context = options?.context;
|
|
531
|
+
const filters = Array.isArray(options?.filters) ? options.filters : [];
|
|
532
|
+
return {
|
|
533
|
+
path,
|
|
534
|
+
queryLength: query.length,
|
|
535
|
+
limit: options?.limit,
|
|
536
|
+
cursor: Boolean(options?.cursor),
|
|
537
|
+
filterCount: filters.length,
|
|
538
|
+
filterTypes: filters.map((f) => f.type),
|
|
539
|
+
requestId: context?.requestId,
|
|
540
|
+
callerDid: context?.caller?.did ?? context?.userId,
|
|
541
|
+
callerRole: context?.caller?.role ?? context?.caller?.roles,
|
|
542
|
+
instanceDid: context?.instanceDid
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
rejectIndexSearchFallback(path, detail, diagnostics) {
|
|
546
|
+
log.warn("[search] /user/index unavailable; refusing DID Space native fallback", {
|
|
547
|
+
...diagnostics,
|
|
548
|
+
path,
|
|
549
|
+
fallback: false,
|
|
550
|
+
detail
|
|
551
|
+
});
|
|
552
|
+
throw new AFSDependencyError("session-user-afs", "search", "/user/index", `${detail}; refusing DID Space native search fallback for indexed path ${path}`);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Parse a `read()`-returned raw content string as JSON, matching the exact
|
|
556
|
+
* fail-soft convention `IndexFollower.indexEntry` uses when hydrating
|
|
557
|
+
* changelog rows (`providers/basic/index/src/follower.ts`): non-string
|
|
558
|
+
* content is passed through untouched; a string that isn't valid JSON is
|
|
559
|
+
* kept as the raw string rather than dropped. afs-list's `performSearch`
|
|
560
|
+
* (P5 forward contract) expects a resolved `content` object for JSON
|
|
561
|
+
* entries — this is what makes that true without a second copy of the
|
|
562
|
+
* parse-or-passthrough logic living in the hydration loop below.
|
|
563
|
+
*/
|
|
564
|
+
parseEntryContent(raw) {
|
|
565
|
+
if (typeof raw !== "string") return raw;
|
|
566
|
+
try {
|
|
567
|
+
return JSON.parse(raw);
|
|
568
|
+
} catch {
|
|
569
|
+
return raw;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Hydrate index-query hits (`{ entryPath, score, matchType }` — path only,
|
|
574
|
+
* no content) into full `AFSEntry` objects by reading each `entryPath`
|
|
575
|
+
* through THIS session view (so the caller's own `/user` overlay + its
|
|
576
|
+
* per-caller isolation applies a second time, on top of the index query's
|
|
577
|
+
* own `boundDomains` isolation — belt-and-suspenders, not redundant: see
|
|
578
|
+
* design.md P5 section). A stale entry (index has it, storage doesn't —
|
|
579
|
+
* e.g. a delete that hasn't reached the follower yet) fails the `read()`
|
|
580
|
+
* and is skipped rather than surfaced as a broken result.
|
|
581
|
+
*/
|
|
582
|
+
async hydrateSearchEntries(results) {
|
|
583
|
+
if (results.length === 0) return [];
|
|
584
|
+
const build = (r, data) => ({
|
|
585
|
+
...data,
|
|
586
|
+
id: r.entryPath,
|
|
587
|
+
path: r.entryPath,
|
|
588
|
+
content: this.parseEntryContent(data.content),
|
|
589
|
+
meta: {
|
|
590
|
+
...data.meta ?? {},
|
|
591
|
+
score: r.score,
|
|
592
|
+
matchType: r.matchType,
|
|
593
|
+
...r.explanation !== void 0 ? { explanation: r.explanation } : {},
|
|
594
|
+
...r.anchors !== void 0 ? { anchors: r.anchors } : {}
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
const matches = results.map((r) => this.matchOverlay(r.entryPath));
|
|
598
|
+
const first = matches[0];
|
|
599
|
+
const provider = first?.overlay.provider;
|
|
600
|
+
if (first && provider?.batchRead && matches.every((m) => m?.overlay.prefix === first.overlay.prefix)) try {
|
|
601
|
+
const batch = await provider.batchRead(matches.map((m) => ({ path: m.sub })));
|
|
602
|
+
const out = [];
|
|
603
|
+
for (let i = 0; i < results.length; i++) {
|
|
604
|
+
const res = batch.results[i];
|
|
605
|
+
if (res?.success && res.data) out.push(build(results[i], res.data));
|
|
606
|
+
}
|
|
607
|
+
return out;
|
|
608
|
+
} catch (err) {
|
|
609
|
+
log.warn("[search] batch hydrate failed, falling back to per-entry read:", err);
|
|
610
|
+
}
|
|
611
|
+
return (await mapWithConcurrency(results, INDEX_SEARCH_HYDRATE_CONCURRENCY, async (r) => {
|
|
612
|
+
try {
|
|
613
|
+
const { data } = await this.read(r.entryPath);
|
|
614
|
+
if (!data) return null;
|
|
615
|
+
return build(r, data);
|
|
616
|
+
} catch (err) {
|
|
617
|
+
log.warn(`[search] index hit "${r.entryPath}" failed to read (stale?), skipping:`, err);
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
})).filter((e) => e != null);
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Search-verb forward contract (P5, design.md "search verb forwarding"):
|
|
624
|
+
* a `/user/**` search first tries the caller's semantic `/user/index`
|
|
625
|
+
* (when mounted with a real provider), scoping hits to the requested
|
|
626
|
+
* subtree and hydrating them with real content via `read()`. For blocklets
|
|
627
|
+
* whose manifest declares `index:`, the index is authoritative: failures are
|
|
628
|
+
* surfaced and DID Space native search is refused because it is an O(N)
|
|
629
|
+
* content scan. Legacy/no-index blocklets keep the old direct overlay search
|
|
630
|
+
* behavior. A successful empty index result is authoritative and returns an
|
|
631
|
+
* empty array. Index results and fallback results are never unioned. Any other
|
|
632
|
+
* overlay (`/user/index` addressed directly, `/tmp`, `/space`,
|
|
633
|
+
* `/instance/settings`, replication overlays) keeps its pre-existing
|
|
634
|
+
* single-overlay-search behavior unchanged.
|
|
635
|
+
*/
|
|
636
|
+
async search(path, query, options) {
|
|
637
|
+
const match = this.matchOverlay(path);
|
|
638
|
+
if (!match) return this.base.search(path, query, options);
|
|
639
|
+
const { overlay, sub } = match;
|
|
640
|
+
if (overlay.prefix === "/user") {
|
|
641
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
642
|
+
const diagnostics = this.searchDiagnostics(normalizedPath, query, options);
|
|
643
|
+
const indexProvider = this.findIndexOverlay()?.provider;
|
|
644
|
+
if (indexProvider?.exec) try {
|
|
645
|
+
const limit = options?.limit ?? 50;
|
|
646
|
+
const prefix = normalizedPath.endsWith("/") ? normalizedPath : `${normalizedPath}/`;
|
|
647
|
+
const filters = options?.filters;
|
|
648
|
+
const hasFilters = Array.isArray(filters) && filters.length > 0;
|
|
649
|
+
const explain = options?.explain === true;
|
|
650
|
+
const execResult = await indexProvider.exec("/.actions/query", {
|
|
651
|
+
text: query,
|
|
652
|
+
...hasFilters ? { anchors: filters } : {},
|
|
653
|
+
...options?.mode ? { mode: options.mode } : {},
|
|
654
|
+
opts: {
|
|
655
|
+
limit,
|
|
656
|
+
...options?.cursor ? { cursor: options.cursor } : {},
|
|
657
|
+
pathPrefix: prefix,
|
|
658
|
+
...hasFilters ? { anchorFilter: true } : {},
|
|
659
|
+
...explain ? { explain: true } : {}
|
|
660
|
+
}
|
|
661
|
+
}, { context: options?.context });
|
|
662
|
+
if (execResult.success) {
|
|
663
|
+
const raw = execResult.data ?? {};
|
|
664
|
+
const scoped = (raw.results ?? []).filter((r) => r.entryPath === normalizedPath || r.entryPath.startsWith(prefix));
|
|
665
|
+
if (scoped.length > 0) {
|
|
666
|
+
const hydrated = await this.hydrateSearchEntries(scoped);
|
|
667
|
+
log.debug("[search] /user/index query served", {
|
|
668
|
+
...diagnostics,
|
|
669
|
+
rawResults: raw.results?.length ?? 0,
|
|
670
|
+
scopedResults: scoped.length,
|
|
671
|
+
hydratedResults: hydrated.length,
|
|
672
|
+
fallback: false
|
|
673
|
+
});
|
|
674
|
+
return {
|
|
675
|
+
data: hydrated,
|
|
676
|
+
...raw.meta ? { meta: raw.meta } : {}
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
log.debug("[search] /user/index query returned no scoped results", {
|
|
680
|
+
...diagnostics,
|
|
681
|
+
rawResults: raw.results?.length ?? 0,
|
|
682
|
+
scopedResults: 0,
|
|
683
|
+
fallback: false
|
|
684
|
+
});
|
|
685
|
+
return {
|
|
686
|
+
data: [],
|
|
687
|
+
...raw.meta ? { meta: raw.meta } : {}
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
const indexError = execResult.error;
|
|
691
|
+
const failedCode = typeof indexError === "object" && indexError ? indexError.code : void 0;
|
|
692
|
+
const failedMessage = typeof indexError === "object" && indexError ? indexError.message ?? "index query failed" : indexError ?? "index query failed";
|
|
693
|
+
if (failedCode === "VALIDATION_ERROR" || failedCode === "AFS_VALIDATION_ERROR") {
|
|
694
|
+
log.warn("[search] /user/index query validation failed", {
|
|
695
|
+
...diagnostics,
|
|
696
|
+
code: failedCode,
|
|
697
|
+
error: failedMessage,
|
|
698
|
+
fallback: false
|
|
699
|
+
});
|
|
700
|
+
throw new AFSValidationError(failedMessage);
|
|
701
|
+
}
|
|
702
|
+
if (options?.cursor) throw new AFSValidationError(failedMessage);
|
|
703
|
+
if (this.indexSearchRequired) this.rejectIndexSearchFallback(normalizedPath, `index query failed${failedCode ? ` (${failedCode})` : ""}: ${failedMessage}`, diagnostics);
|
|
704
|
+
log.warn("[search] /user/index query failed, falling back to native search", {
|
|
705
|
+
...diagnostics,
|
|
706
|
+
code: failedCode,
|
|
707
|
+
error: failedMessage,
|
|
708
|
+
fallback: true
|
|
709
|
+
});
|
|
710
|
+
} catch (err) {
|
|
711
|
+
if (options?.cursor) throw err;
|
|
712
|
+
if (this.isAfsValidationError(err) || this.isAfsDependencyError(err)) throw err;
|
|
713
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
714
|
+
if (this.indexSearchRequired) this.rejectIndexSearchFallback(normalizedPath, `index query threw: ${message}`, diagnostics);
|
|
715
|
+
log.warn("[search] /user/index query threw, falling back to native search", {
|
|
716
|
+
...diagnostics,
|
|
717
|
+
error: message,
|
|
718
|
+
fallback: true
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
else if (this.indexSearchRequired) this.rejectIndexSearchFallback(normalizedPath, "index provider unavailable", diagnostics);
|
|
722
|
+
}
|
|
723
|
+
if (!overlay.provider?.search) return { data: [] };
|
|
724
|
+
return overlay.provider.search(sub, query, options);
|
|
725
|
+
}
|
|
726
|
+
async exec(path, args, options) {
|
|
727
|
+
options = this.withSelfContext(options);
|
|
728
|
+
const match = this.matchOverlay(path);
|
|
729
|
+
if (match) {
|
|
730
|
+
if (!match.overlay.provider?.exec) this.rejectMissing(path);
|
|
731
|
+
return match.overlay.provider.exec(match.sub, args, options);
|
|
732
|
+
}
|
|
733
|
+
if (isReflexiveRootDataAction(path)) {
|
|
734
|
+
const context = options?.context;
|
|
735
|
+
enforceEffectGate({
|
|
736
|
+
effect: rootActionEffect(path.slice(10)) ?? "write",
|
|
737
|
+
context,
|
|
738
|
+
face: "session-reflexive",
|
|
739
|
+
path
|
|
740
|
+
});
|
|
741
|
+
const reflexiveAction = path.slice(10);
|
|
742
|
+
if ((reflexiveAction === "write" || reflexiveAction === "delete") && typeof args.path === "string" && !this.matchOverlay(args.path)) this.enforceBaseWriteGate(args.path, context);
|
|
743
|
+
const ctxOpts = context ? { context } : void 0;
|
|
744
|
+
return execReflexiveRootDataAction(path, args, {
|
|
745
|
+
read: (p) => this.read(p, ctxOpts),
|
|
746
|
+
list: (p) => this.list(p, ctxOpts),
|
|
747
|
+
query: (p, spec, o) => this.query(p, spec, {
|
|
748
|
+
...o,
|
|
749
|
+
...ctxOpts ?? {}
|
|
750
|
+
}),
|
|
751
|
+
write: (p, c, o) => this.write(p, c, {
|
|
752
|
+
...o,
|
|
753
|
+
...ctxOpts ?? {}
|
|
754
|
+
}),
|
|
755
|
+
delete: (p, o) => this.delete(p, {
|
|
756
|
+
...o,
|
|
757
|
+
...ctxOpts ?? {}
|
|
758
|
+
})
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
if (!this.base.exec) throw new Error("base.exec not supported");
|
|
762
|
+
return this.base.exec(path, args, options);
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Inject `context.afs = this` so downstream provider handlers that call
|
|
766
|
+
* back into AFS (`ctx.context.afs.read`/`.write`/`.exec`/...) hit this
|
|
767
|
+
* overlaid session view — not the bare runtime root the provider was
|
|
768
|
+
* mounted into. Without this, the `/user` overlay (and any other per-
|
|
769
|
+
* caller overlay) is invisible to handler-internal AFS calls, so writes
|
|
770
|
+
* silently land on the global `/user` fs mount instead of the caller's
|
|
771
|
+
* DID-Space-projected `/user`.
|
|
772
|
+
*/
|
|
773
|
+
withSelfContext(options) {
|
|
774
|
+
const ctx = options?.context ?? {};
|
|
775
|
+
return {
|
|
776
|
+
...options ?? {},
|
|
777
|
+
context: {
|
|
778
|
+
...ctx,
|
|
779
|
+
afs: this
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
subscribe(filter, callback) {
|
|
784
|
+
const rawPath = typeof filter.path === "string" ? filter.path : "";
|
|
785
|
+
const normalized = rawPath ? rawPath.startsWith("/") ? rawPath : `/${rawPath}` : "";
|
|
786
|
+
if (normalized && normalized !== "/") {
|
|
787
|
+
const match = this.matchOverlay(normalized);
|
|
788
|
+
if (match) return this.subscribeOverlay(match.overlay, {
|
|
789
|
+
...filter,
|
|
790
|
+
path: match.sub
|
|
791
|
+
}, callback);
|
|
792
|
+
if (!this.base.subscribe) return () => {};
|
|
793
|
+
return this.base.subscribe(filter, callback);
|
|
794
|
+
}
|
|
795
|
+
const unsubs = [];
|
|
796
|
+
if (this.base.subscribe) unsubs.push(this.base.subscribe(filter, callback));
|
|
797
|
+
for (const overlay of this.activeOverlays) unsubs.push(this.subscribeOverlay(overlay, {
|
|
798
|
+
...filter,
|
|
799
|
+
path: "/"
|
|
800
|
+
}, callback));
|
|
801
|
+
return () => {
|
|
802
|
+
for (const u of unsubs) try {
|
|
803
|
+
u();
|
|
804
|
+
} catch {}
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Subscribe one overlay's backing provider, re-prefixing bridged event paths
|
|
809
|
+
* back into the overlay namespace. No-op when the overlay is unbacked
|
|
810
|
+
* (anonymous `/user`) or its provider lacks `subscribe`.
|
|
811
|
+
*/
|
|
812
|
+
subscribeOverlay(overlay, filter, callback) {
|
|
813
|
+
const subscribe = overlay.provider?.subscribe;
|
|
814
|
+
if (!subscribe) return () => {};
|
|
815
|
+
return subscribe.call(overlay.provider, filter, (evt) => {
|
|
816
|
+
callback({
|
|
817
|
+
...evt,
|
|
818
|
+
path: this.reprefix(overlay.prefix, evt.path)
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
async beginRender(renderId) {
|
|
823
|
+
await this.settingsResolver?.beginRender?.(renderId);
|
|
824
|
+
}
|
|
825
|
+
endRender(renderId) {
|
|
826
|
+
this.settingsResolver?.endRender?.(renderId);
|
|
827
|
+
}
|
|
828
|
+
getMounts(namespace) {
|
|
829
|
+
const baseGetMounts = this.base.getMounts;
|
|
830
|
+
const mounts = [...baseGetMounts ? baseGetMounts.call(this.base, namespace) : []];
|
|
831
|
+
for (const overlay of this.rootOverlays) mounts.push({
|
|
832
|
+
namespace: namespace ?? null,
|
|
833
|
+
path: overlay.prefix,
|
|
834
|
+
module: overlay.provider,
|
|
835
|
+
status: "ready"
|
|
836
|
+
});
|
|
837
|
+
return mounts;
|
|
838
|
+
}
|
|
839
|
+
initializePhysicalPath(...args) {
|
|
840
|
+
return this.base.initializePhysicalPath(...args);
|
|
841
|
+
}
|
|
842
|
+
cleanupPhysicalPath(...args) {
|
|
843
|
+
return this.base.cleanupPhysicalPath(...args);
|
|
844
|
+
}
|
|
845
|
+
setEventSink(...args) {
|
|
846
|
+
this.base.setEventSink?.(...args);
|
|
847
|
+
}
|
|
848
|
+
setSecretCapability(...args) {
|
|
849
|
+
this.base.setSecretCapability?.(...args);
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
/**
|
|
853
|
+
* Assemble a caller's per-session view: a SettingsResolver (instance+user
|
|
854
|
+
* settings cascade, role-aware) wrapped by a SessionUserAFS (`/user` +
|
|
855
|
+
* optional `/space` + `/tmp` + `/instance/settings`). This is the construction the daemon's
|
|
856
|
+
* `buildSessionView` chokepoint delegates to — extracted so the role→resolver
|
|
857
|
+
* wiring is unit-testable in isolation (the daemon's only remaining job is to
|
|
858
|
+
* RESOLVE `role` from the verified session before calling this).
|
|
859
|
+
*
|
|
860
|
+
* The resolver always exists (even for anonymous / no role) so
|
|
861
|
+
* `/instance/settings` carries correct capability hints + enforcement for every
|
|
862
|
+
* caller — there is no bypass path.
|
|
863
|
+
*/
|
|
864
|
+
function createSessionView(opts) {
|
|
865
|
+
const settingsResolver = new SettingsResolver({
|
|
866
|
+
base: opts.base,
|
|
867
|
+
userProvider: opts.userProvider,
|
|
868
|
+
role: opts.role,
|
|
869
|
+
sessionId: opts.sessionId,
|
|
870
|
+
schema: opts.settingsSchema
|
|
871
|
+
});
|
|
872
|
+
let replicationOverlays;
|
|
873
|
+
if (opts.replicated && Object.keys(opts.replicated).length > 0) {
|
|
874
|
+
const mountPrefix = computeReplicationMountPrefix(opts.replicated);
|
|
875
|
+
const resolver = new ReplicationResolver({
|
|
876
|
+
collections: opts.replicated,
|
|
877
|
+
instanceBackend: opts.base,
|
|
878
|
+
userBackend: opts.userProvider,
|
|
879
|
+
settingsResolver,
|
|
880
|
+
callerDid: opts.callerDid ?? void 0,
|
|
881
|
+
callerRole: opts.role,
|
|
882
|
+
sessionId: opts.sessionId,
|
|
883
|
+
mountPrefix
|
|
884
|
+
});
|
|
885
|
+
replicationOverlays = [{
|
|
886
|
+
prefix: `/${mountPrefix}`,
|
|
887
|
+
id: "replication",
|
|
888
|
+
provider: resolver
|
|
889
|
+
}];
|
|
890
|
+
}
|
|
891
|
+
return new SessionUserAFS(opts.base, opts.userProvider, opts.tmpProvider, opts.sessionId, settingsResolver, opts.spaceProvider, opts.indexProvider, replicationOverlays, opts.indexSearchRequired ?? opts.indexProvider != null);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
//#endregion
|
|
895
|
+
export { SESSION_OVERLAY_PREFIXES, SessionUserAFS, assertOverlayOrder, createSessionView, isSessionPrivatePath };
|
|
896
|
+
//# sourceMappingURL=session-user-afs.mjs.map
|