@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,264 @@
|
|
|
1
|
+
import { createAfsRequestContext } from "./request-context.mjs";
|
|
2
|
+
import { statusForError } from "./afs-rpc.mjs";
|
|
3
|
+
import { verifyRawUrl } from "./raw-url.mjs";
|
|
4
|
+
import { sanitizeAfsPath } from "@aigne/afs";
|
|
5
|
+
import { detectMimeType } from "@aigne/afs-provider-utils";
|
|
6
|
+
|
|
7
|
+
//#region src/http/afs-raw.ts
|
|
8
|
+
/**
|
|
9
|
+
* `GET /api/afs/raw` — raw-bytes endpoint (afs-preview T2.1, design §3).
|
|
10
|
+
*
|
|
11
|
+
* Lets `<img>` / `<iframe>` / `<video>` reference AFS content that is too
|
|
12
|
+
* large to inline as a data URL. AFS-Only I/O: the handler speaks ONLY the
|
|
13
|
+
* scoped AFS API (`stat` + `read`) — never CAS/R2/disk.
|
|
14
|
+
*
|
|
15
|
+
* TWO auth modes (afs-raw cookie mode):
|
|
16
|
+
* - SIGNED (sig query present): a bearer URL whose HMAC binds
|
|
17
|
+
* path+sid+caller+blocklet (raw-url.ts). The ONLY mode that can serve an
|
|
18
|
+
* anonymous caller or a cookie-less context — sandboxed PDF iframe (no
|
|
19
|
+
* `allow-same-origin` ⇒ null origin ⇒ no cookie), cross-origin embeds,
|
|
20
|
+
* public share links. Issued server-side because signing needs the secret.
|
|
21
|
+
* - COOKIE (no sig): a same-origin AUTHENTICATED GET — feed/list `<img>`
|
|
22
|
+
* cards. Identity is the verified session cookie (resolveCaller); the
|
|
23
|
+
* scoped `/user` overlay grants the SAME read authz as afs-rpc, so no
|
|
24
|
+
* bearer URL is minted. `SameSite=Lax` on the session cookie means a
|
|
25
|
+
* cross-site subresource (`<img>` from another origin) carries NO cookie ⇒
|
|
26
|
+
* 401/403, so this can't be hotlinked/CSRF'd; and the only cross-site case
|
|
27
|
+
* Lax DOES allow (top-level nav) only ever exposes the caller's OWN `/user`
|
|
28
|
+
* space to themselves. Anonymous (no cookie) is refused here — an
|
|
29
|
+
* unauthenticated reader must use a signed URL. No per-render server
|
|
30
|
+
* pre-signing, no `exp` churn ⇒ the URL is stable (cacheable later).
|
|
31
|
+
*
|
|
32
|
+
* Processing order (the contract — every step fail-closed):
|
|
33
|
+
* 1. method gate (GET) → 405
|
|
34
|
+
* 2. signing secret present? → else 503 (no signing = no endpoint)
|
|
35
|
+
* 3. cookie caller resolution (anonymous OK in SIGNED mode — symmetry is
|
|
36
|
+
* enforced by the signature, see raw-url.ts)
|
|
37
|
+
* 4. auth: SIGNED → `verifyRawUrl` (sig/exp/caller-binding/anonymous-
|
|
38
|
+
* private-path) any failure → 403; COOKIE → require non-anonymous caller
|
|
39
|
+
* (else 403) + `?path=` (else 400)
|
|
40
|
+
* 5. `sanitizeAfsPath` (single shared entry — no local normalize/reorder)
|
|
41
|
+
* → 400
|
|
42
|
+
* 6. blocklet resolution (query/host alias/first-label) → 400
|
|
43
|
+
* 7. scoped AFS via the shared request-context helper. SIGNED passes the
|
|
44
|
+
* EXPLICIT signature-verified sessionId (never a `rpc-<blocklet>`-style
|
|
45
|
+
* fallback); COOKIE passes null (the `/user` overlay keys on caller.did)
|
|
46
|
+
* 8a. media-302 (preview-r2-direct): MEDIA (image/video/audio) over
|
|
47
|
+
* `RAW_REDIRECT_MIN_BYTES` with a presign-capable scoped AFS → 302 to a
|
|
48
|
+
* presigned R2 GET. Runs AFTER the size-validity check but BEFORE the
|
|
49
|
+
* `maxBytes` cap (cap-exempt — R2's ceiling is the object size); the
|
|
50
|
+
* worker never buffers these bytes. Falls through to 8b on null.
|
|
51
|
+
* 8b. `afs.stat` size cap — over `maxBytes` → 413 BEFORE any read; size
|
|
52
|
+
* missing → conservative 413 (read-after-judge would defeat the memory
|
|
53
|
+
* guardrail)
|
|
54
|
+
* 9. `afs.read` → bytes → response with `Content-Type` (meta.mimeType,
|
|
55
|
+
* fallback shared detectMimeType), `X-Content-Type-Options: nosniff`
|
|
56
|
+
* (mandatory — binary serving endpoint), `Cache-Control: private,
|
|
57
|
+
* no-store`. #818: a CLIENT-DECLARED browser-scriptable type
|
|
58
|
+
* (`isScriptableMimeType`: text/html, image/svg+xml, xml, JS variants) is
|
|
59
|
+
* NEVER served inline — forced to `application/octet-stream` +
|
|
60
|
+
* `Content-Disposition: attachment` + CSP sandbox + `X-Frame-Options: DENY`
|
|
61
|
+
* (nosniff alone can't stop a genuinely-declared scriptable type executing).
|
|
62
|
+
*
|
|
63
|
+
* Cache semantics: this handler owns its OWN request-context instance —
|
|
64
|
+
* code shared with afs-rpc, runtime state (projection cache) NOT shared.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Default max served size — 100 MiB (413 above; streaming/Range is a separate
|
|
68
|
+
* project). upload-limits Phase 6 (D4 interim): raised 50→100 MiB to ALIGN with
|
|
69
|
+
* the grant upload cap (`AFS_DID_SPACE_UPLOAD_MAX_BYTES`, 100 MiB) so a file the
|
|
70
|
+
* upload plane accepts can be raw-served, closing the G4 upload/serve asymmetry
|
|
71
|
+
* for the worker-serve path. This is the NODE/default ceiling (Node can buffer
|
|
72
|
+
* 100 MiB once). It is NOT runtime-uniform: the CF Worker passes a much smaller
|
|
73
|
+
* `maxBytes` (~4 MiB, preview-r2-direct's runtime-aware clean-413) because a
|
|
74
|
+
* one-shot read of ≳8 MiB OOMs the worker (Error 1102 → 503); CF non-media over
|
|
75
|
+
* that gets a CLEAN 413 (never a crash), and CF MEDIA over the gate is exempt via
|
|
76
|
+
* the 302→R2-direct path above. The 50→100 doubling of one-shot read memory on
|
|
77
|
+
* Node is the known interim cost; true large serve needs streaming/Range.
|
|
78
|
+
*/
|
|
79
|
+
const RAW_MAX_BYTES_DEFAULT = 100 * 1024 * 1024;
|
|
80
|
+
/**
|
|
81
|
+
* Media over this size redirect (302) to a presigned object-store GET instead of
|
|
82
|
+
* being served by the worker (preview-r2-direct §4 / Review-B). v1 = 32 KB, locked
|
|
83
|
+
* equal to `PREVIEW_IMAGE_INLINE_MAX` (the user-locked "> 32 KB → R2-direct"
|
|
84
|
+
* decision; maximizes worker-offload). The correctness floor is the worker cliff
|
|
85
|
+
* (~4–8 MiB); anything below is a worker-offload-vs-first-byte-latency CHOICE, and
|
|
86
|
+
* a future raise is a measurement-gated, OPTIONAL post-ship activity — NOT a gate.
|
|
87
|
+
*/
|
|
88
|
+
const RAW_REDIRECT_MIN_BYTES = 32 * 1024;
|
|
89
|
+
/**
|
|
90
|
+
* The 302 path is MEDIA-ONLY (preview-r2-direct §5 / Review-1): only `image/*`,
|
|
91
|
+
* `video/*`, `audio/*` are script-safe to redirect cross-origin to R2 (the
|
|
92
|
+
* presigned URL drops `nosniff`; a media element never executes mislabeled
|
|
93
|
+
* bytes). SVG (`image/svg+xml`) matches `image/*` here but is EXCLUDED from the
|
|
94
|
+
* redirect at the call site via `isScriptableMimeType` (#818 supersedes the old
|
|
95
|
+
* Review-A "SVG rides image/*" behavior): a scripted SVG is browser-scriptable,
|
|
96
|
+
* so it falls through to worker-serve, which forces a safe attachment. PDF/HTML/
|
|
97
|
+
* text MUST stay on the worker (iframe `noSandbox`/`_isSameOriginUrl` depends on
|
|
98
|
+
* same-origin + nosniff; text is client-rendered → `fetch` → CORS-gated).
|
|
99
|
+
*/
|
|
100
|
+
function isRedirectableMediaType(mime) {
|
|
101
|
+
const m = mime.toLowerCase();
|
|
102
|
+
return m.startsWith("image/") || m.startsWith("video/") || m.startsWith("audio/");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Browser-scriptable MIME types (#818). `meta.mimeType` is CLIENT-CONTROLLED —
|
|
106
|
+
* any writer can declare it, there is no write-side allowlist, and this endpoint
|
|
107
|
+
* serves anonymous bearer URLs (public share links). If we echo a declared
|
|
108
|
+
* scriptable type as an inline `Content-Type`, the bytes execute in the serving
|
|
109
|
+
* origin → stored XSS. `X-Content-Type-Options: nosniff` does NOT help here: it
|
|
110
|
+
* only stops sniffing of MIS-labeled bytes; a GENUINELY-declared `text/html`
|
|
111
|
+
* (or scripted `image/svg+xml`) still runs. So at the serve boundary — the
|
|
112
|
+
* provider-agnostic place — these are forced to a non-executing disposition
|
|
113
|
+
* (octet-stream + `Content-Disposition: attachment`) and can never render inline.
|
|
114
|
+
*
|
|
115
|
+
* SVG is included: rendered inline (top-level nav / `<embed>`/`<object>`) a
|
|
116
|
+
* scripted SVG executes same-origin. It is ALSO excluded from the 302→R2 media
|
|
117
|
+
* redirect below (falls through to worker-serve, which forces attachment).
|
|
118
|
+
*/
|
|
119
|
+
const SCRIPTABLE_MIME_TYPES = new Set([
|
|
120
|
+
"text/html",
|
|
121
|
+
"application/xhtml+xml",
|
|
122
|
+
"image/svg+xml",
|
|
123
|
+
"text/xml",
|
|
124
|
+
"application/xml",
|
|
125
|
+
"text/javascript",
|
|
126
|
+
"application/javascript",
|
|
127
|
+
"application/x-javascript",
|
|
128
|
+
"text/ecmascript",
|
|
129
|
+
"application/ecmascript",
|
|
130
|
+
"application/x-ecmascript"
|
|
131
|
+
]);
|
|
132
|
+
/** True when a MIME type can execute script if rendered inline (#818). */
|
|
133
|
+
function isScriptableMimeType(mime) {
|
|
134
|
+
const base = mime.toLowerCase().split(";", 1)[0]?.trim() ?? "";
|
|
135
|
+
return SCRIPTABLE_MIME_TYPES.has(base);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A header-safe `filename` for `Content-Disposition: attachment` (#818). The
|
|
139
|
+
* path is already `sanitizeAfsPath`-clean (no traversal), but strip quotes /
|
|
140
|
+
* backslashes / CR-LF defensively so the value can never break out of the
|
|
141
|
+
* header or inject a second directive.
|
|
142
|
+
*/
|
|
143
|
+
function attachmentFilename(path) {
|
|
144
|
+
return (path.split("/").pop() || "download").replace(/["\\\r\n]/g, "_") || "download";
|
|
145
|
+
}
|
|
146
|
+
const RAW_HEADERS_BASE = {
|
|
147
|
+
"X-Content-Type-Options": "nosniff",
|
|
148
|
+
"Cache-Control": "private, no-store"
|
|
149
|
+
};
|
|
150
|
+
function deny(status, text) {
|
|
151
|
+
return new Response(text, {
|
|
152
|
+
status,
|
|
153
|
+
headers: {
|
|
154
|
+
...RAW_HEADERS_BASE,
|
|
155
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/** Normalize an AFS read result's content to raw bytes. Null = no bytes. */
|
|
160
|
+
function contentToBytes(content, encoding) {
|
|
161
|
+
if (content instanceof Uint8Array) return content;
|
|
162
|
+
if (content instanceof ArrayBuffer) return new Uint8Array(content);
|
|
163
|
+
if (typeof content === "string") {
|
|
164
|
+
if (encoding === "base64") try {
|
|
165
|
+
return Uint8Array.from(atob(content), (c) => c.charCodeAt(0));
|
|
166
|
+
} catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
return new TextEncoder().encode(content);
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
function createAfsRawHandler(options) {
|
|
174
|
+
const reqCtx = createAfsRequestContext(options);
|
|
175
|
+
const maxBytes = options.maxBytes ?? RAW_MAX_BYTES_DEFAULT;
|
|
176
|
+
return async function handleRaw(request) {
|
|
177
|
+
try {
|
|
178
|
+
return await handleInner(request);
|
|
179
|
+
} catch (err) {
|
|
180
|
+
return deny(statusForError(err), "Internal error");
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
async function handleInner(request) {
|
|
184
|
+
if (request.method !== "GET") return deny(405, "Method Not Allowed (use GET)");
|
|
185
|
+
const secret = options.rawUrlSecret;
|
|
186
|
+
if (!secret || typeof secret === "string" && secret.length === 0) return deny(503, "raw endpoint unavailable (signing key not configured)");
|
|
187
|
+
const caller = await reqCtx.resolveCaller(request);
|
|
188
|
+
const callerDid = caller?.did ?? null;
|
|
189
|
+
const url = new URL(request.url);
|
|
190
|
+
const hasSignature = url.searchParams.has("sig");
|
|
191
|
+
let rawPath;
|
|
192
|
+
let sessionId;
|
|
193
|
+
let signedBlocklet;
|
|
194
|
+
if (hasSignature) {
|
|
195
|
+
const verdict = await verifyRawUrl(request, callerDid, { secret });
|
|
196
|
+
if (!verdict.ok) return deny(403, "Forbidden");
|
|
197
|
+
rawPath = verdict.path;
|
|
198
|
+
sessionId = verdict.sessionId;
|
|
199
|
+
signedBlocklet = verdict.blocklet;
|
|
200
|
+
} else {
|
|
201
|
+
if (!callerDid) return deny(403, "Forbidden");
|
|
202
|
+
const qPath = url.searchParams.get("path");
|
|
203
|
+
if (!qPath) return deny(400, "Invalid path");
|
|
204
|
+
rawPath = qPath;
|
|
205
|
+
sessionId = null;
|
|
206
|
+
signedBlocklet = url.searchParams.get("blocklet");
|
|
207
|
+
}
|
|
208
|
+
const safePath = sanitizeAfsPath(rawPath);
|
|
209
|
+
if (safePath === null) return deny(400, "Invalid path");
|
|
210
|
+
const blocklet = await reqCtx.resolveBlocklet(request, signedBlocklet);
|
|
211
|
+
if (!blocklet) return deny(400, "Could not resolve blocklet");
|
|
212
|
+
const scoped = await reqCtx.resolveScoped(request, {
|
|
213
|
+
blocklet,
|
|
214
|
+
sessionId,
|
|
215
|
+
caller
|
|
216
|
+
});
|
|
217
|
+
if (!scoped.afs.stat || !scoped.afs.read) return deny(501, "stat/read not supported");
|
|
218
|
+
const statData = (await scoped.afs.stat(safePath, { context: scoped.context }))?.data ?? {};
|
|
219
|
+
const meta = statData.meta ?? {};
|
|
220
|
+
const size = typeof statData.size === "number" ? statData.size : typeof meta.size === "number" ? meta.size : void 0;
|
|
221
|
+
if (typeof size !== "number" || !Number.isFinite(size) || size < 0) return deny(413, "Content size unknown");
|
|
222
|
+
const statMimeType = typeof meta.mimeType === "string" && meta.mimeType || detectMimeType(safePath) || "application/octet-stream";
|
|
223
|
+
if (size > RAW_REDIRECT_MIN_BYTES && isRedirectableMediaType(statMimeType) && !isScriptableMimeType(statMimeType) && typeof scoped.afs.presignRead === "function") {
|
|
224
|
+
let grant = null;
|
|
225
|
+
try {
|
|
226
|
+
grant = await scoped.afs.presignRead(safePath, { responseContentType: statMimeType });
|
|
227
|
+
} catch {
|
|
228
|
+
grant = null;
|
|
229
|
+
}
|
|
230
|
+
if (grant) return new Response(null, {
|
|
231
|
+
status: 302,
|
|
232
|
+
headers: {
|
|
233
|
+
Location: grant.url,
|
|
234
|
+
"Cache-Control": "private, no-store",
|
|
235
|
+
"Referrer-Policy": "no-referrer"
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
if (size > maxBytes) return deny(413, "Content too large");
|
|
240
|
+
const data = (await scoped.afs.read(safePath, { context: scoped.context }))?.data ?? {};
|
|
241
|
+
const encoding = data.encoding ?? (data.meta?.contentType === "base64" || data.meta?.encoding === "base64" ? "base64" : void 0);
|
|
242
|
+
const bytes = contentToBytes(data.content, encoding);
|
|
243
|
+
if (!bytes) return deny(404, "No content");
|
|
244
|
+
const mimeType = typeof meta.mimeType === "string" && meta.mimeType || typeof data.meta?.mimeType === "string" && data.meta.mimeType || detectMimeType(safePath) || "application/octet-stream";
|
|
245
|
+
const headers = {
|
|
246
|
+
...RAW_HEADERS_BASE,
|
|
247
|
+
"Content-Length": String(bytes.length)
|
|
248
|
+
};
|
|
249
|
+
if (isScriptableMimeType(mimeType)) {
|
|
250
|
+
headers["Content-Type"] = "application/octet-stream";
|
|
251
|
+
headers["Content-Disposition"] = `attachment; filename="${attachmentFilename(safePath)}"`;
|
|
252
|
+
headers["Content-Security-Policy"] = "default-src 'none'; sandbox";
|
|
253
|
+
headers["X-Frame-Options"] = "DENY";
|
|
254
|
+
} else headers["Content-Type"] = mimeType;
|
|
255
|
+
return new Response(bytes, {
|
|
256
|
+
status: 200,
|
|
257
|
+
headers
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
//#endregion
|
|
263
|
+
export { RAW_MAX_BYTES_DEFAULT, createAfsRawHandler };
|
|
264
|
+
//# sourceMappingURL=afs-raw.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"afs-raw.mjs","names":[],"sources":["../../src/http/afs-raw.ts"],"sourcesContent":["/**\n * `GET /api/afs/raw` — raw-bytes endpoint (afs-preview T2.1, design §3).\n *\n * Lets `<img>` / `<iframe>` / `<video>` reference AFS content that is too\n * large to inline as a data URL. AFS-Only I/O: the handler speaks ONLY the\n * scoped AFS API (`stat` + `read`) — never CAS/R2/disk.\n *\n * TWO auth modes (afs-raw cookie mode):\n * - SIGNED (sig query present): a bearer URL whose HMAC binds\n * path+sid+caller+blocklet (raw-url.ts). The ONLY mode that can serve an\n * anonymous caller or a cookie-less context — sandboxed PDF iframe (no\n * `allow-same-origin` ⇒ null origin ⇒ no cookie), cross-origin embeds,\n * public share links. Issued server-side because signing needs the secret.\n * - COOKIE (no sig): a same-origin AUTHENTICATED GET — feed/list `<img>`\n * cards. Identity is the verified session cookie (resolveCaller); the\n * scoped `/user` overlay grants the SAME read authz as afs-rpc, so no\n * bearer URL is minted. `SameSite=Lax` on the session cookie means a\n * cross-site subresource (`<img>` from another origin) carries NO cookie ⇒\n * 401/403, so this can't be hotlinked/CSRF'd; and the only cross-site case\n * Lax DOES allow (top-level nav) only ever exposes the caller's OWN `/user`\n * space to themselves. Anonymous (no cookie) is refused here — an\n * unauthenticated reader must use a signed URL. No per-render server\n * pre-signing, no `exp` churn ⇒ the URL is stable (cacheable later).\n *\n * Processing order (the contract — every step fail-closed):\n * 1. method gate (GET) → 405\n * 2. signing secret present? → else 503 (no signing = no endpoint)\n * 3. cookie caller resolution (anonymous OK in SIGNED mode — symmetry is\n * enforced by the signature, see raw-url.ts)\n * 4. auth: SIGNED → `verifyRawUrl` (sig/exp/caller-binding/anonymous-\n * private-path) any failure → 403; COOKIE → require non-anonymous caller\n * (else 403) + `?path=` (else 400)\n * 5. `sanitizeAfsPath` (single shared entry — no local normalize/reorder)\n * → 400\n * 6. blocklet resolution (query/host alias/first-label) → 400\n * 7. scoped AFS via the shared request-context helper. SIGNED passes the\n * EXPLICIT signature-verified sessionId (never a `rpc-<blocklet>`-style\n * fallback); COOKIE passes null (the `/user` overlay keys on caller.did)\n * 8a. media-302 (preview-r2-direct): MEDIA (image/video/audio) over\n * `RAW_REDIRECT_MIN_BYTES` with a presign-capable scoped AFS → 302 to a\n * presigned R2 GET. Runs AFTER the size-validity check but BEFORE the\n * `maxBytes` cap (cap-exempt — R2's ceiling is the object size); the\n * worker never buffers these bytes. Falls through to 8b on null.\n * 8b. `afs.stat` size cap — over `maxBytes` → 413 BEFORE any read; size\n * missing → conservative 413 (read-after-judge would defeat the memory\n * guardrail)\n * 9. `afs.read` → bytes → response with `Content-Type` (meta.mimeType,\n * fallback shared detectMimeType), `X-Content-Type-Options: nosniff`\n * (mandatory — binary serving endpoint), `Cache-Control: private,\n * no-store`. #818: a CLIENT-DECLARED browser-scriptable type\n * (`isScriptableMimeType`: text/html, image/svg+xml, xml, JS variants) is\n * NEVER served inline — forced to `application/octet-stream` +\n * `Content-Disposition: attachment` + CSP sandbox + `X-Frame-Options: DENY`\n * (nosniff alone can't stop a genuinely-declared scriptable type executing).\n *\n * Cache semantics: this handler owns its OWN request-context instance —\n * code shared with afs-rpc, runtime state (projection cache) NOT shared.\n */\n\nimport { sanitizeAfsPath } from \"@aigne/afs\";\nimport { detectMimeType } from \"@aigne/afs-provider-utils\";\nimport { statusForError } from \"./afs-rpc.js\";\nimport { verifyRawUrl } from \"./raw-url.js\";\nimport { type AfsRequestContextOptions, createAfsRequestContext } from \"./request-context.js\";\n\n/**\n * Default max served size — 100 MiB (413 above; streaming/Range is a separate\n * project). upload-limits Phase 6 (D4 interim): raised 50→100 MiB to ALIGN with\n * the grant upload cap (`AFS_DID_SPACE_UPLOAD_MAX_BYTES`, 100 MiB) so a file the\n * upload plane accepts can be raw-served, closing the G4 upload/serve asymmetry\n * for the worker-serve path. This is the NODE/default ceiling (Node can buffer\n * 100 MiB once). It is NOT runtime-uniform: the CF Worker passes a much smaller\n * `maxBytes` (~4 MiB, preview-r2-direct's runtime-aware clean-413) because a\n * one-shot read of ≳8 MiB OOMs the worker (Error 1102 → 503); CF non-media over\n * that gets a CLEAN 413 (never a crash), and CF MEDIA over the gate is exempt via\n * the 302→R2-direct path above. The 50→100 doubling of one-shot read memory on\n * Node is the known interim cost; true large serve needs streaming/Range.\n */\nexport const RAW_MAX_BYTES_DEFAULT = 100 * 1024 * 1024;\n\n/**\n * Media over this size redirect (302) to a presigned object-store GET instead of\n * being served by the worker (preview-r2-direct §4 / Review-B). v1 = 32 KB, locked\n * equal to `PREVIEW_IMAGE_INLINE_MAX` (the user-locked \"> 32 KB → R2-direct\"\n * decision; maximizes worker-offload). The correctness floor is the worker cliff\n * (~4–8 MiB); anything below is a worker-offload-vs-first-byte-latency CHOICE, and\n * a future raise is a measurement-gated, OPTIONAL post-ship activity — NOT a gate.\n */\nexport const RAW_REDIRECT_MIN_BYTES = 32 * 1024;\n\n/**\n * The 302 path is MEDIA-ONLY (preview-r2-direct §5 / Review-1): only `image/*`,\n * `video/*`, `audio/*` are script-safe to redirect cross-origin to R2 (the\n * presigned URL drops `nosniff`; a media element never executes mislabeled\n * bytes). SVG (`image/svg+xml`) matches `image/*` here but is EXCLUDED from the\n * redirect at the call site via `isScriptableMimeType` (#818 supersedes the old\n * Review-A \"SVG rides image/*\" behavior): a scripted SVG is browser-scriptable,\n * so it falls through to worker-serve, which forces a safe attachment. PDF/HTML/\n * text MUST stay on the worker (iframe `noSandbox`/`_isSameOriginUrl` depends on\n * same-origin + nosniff; text is client-rendered → `fetch` → CORS-gated).\n */\nfunction isRedirectableMediaType(mime: string): boolean {\n const m = mime.toLowerCase();\n return m.startsWith(\"image/\") || m.startsWith(\"video/\") || m.startsWith(\"audio/\");\n}\n\n/**\n * Browser-scriptable MIME types (#818). `meta.mimeType` is CLIENT-CONTROLLED —\n * any writer can declare it, there is no write-side allowlist, and this endpoint\n * serves anonymous bearer URLs (public share links). If we echo a declared\n * scriptable type as an inline `Content-Type`, the bytes execute in the serving\n * origin → stored XSS. `X-Content-Type-Options: nosniff` does NOT help here: it\n * only stops sniffing of MIS-labeled bytes; a GENUINELY-declared `text/html`\n * (or scripted `image/svg+xml`) still runs. So at the serve boundary — the\n * provider-agnostic place — these are forced to a non-executing disposition\n * (octet-stream + `Content-Disposition: attachment`) and can never render inline.\n *\n * SVG is included: rendered inline (top-level nav / `<embed>`/`<object>`) a\n * scripted SVG executes same-origin. It is ALSO excluded from the 302→R2 media\n * redirect below (falls through to worker-serve, which forces attachment).\n */\nconst SCRIPTABLE_MIME_TYPES = new Set([\n \"text/html\",\n \"application/xhtml+xml\",\n \"image/svg+xml\",\n \"text/xml\",\n \"application/xml\",\n \"text/javascript\",\n \"application/javascript\",\n \"application/x-javascript\",\n \"text/ecmascript\",\n \"application/ecmascript\",\n \"application/x-ecmascript\",\n]);\n\n/** True when a MIME type can execute script if rendered inline (#818). */\nfunction isScriptableMimeType(mime: string): boolean {\n // Parse the base type: lowercase, drop any `; charset=…` parameter, trim.\n const base = mime.toLowerCase().split(\";\", 1)[0]?.trim() ?? \"\";\n return SCRIPTABLE_MIME_TYPES.has(base);\n}\n\n/**\n * A header-safe `filename` for `Content-Disposition: attachment` (#818). The\n * path is already `sanitizeAfsPath`-clean (no traversal), but strip quotes /\n * backslashes / CR-LF defensively so the value can never break out of the\n * header or inject a second directive.\n */\nfunction attachmentFilename(path: string): string {\n const base = path.split(\"/\").pop() || \"download\";\n return base.replace(/[\"\\\\\\r\\n]/g, \"_\") || \"download\";\n}\n\nexport interface AfsRawHandlerOptions extends AfsRequestContextOptions {\n /**\n * HMAC secret for signed raw URLs (Node: vault-derived; CF: env secret).\n * ABSENT → every request answers 503 (fail-closed: no key, no endpoint —\n * never an unsigned/degraded mode).\n */\n rawUrlSecret?: string | Uint8Array;\n /** Size cap in bytes (default 50MB). */\n maxBytes?: number;\n}\n\nconst RAW_HEADERS_BASE = {\n // Mandatory (design §3): without nosniff, browsers may MIME-sniff\n // mislabeled HTML content into executing as HTML/JS.\n \"X-Content-Type-Options\": \"nosniff\",\n \"Cache-Control\": \"private, no-store\",\n} as const;\n\nfunction deny(status: number, text: string): Response {\n return new Response(text, {\n status,\n headers: { ...RAW_HEADERS_BASE, \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n}\n\n/** Normalize an AFS read result's content to raw bytes. Null = no bytes. */\nfunction contentToBytes(content: unknown, encoding?: string): Uint8Array | null {\n if (content instanceof Uint8Array) return content;\n if (content instanceof ArrayBuffer) return new Uint8Array(content);\n if (typeof content === \"string\") {\n if (encoding === \"base64\") {\n try {\n return Uint8Array.from(atob(content), (c) => c.charCodeAt(0));\n } catch {\n return null;\n }\n }\n return new TextEncoder().encode(content);\n }\n return null;\n}\n\nexport function createAfsRawHandler(\n options: AfsRawHandlerOptions,\n): (request: Request) => Promise<Response> {\n // Own instance — never share the rpc handler's projection cache (§3).\n const reqCtx = createAfsRequestContext(options);\n const maxBytes = options.maxBytes ?? RAW_MAX_BYTES_DEFAULT;\n\n return async function handleRaw(request: Request): Promise<Response> {\n try {\n return await handleInner(request);\n } catch (err) {\n // workerd treats unhandled rejections as fatal isolate errors.\n return deny(statusForError(err), \"Internal error\");\n }\n };\n\n async function handleInner(request: Request): Promise<Response> {\n if (request.method !== \"GET\") return deny(405, \"Method Not Allowed (use GET)\");\n\n const secret = options.rawUrlSecret;\n if (!secret || (typeof secret === \"string\" && secret.length === 0)) {\n // Fail-closed: a deployment without the signing key serves nothing.\n return deny(503, \"raw endpoint unavailable (signing key not configured)\");\n }\n\n // Cookie caller (anonymous allowed) — used by both auth modes.\n const caller = await reqCtx.resolveCaller(request);\n const callerDid = caller?.did ?? null;\n\n // Two auth modes (see file header). SIGNED when a `sig` rides the URL;\n // COOKIE otherwise (same-origin authenticated GET, identity = cookie).\n const url = new URL(request.url);\n const hasSignature = url.searchParams.has(\"sig\");\n\n let rawPath: string;\n let sessionId: string | null;\n let signedBlocklet: string | null;\n\n if (hasSignature) {\n const verdict = await verifyRawUrl(request, callerDid, { secret });\n if (!verdict.ok) {\n // Uniform 403: no distinction between missing/tampered/expired/\n // mismatched — reasons stay in logs/tests, not responses.\n return deny(403, \"Forbidden\");\n }\n rawPath = verdict.path;\n // EXPLICIT signature-verified sessionId — by construction non-null here,\n // so no `?? \"rpc-<blocklet>\"`-style fallback can engage.\n sessionId = verdict.sessionId;\n // Signature-bound blocklet wins (the issuer baked the session's blocklet\n // into the URL + HMAC); query/host resolution is the fallback below.\n signedBlocklet = verdict.blocklet;\n } else {\n // COOKIE mode: an authenticated caller is mandatory — an anonymous reader\n // gets nothing here (must use a signed URL). The scoped `/user` overlay\n // (keyed on caller.did) enforces the SAME read authz as afs-rpc, so this\n // grants no access the cookie didn't already have.\n if (!callerDid) return deny(403, \"Forbidden\");\n const qPath = url.searchParams.get(\"path\");\n if (!qPath) return deny(400, \"Invalid path\");\n rawPath = qPath;\n sessionId = null;\n signedBlocklet = url.searchParams.get(\"blocklet\");\n }\n\n // Single shared sanitizer entry — the handler must not normalize or\n // reorder around it (design §2.3).\n const safePath = sanitizeAfsPath(rawPath);\n if (safePath === null) return deny(400, \"Invalid path\");\n\n const blocklet = await reqCtx.resolveBlocklet(request, signedBlocklet);\n if (!blocklet) return deny(400, \"Could not resolve blocklet\");\n\n const scoped = await reqCtx.resolveScoped(request, {\n blocklet,\n sessionId,\n caller,\n });\n\n if (!scoped.afs.stat || !scoped.afs.read) {\n return deny(501, \"stat/read not supported\");\n }\n\n // stat-before-read: the size cap must hold BEFORE bytes are pulled.\n const statResult = await scoped.afs.stat(safePath, { context: scoped.context });\n const statData = (statResult?.data ?? {}) as {\n size?: unknown;\n meta?: Record<string, unknown>;\n };\n const meta = statData.meta ?? {};\n const size =\n typeof statData.size === \"number\"\n ? statData.size\n : typeof meta.size === \"number\"\n ? (meta.size as number)\n : undefined;\n if (typeof size !== \"number\" || !Number.isFinite(size) || size < 0) {\n // Conservative rejection (design §3): an unbounded read defeats the cap.\n return deny(413, \"Content size unknown\");\n }\n\n // mimeType from stat (hoisted before read for the 302 decision, T2.3): the\n // load-bearing input both for \"is this redirectable media\" and the signed\n // `response-content-type` baked into the presigned URL (Review-1).\n const statMimeType =\n (typeof meta.mimeType === \"string\" && meta.mimeType) ||\n detectMimeType(safePath) ||\n \"application/octet-stream\";\n\n // 302 → R2-direct (preview-r2-direct §2 / Review-1/5): MEDIA over the gate,\n // when the scoped AFS can presign. This runs BEFORE the `size > maxBytes`\n // 413 (Review-5) so large media (the exact thing the 302 exists for) is\n // EXEMPT from the worker-serve cap — R2's ceiling is the object size. The\n // worker NEVER buffers these bytes. presignRead returns null (no signer /\n // non-CAS / meta / unresolved) → natural fall-through to worker-serve;\n // wrapped defensively so a presign error can never 500 the handler.\n if (\n size > RAW_REDIRECT_MIN_BYTES &&\n isRedirectableMediaType(statMimeType) &&\n // #818: a scripted SVG rides the `image/*` branch — never redirect it\n // (it falls through to worker-serve, which forces a safe attachment).\n !isScriptableMimeType(statMimeType) &&\n typeof scoped.afs.presignRead === \"function\"\n ) {\n let grant: { url: string; expiresAt: string } | null = null;\n try {\n grant = await scoped.afs.presignRead(safePath, { responseContentType: statMimeType });\n } catch {\n grant = null;\n }\n if (grant) {\n return new Response(null, {\n status: 302,\n headers: {\n Location: grant.url,\n // Review-8: the 302 carries a BEARER presigned Location — don't let a\n // shared/browser cache retain it, and don't leak the signed URL (with\n // its X-Amz-Signature) via Referer on the redirected request. nosniff\n // is irrelevant on a bodyless 302 (media safety lives in §5/Review-1).\n \"Cache-Control\": \"private, no-store\",\n \"Referrer-Policy\": \"no-referrer\",\n },\n });\n }\n }\n\n if (size > maxBytes) return deny(413, \"Content too large\");\n\n const readResult = await scoped.afs.read(safePath, { context: scoped.context });\n const data = (readResult?.data ?? {}) as {\n content?: unknown;\n encoding?: string;\n meta?: Record<string, unknown>;\n };\n // Base64 marker rides different fields per provider: wire-contract §5\n // uses `encoding`, the fs provider uses `meta.contentType` (\"base64\").\n const encoding =\n data.encoding ??\n (data.meta?.contentType === \"base64\" || data.meta?.encoding === \"base64\"\n ? \"base64\"\n : undefined);\n const bytes = contentToBytes(data.content, encoding);\n if (!bytes) return deny(404, \"No content\");\n\n const mimeType =\n (typeof meta.mimeType === \"string\" && meta.mimeType) ||\n (typeof data.meta?.mimeType === \"string\" && (data.meta.mimeType as string)) ||\n detectMimeType(safePath) ||\n \"application/octet-stream\";\n\n // #818: never render a client-declared scriptable type inline. Force it to a\n // non-executing download (octet-stream + attachment) + defense-in-depth CSP /\n // frame denial. Legit inline types (image except SVG, pdf, text/plain, video,\n // audio) are untouched — including the sandboxed-PDF-iframe path (no\n // X-Frame-Options is added to those, so same-origin embedding still works).\n const headers: Record<string, string> = {\n ...RAW_HEADERS_BASE,\n \"Content-Length\": String(bytes.length),\n };\n if (isScriptableMimeType(mimeType)) {\n headers[\"Content-Type\"] = \"application/octet-stream\";\n headers[\"Content-Disposition\"] = `attachment; filename=\"${attachmentFilename(safePath)}\"`;\n // Belt-and-suspenders: even if a client ignores the disposition, box it.\n headers[\"Content-Security-Policy\"] = \"default-src 'none'; sandbox\";\n headers[\"X-Frame-Options\"] = \"DENY\";\n } else {\n headers[\"Content-Type\"] = mimeType;\n }\n\n return new Response(bytes as unknown as BodyInit, {\n status: 200,\n headers,\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
let _aigne_afs_http = require("@aigne/afs-http");
|
|
2
|
+
|
|
3
|
+
//#region src/http/afs-rest.ts
|
|
4
|
+
/** Delegating wrapper — Object.create doesn't work because AFS uses private class fields. */
|
|
5
|
+
function createAFSModuleWrapper(afs, context) {
|
|
6
|
+
const withCtx = (options) => context ? Object.assign({}, options, { context }) : options;
|
|
7
|
+
return {
|
|
8
|
+
name: afs.name ?? "afs",
|
|
9
|
+
accessMode: "readwrite",
|
|
10
|
+
list: (path, options) => afs.list(path, withCtx(options)),
|
|
11
|
+
read: (path, options) => afs.read(path, withCtx(options)),
|
|
12
|
+
write: (path, content, options) => afs.write(path, content, withCtx(options)),
|
|
13
|
+
delete: (path, options) => afs.delete(path, withCtx(options)),
|
|
14
|
+
search: (path, query, options) => afs.search(path, query, withCtx(options)),
|
|
15
|
+
stat: (path, options) => afs.stat(path, withCtx(options)),
|
|
16
|
+
explain: (path, options) => afs.explain(path, withCtx(options)),
|
|
17
|
+
exec: (path, args, options) => afs.exec(path, args, withCtx(options)),
|
|
18
|
+
rename: (oldPath, newPath, options) => afs.rename(oldPath, newPath, withCtx(options))
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function createAFSRestHandler(afs, options) {
|
|
22
|
+
return (0, _aigne_afs_http.createAFSHttpHandler)({
|
|
23
|
+
module: createAFSModuleWrapper(afs, options?.context),
|
|
24
|
+
token: options?.token,
|
|
25
|
+
maxBodySize: options?.maxBodySize
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
exports.createAFSRestHandler = createAFSRestHandler;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AFS, AFSContext } from "@aigne/afs";
|
|
2
|
+
|
|
3
|
+
//#region src/http/afs-rest.d.ts
|
|
4
|
+
interface AFSRestOptions {
|
|
5
|
+
token?: string;
|
|
6
|
+
/** Max request body size in bytes (default: 10MB) */
|
|
7
|
+
maxBodySize?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Trusted op context forced onto every AFS call. The runtime sets this AFTER
|
|
10
|
+
* it has verified a network caller: it OVERRIDES any client-supplied
|
|
11
|
+
* `options.context`, so a caller can't forge caller / instanceDid /
|
|
12
|
+
* callerOrigin, and the stamped `callerOrigin: "network"` makes the exec-effect
|
|
13
|
+
* and write gates engage. Left unset for the loopback operator and in-process
|
|
14
|
+
* tests, where the client's options pass through unchanged.
|
|
15
|
+
*/
|
|
16
|
+
context?: AFSContext;
|
|
17
|
+
}
|
|
18
|
+
declare function createAFSRestHandler(afs: AFS, options?: AFSRestOptions): (request: Request) => Promise<Response>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { AFSRestOptions, createAFSRestHandler };
|
|
21
|
+
//# sourceMappingURL=afs-rest.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"afs-rest.d.cts","names":[],"sources":["../../src/http/afs-rest.ts"],"mappings":";;;UASiB,cAAA;EACf,KAAA;EAEA;EAAA,WAAA;EASU;;;AAyBZ;;;;;EAzBE,OAAA,GAAU,UAAA;AAAA;AAAA,iBAyBI,oBAAA,CACd,GAAA,EAAK,GAAA,EACL,OAAA,GAAU,cAAA,IACR,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AFS, AFSContext } from "@aigne/afs";
|
|
2
|
+
|
|
3
|
+
//#region src/http/afs-rest.d.ts
|
|
4
|
+
interface AFSRestOptions {
|
|
5
|
+
token?: string;
|
|
6
|
+
/** Max request body size in bytes (default: 10MB) */
|
|
7
|
+
maxBodySize?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Trusted op context forced onto every AFS call. The runtime sets this AFTER
|
|
10
|
+
* it has verified a network caller: it OVERRIDES any client-supplied
|
|
11
|
+
* `options.context`, so a caller can't forge caller / instanceDid /
|
|
12
|
+
* callerOrigin, and the stamped `callerOrigin: "network"` makes the exec-effect
|
|
13
|
+
* and write gates engage. Left unset for the loopback operator and in-process
|
|
14
|
+
* tests, where the client's options pass through unchanged.
|
|
15
|
+
*/
|
|
16
|
+
context?: AFSContext;
|
|
17
|
+
}
|
|
18
|
+
declare function createAFSRestHandler(afs: AFS, options?: AFSRestOptions): (request: Request) => Promise<Response>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { AFSRestOptions, createAFSRestHandler };
|
|
21
|
+
//# sourceMappingURL=afs-rest.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"afs-rest.d.mts","names":[],"sources":["../../src/http/afs-rest.ts"],"mappings":";;;UASiB,cAAA;EACf,KAAA;EAEA;EAAA,WAAA;EASU;;;AAyBZ;;;;;EAzBE,OAAA,GAAU,UAAA;AAAA;AAAA,iBAyBI,oBAAA,CACd,GAAA,EAAK,GAAA,EACL,OAAA,GAAU,cAAA,IACR,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createAFSHttpHandler } from "@aigne/afs-http";
|
|
2
|
+
|
|
3
|
+
//#region src/http/afs-rest.ts
|
|
4
|
+
/** Delegating wrapper — Object.create doesn't work because AFS uses private class fields. */
|
|
5
|
+
function createAFSModuleWrapper(afs, context) {
|
|
6
|
+
const withCtx = (options) => context ? Object.assign({}, options, { context }) : options;
|
|
7
|
+
return {
|
|
8
|
+
name: afs.name ?? "afs",
|
|
9
|
+
accessMode: "readwrite",
|
|
10
|
+
list: (path, options) => afs.list(path, withCtx(options)),
|
|
11
|
+
read: (path, options) => afs.read(path, withCtx(options)),
|
|
12
|
+
write: (path, content, options) => afs.write(path, content, withCtx(options)),
|
|
13
|
+
delete: (path, options) => afs.delete(path, withCtx(options)),
|
|
14
|
+
search: (path, query, options) => afs.search(path, query, withCtx(options)),
|
|
15
|
+
stat: (path, options) => afs.stat(path, withCtx(options)),
|
|
16
|
+
explain: (path, options) => afs.explain(path, withCtx(options)),
|
|
17
|
+
exec: (path, args, options) => afs.exec(path, args, withCtx(options)),
|
|
18
|
+
rename: (oldPath, newPath, options) => afs.rename(oldPath, newPath, withCtx(options))
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function createAFSRestHandler(afs, options) {
|
|
22
|
+
return createAFSHttpHandler({
|
|
23
|
+
module: createAFSModuleWrapper(afs, options?.context),
|
|
24
|
+
token: options?.token,
|
|
25
|
+
maxBodySize: options?.maxBodySize
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { createAFSRestHandler };
|
|
31
|
+
//# sourceMappingURL=afs-rest.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"afs-rest.mjs","names":[],"sources":["../../src/http/afs-rest.ts"],"sourcesContent":["/**\n * AOS AFS REST Handler\n *\n * Bridges AFS to HTTP transport via @aigne/afs-http.\n */\n\nimport type { AFS, AFSContext, AFSModule } from \"@aigne/afs\";\nimport { createAFSHttpHandler } from \"@aigne/afs-http\";\n\nexport interface AFSRestOptions {\n token?: string;\n /** Max request body size in bytes (default: 10MB) */\n maxBodySize?: number;\n /**\n * Trusted op context forced onto every AFS call. The runtime sets this AFTER\n * it has verified a network caller: it OVERRIDES any client-supplied\n * `options.context`, so a caller can't forge caller / instanceDid /\n * callerOrigin, and the stamped `callerOrigin: \"network\"` makes the exec-effect\n * and write gates engage. Left unset for the loopback operator and in-process\n * tests, where the client's options pass through unchanged.\n */\n context?: AFSContext;\n}\n\n/** Delegating wrapper — Object.create doesn't work because AFS uses private class fields. */\nfunction createAFSModuleWrapper(afs: AFS, context?: AFSContext): AFSModule {\n // When a trusted context is supplied (a verified network caller), force it\n // onto every op so the client can't forge caller / instanceDid / callerOrigin;\n // otherwise pass the caller's options through unchanged (loopback / tests).\n const withCtx = <O>(options: O): O =>\n context ? (Object.assign({}, options, { context }) as unknown as O) : options;\n return {\n name: afs.name ?? \"afs\",\n accessMode: \"readwrite\",\n list: (path, options) => afs.list(path, withCtx(options)),\n read: (path, options) => afs.read(path, withCtx(options)),\n write: (path, content, options) => afs.write(path, content, withCtx(options)),\n delete: (path, options) => afs.delete(path, withCtx(options)),\n search: (path, query, options) => afs.search(path, query, withCtx(options)),\n stat: (path, options) => afs.stat(path, withCtx(options)),\n explain: (path, options) => afs.explain(path, withCtx(options)),\n exec: (path, args, options) => afs.exec(path, args, withCtx(options)),\n rename: (oldPath, newPath, options) => afs.rename(oldPath, newPath, withCtx(options)),\n };\n}\n\nexport function createAFSRestHandler(\n afs: AFS,\n options?: AFSRestOptions,\n): (request: Request) => Promise<Response> {\n return createAFSHttpHandler({\n module: createAFSModuleWrapper(afs, options?.context),\n token: options?.token,\n maxBodySize: options?.maxBodySize,\n });\n}\n"],"mappings":";;;;AAyBA,SAAS,uBAAuB,KAAU,SAAiC;CAIzE,MAAM,WAAc,YAClB,UAAW,OAAO,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,GAAoB;AACxE,QAAO;EACL,MAAM,IAAI,QAAQ;EAClB,YAAY;EACZ,OAAO,MAAM,YAAY,IAAI,KAAK,MAAM,QAAQ,QAAQ,CAAC;EACzD,OAAO,MAAM,YAAY,IAAI,KAAK,MAAM,QAAQ,QAAQ,CAAC;EACzD,QAAQ,MAAM,SAAS,YAAY,IAAI,MAAM,MAAM,SAAS,QAAQ,QAAQ,CAAC;EAC7E,SAAS,MAAM,YAAY,IAAI,OAAO,MAAM,QAAQ,QAAQ,CAAC;EAC7D,SAAS,MAAM,OAAO,YAAY,IAAI,OAAO,MAAM,OAAO,QAAQ,QAAQ,CAAC;EAC3E,OAAO,MAAM,YAAY,IAAI,KAAK,MAAM,QAAQ,QAAQ,CAAC;EACzD,UAAU,MAAM,YAAY,IAAI,QAAQ,MAAM,QAAQ,QAAQ,CAAC;EAC/D,OAAO,MAAM,MAAM,YAAY,IAAI,KAAK,MAAM,MAAM,QAAQ,QAAQ,CAAC;EACrE,SAAS,SAAS,SAAS,YAAY,IAAI,OAAO,SAAS,SAAS,QAAQ,QAAQ,CAAC;EACtF;;AAGH,SAAgB,qBACd,KACA,SACyC;AACzC,QAAO,qBAAqB;EAC1B,QAAQ,uBAAuB,KAAK,SAAS,QAAQ;EACrD,OAAO,SAAS;EAChB,aAAa,SAAS;EACvB,CAAC"}
|