@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,136 @@
|
|
|
1
|
+
const require_session_user_afs = require('../session/session-user-afs.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/http/raw-url.ts
|
|
4
|
+
/**
|
|
5
|
+
* Signed raw-URL primitives (afs-preview T2.0/T2.1, design §3).
|
|
6
|
+
*
|
|
7
|
+
* `GET /api/afs/raw?path=…&sid=…&exp=…&sig=…` lets `<img>` / `<iframe>` /
|
|
8
|
+
* `<video>` reference AFS bytes. GET carries no body, so session identity
|
|
9
|
+
* rides a presigned HMAC instead of afs-rpc's body.sessionId:
|
|
10
|
+
*
|
|
11
|
+
* sig = HMAC-SHA256(secret, [path, sid, normalizedCallerDid, exp])
|
|
12
|
+
*
|
|
13
|
+
* WHY presigned, not a session-registry lookup: CF session state lives in a
|
|
14
|
+
* Durable Object — every `<img>` GET would wake the DO (a gallery page =
|
|
15
|
+
* dozens of wakes; DO-billing lesson). HMAC verification is stateless and
|
|
16
|
+
* identical on Node + workerd (crypto.subtle).
|
|
17
|
+
*
|
|
18
|
+
* Caller binding is symmetric and strict: the verifier recomputes the HMAC
|
|
19
|
+
* with the COOKIE caller (normalized, anonymous = "") — an anonymous-issued
|
|
20
|
+
* URL with an authed cookie fails, an authed-issued URL without a cookie
|
|
21
|
+
* fails. No one-sided downgrade.
|
|
22
|
+
*
|
|
23
|
+
* Anonymous URLs are pure bearer tokens (possession = access), so they are
|
|
24
|
+
* REFUSED for session-private overlay paths (static denylist exported by
|
|
25
|
+
* SessionUserAFS — never hand-written, never derived from a live instance's
|
|
26
|
+
* conditional mounts). Issue-side denial + verify-side second defense.
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_TTL_MS = 36e5;
|
|
29
|
+
/** Anonymous caller normalization — identical on issue and verify ends. */
|
|
30
|
+
function normalizeCallerDid(did) {
|
|
31
|
+
return typeof did === "string" && did ? did : "";
|
|
32
|
+
}
|
|
33
|
+
const _encoder = new TextEncoder();
|
|
34
|
+
async function importKey(secret) {
|
|
35
|
+
const raw = typeof secret === "string" ? _encoder.encode(secret) : secret;
|
|
36
|
+
return crypto.subtle.importKey("raw", raw, {
|
|
37
|
+
name: "HMAC",
|
|
38
|
+
hash: "SHA-256"
|
|
39
|
+
}, false, ["sign", "verify"]);
|
|
40
|
+
}
|
|
41
|
+
/** Unambiguous signing payload — JSON array survives any char in fields. */
|
|
42
|
+
function payloadFor(path, sid, callerDid, exp, blocklet) {
|
|
43
|
+
return _encoder.encode(JSON.stringify([
|
|
44
|
+
path,
|
|
45
|
+
sid,
|
|
46
|
+
callerDid,
|
|
47
|
+
exp,
|
|
48
|
+
blocklet
|
|
49
|
+
]));
|
|
50
|
+
}
|
|
51
|
+
function toBase64Url(bytes) {
|
|
52
|
+
let binary = "";
|
|
53
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
54
|
+
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
55
|
+
}
|
|
56
|
+
function fromBase64Url(s) {
|
|
57
|
+
try {
|
|
58
|
+
const b64 = s.replaceAll("-", "+").replaceAll("_", "/");
|
|
59
|
+
return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Issue a signed raw URL (path + query, no origin). Returns null when the
|
|
66
|
+
* request is refused (anonymous caller + session-private path) — callers
|
|
67
|
+
* (preview builders) fall back to the no-preview subtree.
|
|
68
|
+
*/
|
|
69
|
+
async function issueRawUrl(params, opts) {
|
|
70
|
+
const caller = normalizeCallerDid(params.callerDid);
|
|
71
|
+
if (caller === "" && !opts.skipPrivatePathCheck && require_session_user_afs.isSessionPrivatePath(params.path)) return null;
|
|
72
|
+
const exp = (opts.now ?? Date.now()) + (params.ttlMs ?? DEFAULT_TTL_MS);
|
|
73
|
+
const blocklet = params.blocklet ?? "";
|
|
74
|
+
const key = await importKey(opts.secret);
|
|
75
|
+
const mac = await crypto.subtle.sign("HMAC", key, payloadFor(params.path, params.sessionId, caller, exp, blocklet));
|
|
76
|
+
const sig = toBase64Url(new Uint8Array(mac));
|
|
77
|
+
const q = new URLSearchParams({
|
|
78
|
+
path: params.path,
|
|
79
|
+
sid: params.sessionId,
|
|
80
|
+
exp: String(exp),
|
|
81
|
+
sig
|
|
82
|
+
});
|
|
83
|
+
if (blocklet) q.set("blocklet", blocklet);
|
|
84
|
+
return `/api/afs/raw?${q.toString()}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Verify a raw request URL against the cookie caller. Constant-time HMAC
|
|
88
|
+
* verification via crypto.subtle.verify; every failure is a generic 403 at
|
|
89
|
+
* the endpoint (reasons are for logs/tests, not responses).
|
|
90
|
+
*/
|
|
91
|
+
async function verifyRawUrl(request, cookieCallerDid, opts) {
|
|
92
|
+
const url = request instanceof URL ? request : new URL(request.url);
|
|
93
|
+
const path = url.searchParams.get("path");
|
|
94
|
+
const sid = url.searchParams.get("sid");
|
|
95
|
+
const expRaw = url.searchParams.get("exp");
|
|
96
|
+
const sig = url.searchParams.get("sig");
|
|
97
|
+
if (!path || !sid || !expRaw || !sig) return {
|
|
98
|
+
ok: false,
|
|
99
|
+
reason: "missing param"
|
|
100
|
+
};
|
|
101
|
+
const exp = Number(expRaw);
|
|
102
|
+
if (!Number.isFinite(exp)) return {
|
|
103
|
+
ok: false,
|
|
104
|
+
reason: "bad exp"
|
|
105
|
+
};
|
|
106
|
+
if ((opts.now ?? Date.now()) > exp) return {
|
|
107
|
+
ok: false,
|
|
108
|
+
reason: "expired"
|
|
109
|
+
};
|
|
110
|
+
const sigBytes = fromBase64Url(sig);
|
|
111
|
+
if (!sigBytes) return {
|
|
112
|
+
ok: false,
|
|
113
|
+
reason: "bad sig encoding"
|
|
114
|
+
};
|
|
115
|
+
const caller = normalizeCallerDid(cookieCallerDid);
|
|
116
|
+
const blocklet = url.searchParams.get("blocklet") ?? "";
|
|
117
|
+
const key = await importKey(opts.secret);
|
|
118
|
+
if (!await crypto.subtle.verify("HMAC", key, sigBytes, payloadFor(path, sid, caller, exp, blocklet))) return {
|
|
119
|
+
ok: false,
|
|
120
|
+
reason: "signature mismatch (tamper or caller mismatch)"
|
|
121
|
+
};
|
|
122
|
+
if (caller === "" && require_session_user_afs.isSessionPrivatePath(path)) return {
|
|
123
|
+
ok: false,
|
|
124
|
+
reason: "anonymous bearer URL for session-private path"
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
ok: true,
|
|
128
|
+
path,
|
|
129
|
+
sessionId: sid,
|
|
130
|
+
blocklet: blocklet || null
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
exports.issueRawUrl = issueRawUrl;
|
|
136
|
+
exports.verifyRawUrl = verifyRawUrl;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { isSessionPrivatePath } from "../session/session-user-afs.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/http/raw-url.d.ts
|
|
4
|
+
interface IssueRawUrlParams {
|
|
5
|
+
/** AFS path (the builder's sanitized path — signed verbatim). */
|
|
6
|
+
path: string;
|
|
7
|
+
/** The verified session id (NEVER a fallback like `rpc-<blocklet>`). */
|
|
8
|
+
sessionId: string;
|
|
9
|
+
/** Verified caller DID, or null for anonymous web sessions. */
|
|
10
|
+
callerDid: string | null;
|
|
11
|
+
/**
|
|
12
|
+
* The session's blocklet — rides the URL (so `<img>` works from any
|
|
13
|
+
* origin without Host-based resolution) AND the signature (so the scoped
|
|
14
|
+
* view can't be re-pointed by query tamper).
|
|
15
|
+
*/
|
|
16
|
+
blocklet?: string | null;
|
|
17
|
+
/** Lifetime in ms (default 1h). */
|
|
18
|
+
ttlMs?: number;
|
|
19
|
+
}
|
|
20
|
+
interface RawUrlCryptoOptions {
|
|
21
|
+
/** HMAC secret (Node: vault-derived; CF: env secret). */
|
|
22
|
+
secret: string | Uint8Array;
|
|
23
|
+
/** Clock override for tests. */
|
|
24
|
+
now?: number;
|
|
25
|
+
/**
|
|
26
|
+
* TEST SEAM ONLY: skip the issue-side anonymous/private-path denial so the
|
|
27
|
+
* verify-side second defense can be exercised. Never set in production.
|
|
28
|
+
*/
|
|
29
|
+
skipPrivatePathCheck?: boolean;
|
|
30
|
+
}
|
|
31
|
+
type VerifyRawUrlResult = {
|
|
32
|
+
ok: true;
|
|
33
|
+
path: string;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
blocklet: string | null;
|
|
36
|
+
} | {
|
|
37
|
+
ok: false;
|
|
38
|
+
reason: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Issue a signed raw URL (path + query, no origin). Returns null when the
|
|
42
|
+
* request is refused (anonymous caller + session-private path) — callers
|
|
43
|
+
* (preview builders) fall back to the no-preview subtree.
|
|
44
|
+
*/
|
|
45
|
+
declare function issueRawUrl(params: IssueRawUrlParams, opts: RawUrlCryptoOptions): Promise<string | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Verify a raw request URL against the cookie caller. Constant-time HMAC
|
|
48
|
+
* verification via crypto.subtle.verify; every failure is a generic 403 at
|
|
49
|
+
* the endpoint (reasons are for logs/tests, not responses).
|
|
50
|
+
*/
|
|
51
|
+
declare function verifyRawUrl(request: Request | URL, cookieCallerDid: string | null, opts: RawUrlCryptoOptions): Promise<VerifyRawUrlResult>;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { IssueRawUrlParams, RawUrlCryptoOptions, VerifyRawUrlResult, issueRawUrl, verifyRawUrl };
|
|
54
|
+
//# sourceMappingURL=raw-url.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-url.d.cts","names":[],"sources":["../../src/http/raw-url.ts"],"mappings":";;;UA+BiB,iBAAA;EA6Ba;EA3B5B,IAAA;EA4Bc;EA1Bd,SAAA;EA0B+C;EAxB/C,SAAA;EAyBe;;;AAmDjB;;EAtEE,QAAA;EAuEQ;EArER,KAAA;AAAA;AAAA,UAGe,mBAAA;EAoEP;EAlER,MAAA,WAAiB,UAAA;EAgEjB;EA9DA,GAAA;EA+DA;;;;EA1DA,oBAAA;AAAA;AAAA,KAGU,kBAAA;EACN,EAAA;EAAU,IAAA;EAAc,SAAA;EAAmB,QAAA;AAAA;EAC3C,EAAA;EAAW,MAAA;AAAA;;;;;;iBAmDK,WAAA,CACpB,MAAA,EAAQ,iBAAA,EACR,IAAA,EAAM,mBAAA,GACL,OAAA;;;;;;iBAgCmB,YAAA,CACpB,OAAA,EAAS,OAAA,GAAU,GAAA,EACnB,eAAA,iBACA,IAAA,EAAM,mBAAA,GACL,OAAA,CAAQ,kBAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { isSessionPrivatePath } from "../session/session-user-afs.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/http/raw-url.d.ts
|
|
4
|
+
interface IssueRawUrlParams {
|
|
5
|
+
/** AFS path (the builder's sanitized path — signed verbatim). */
|
|
6
|
+
path: string;
|
|
7
|
+
/** The verified session id (NEVER a fallback like `rpc-<blocklet>`). */
|
|
8
|
+
sessionId: string;
|
|
9
|
+
/** Verified caller DID, or null for anonymous web sessions. */
|
|
10
|
+
callerDid: string | null;
|
|
11
|
+
/**
|
|
12
|
+
* The session's blocklet — rides the URL (so `<img>` works from any
|
|
13
|
+
* origin without Host-based resolution) AND the signature (so the scoped
|
|
14
|
+
* view can't be re-pointed by query tamper).
|
|
15
|
+
*/
|
|
16
|
+
blocklet?: string | null;
|
|
17
|
+
/** Lifetime in ms (default 1h). */
|
|
18
|
+
ttlMs?: number;
|
|
19
|
+
}
|
|
20
|
+
interface RawUrlCryptoOptions {
|
|
21
|
+
/** HMAC secret (Node: vault-derived; CF: env secret). */
|
|
22
|
+
secret: string | Uint8Array;
|
|
23
|
+
/** Clock override for tests. */
|
|
24
|
+
now?: number;
|
|
25
|
+
/**
|
|
26
|
+
* TEST SEAM ONLY: skip the issue-side anonymous/private-path denial so the
|
|
27
|
+
* verify-side second defense can be exercised. Never set in production.
|
|
28
|
+
*/
|
|
29
|
+
skipPrivatePathCheck?: boolean;
|
|
30
|
+
}
|
|
31
|
+
type VerifyRawUrlResult = {
|
|
32
|
+
ok: true;
|
|
33
|
+
path: string;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
blocklet: string | null;
|
|
36
|
+
} | {
|
|
37
|
+
ok: false;
|
|
38
|
+
reason: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Issue a signed raw URL (path + query, no origin). Returns null when the
|
|
42
|
+
* request is refused (anonymous caller + session-private path) — callers
|
|
43
|
+
* (preview builders) fall back to the no-preview subtree.
|
|
44
|
+
*/
|
|
45
|
+
declare function issueRawUrl(params: IssueRawUrlParams, opts: RawUrlCryptoOptions): Promise<string | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Verify a raw request URL against the cookie caller. Constant-time HMAC
|
|
48
|
+
* verification via crypto.subtle.verify; every failure is a generic 403 at
|
|
49
|
+
* the endpoint (reasons are for logs/tests, not responses).
|
|
50
|
+
*/
|
|
51
|
+
declare function verifyRawUrl(request: Request | URL, cookieCallerDid: string | null, opts: RawUrlCryptoOptions): Promise<VerifyRawUrlResult>;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { IssueRawUrlParams, RawUrlCryptoOptions, VerifyRawUrlResult, issueRawUrl, verifyRawUrl };
|
|
54
|
+
//# sourceMappingURL=raw-url.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-url.d.mts","names":[],"sources":["../../src/http/raw-url.ts"],"mappings":";;;UA+BiB,iBAAA;EA6Ba;EA3B5B,IAAA;EA4Bc;EA1Bd,SAAA;EA0B+C;EAxB/C,SAAA;EAyBe;;;AAmDjB;;EAtEE,QAAA;EAuEQ;EArER,KAAA;AAAA;AAAA,UAGe,mBAAA;EAoEP;EAlER,MAAA,WAAiB,UAAA;EAgEjB;EA9DA,GAAA;EA+DA;;;;EA1DA,oBAAA;AAAA;AAAA,KAGU,kBAAA;EACN,EAAA;EAAU,IAAA;EAAc,SAAA;EAAmB,QAAA;AAAA;EAC3C,EAAA;EAAW,MAAA;AAAA;;;;;;iBAmDK,WAAA,CACpB,MAAA,EAAQ,iBAAA,EACR,IAAA,EAAM,mBAAA,GACL,OAAA;;;;;;iBAgCmB,YAAA,CACpB,OAAA,EAAS,OAAA,GAAU,GAAA,EACnB,eAAA,iBACA,IAAA,EAAM,mBAAA,GACL,OAAA,CAAQ,kBAAA"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { isSessionPrivatePath } from "../session/session-user-afs.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/http/raw-url.ts
|
|
4
|
+
/**
|
|
5
|
+
* Signed raw-URL primitives (afs-preview T2.0/T2.1, design §3).
|
|
6
|
+
*
|
|
7
|
+
* `GET /api/afs/raw?path=…&sid=…&exp=…&sig=…` lets `<img>` / `<iframe>` /
|
|
8
|
+
* `<video>` reference AFS bytes. GET carries no body, so session identity
|
|
9
|
+
* rides a presigned HMAC instead of afs-rpc's body.sessionId:
|
|
10
|
+
*
|
|
11
|
+
* sig = HMAC-SHA256(secret, [path, sid, normalizedCallerDid, exp])
|
|
12
|
+
*
|
|
13
|
+
* WHY presigned, not a session-registry lookup: CF session state lives in a
|
|
14
|
+
* Durable Object — every `<img>` GET would wake the DO (a gallery page =
|
|
15
|
+
* dozens of wakes; DO-billing lesson). HMAC verification is stateless and
|
|
16
|
+
* identical on Node + workerd (crypto.subtle).
|
|
17
|
+
*
|
|
18
|
+
* Caller binding is symmetric and strict: the verifier recomputes the HMAC
|
|
19
|
+
* with the COOKIE caller (normalized, anonymous = "") — an anonymous-issued
|
|
20
|
+
* URL with an authed cookie fails, an authed-issued URL without a cookie
|
|
21
|
+
* fails. No one-sided downgrade.
|
|
22
|
+
*
|
|
23
|
+
* Anonymous URLs are pure bearer tokens (possession = access), so they are
|
|
24
|
+
* REFUSED for session-private overlay paths (static denylist exported by
|
|
25
|
+
* SessionUserAFS — never hand-written, never derived from a live instance's
|
|
26
|
+
* conditional mounts). Issue-side denial + verify-side second defense.
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_TTL_MS = 36e5;
|
|
29
|
+
/** Anonymous caller normalization — identical on issue and verify ends. */
|
|
30
|
+
function normalizeCallerDid(did) {
|
|
31
|
+
return typeof did === "string" && did ? did : "";
|
|
32
|
+
}
|
|
33
|
+
const _encoder = new TextEncoder();
|
|
34
|
+
async function importKey(secret) {
|
|
35
|
+
const raw = typeof secret === "string" ? _encoder.encode(secret) : secret;
|
|
36
|
+
return crypto.subtle.importKey("raw", raw, {
|
|
37
|
+
name: "HMAC",
|
|
38
|
+
hash: "SHA-256"
|
|
39
|
+
}, false, ["sign", "verify"]);
|
|
40
|
+
}
|
|
41
|
+
/** Unambiguous signing payload — JSON array survives any char in fields. */
|
|
42
|
+
function payloadFor(path, sid, callerDid, exp, blocklet) {
|
|
43
|
+
return _encoder.encode(JSON.stringify([
|
|
44
|
+
path,
|
|
45
|
+
sid,
|
|
46
|
+
callerDid,
|
|
47
|
+
exp,
|
|
48
|
+
blocklet
|
|
49
|
+
]));
|
|
50
|
+
}
|
|
51
|
+
function toBase64Url(bytes) {
|
|
52
|
+
let binary = "";
|
|
53
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
54
|
+
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
55
|
+
}
|
|
56
|
+
function fromBase64Url(s) {
|
|
57
|
+
try {
|
|
58
|
+
const b64 = s.replaceAll("-", "+").replaceAll("_", "/");
|
|
59
|
+
return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Issue a signed raw URL (path + query, no origin). Returns null when the
|
|
66
|
+
* request is refused (anonymous caller + session-private path) — callers
|
|
67
|
+
* (preview builders) fall back to the no-preview subtree.
|
|
68
|
+
*/
|
|
69
|
+
async function issueRawUrl(params, opts) {
|
|
70
|
+
const caller = normalizeCallerDid(params.callerDid);
|
|
71
|
+
if (caller === "" && !opts.skipPrivatePathCheck && isSessionPrivatePath(params.path)) return null;
|
|
72
|
+
const exp = (opts.now ?? Date.now()) + (params.ttlMs ?? DEFAULT_TTL_MS);
|
|
73
|
+
const blocklet = params.blocklet ?? "";
|
|
74
|
+
const key = await importKey(opts.secret);
|
|
75
|
+
const mac = await crypto.subtle.sign("HMAC", key, payloadFor(params.path, params.sessionId, caller, exp, blocklet));
|
|
76
|
+
const sig = toBase64Url(new Uint8Array(mac));
|
|
77
|
+
const q = new URLSearchParams({
|
|
78
|
+
path: params.path,
|
|
79
|
+
sid: params.sessionId,
|
|
80
|
+
exp: String(exp),
|
|
81
|
+
sig
|
|
82
|
+
});
|
|
83
|
+
if (blocklet) q.set("blocklet", blocklet);
|
|
84
|
+
return `/api/afs/raw?${q.toString()}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Verify a raw request URL against the cookie caller. Constant-time HMAC
|
|
88
|
+
* verification via crypto.subtle.verify; every failure is a generic 403 at
|
|
89
|
+
* the endpoint (reasons are for logs/tests, not responses).
|
|
90
|
+
*/
|
|
91
|
+
async function verifyRawUrl(request, cookieCallerDid, opts) {
|
|
92
|
+
const url = request instanceof URL ? request : new URL(request.url);
|
|
93
|
+
const path = url.searchParams.get("path");
|
|
94
|
+
const sid = url.searchParams.get("sid");
|
|
95
|
+
const expRaw = url.searchParams.get("exp");
|
|
96
|
+
const sig = url.searchParams.get("sig");
|
|
97
|
+
if (!path || !sid || !expRaw || !sig) return {
|
|
98
|
+
ok: false,
|
|
99
|
+
reason: "missing param"
|
|
100
|
+
};
|
|
101
|
+
const exp = Number(expRaw);
|
|
102
|
+
if (!Number.isFinite(exp)) return {
|
|
103
|
+
ok: false,
|
|
104
|
+
reason: "bad exp"
|
|
105
|
+
};
|
|
106
|
+
if ((opts.now ?? Date.now()) > exp) return {
|
|
107
|
+
ok: false,
|
|
108
|
+
reason: "expired"
|
|
109
|
+
};
|
|
110
|
+
const sigBytes = fromBase64Url(sig);
|
|
111
|
+
if (!sigBytes) return {
|
|
112
|
+
ok: false,
|
|
113
|
+
reason: "bad sig encoding"
|
|
114
|
+
};
|
|
115
|
+
const caller = normalizeCallerDid(cookieCallerDid);
|
|
116
|
+
const blocklet = url.searchParams.get("blocklet") ?? "";
|
|
117
|
+
const key = await importKey(opts.secret);
|
|
118
|
+
if (!await crypto.subtle.verify("HMAC", key, sigBytes, payloadFor(path, sid, caller, exp, blocklet))) return {
|
|
119
|
+
ok: false,
|
|
120
|
+
reason: "signature mismatch (tamper or caller mismatch)"
|
|
121
|
+
};
|
|
122
|
+
if (caller === "" && isSessionPrivatePath(path)) return {
|
|
123
|
+
ok: false,
|
|
124
|
+
reason: "anonymous bearer URL for session-private path"
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
ok: true,
|
|
128
|
+
path,
|
|
129
|
+
sessionId: sid,
|
|
130
|
+
blocklet: blocklet || null
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
export { issueRawUrl, verifyRawUrl };
|
|
136
|
+
//# sourceMappingURL=raw-url.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-url.mjs","names":[],"sources":["../../src/http/raw-url.ts"],"sourcesContent":["/**\n * Signed raw-URL primitives (afs-preview T2.0/T2.1, design §3).\n *\n * `GET /api/afs/raw?path=…&sid=…&exp=…&sig=…` lets `<img>` / `<iframe>` /\n * `<video>` reference AFS bytes. GET carries no body, so session identity\n * rides a presigned HMAC instead of afs-rpc's body.sessionId:\n *\n * sig = HMAC-SHA256(secret, [path, sid, normalizedCallerDid, exp])\n *\n * WHY presigned, not a session-registry lookup: CF session state lives in a\n * Durable Object — every `<img>` GET would wake the DO (a gallery page =\n * dozens of wakes; DO-billing lesson). HMAC verification is stateless and\n * identical on Node + workerd (crypto.subtle).\n *\n * Caller binding is symmetric and strict: the verifier recomputes the HMAC\n * with the COOKIE caller (normalized, anonymous = \"\") — an anonymous-issued\n * URL with an authed cookie fails, an authed-issued URL without a cookie\n * fails. No one-sided downgrade.\n *\n * Anonymous URLs are pure bearer tokens (possession = access), so they are\n * REFUSED for session-private overlay paths (static denylist exported by\n * SessionUserAFS — never hand-written, never derived from a live instance's\n * conditional mounts). Issue-side denial + verify-side second defense.\n */\n\nimport { isSessionPrivatePath } from \"../session/session-user-afs.js\";\n\nexport { isSessionPrivatePath };\n\nconst DEFAULT_TTL_MS = 3600_000; // 1h — re-render/new select re-issues; no auto-renewal\n\nexport interface IssueRawUrlParams {\n /** AFS path (the builder's sanitized path — signed verbatim). */\n path: string;\n /** The verified session id (NEVER a fallback like `rpc-<blocklet>`). */\n sessionId: string;\n /** Verified caller DID, or null for anonymous web sessions. */\n callerDid: string | null;\n /**\n * The session's blocklet — rides the URL (so `<img>` works from any\n * origin without Host-based resolution) AND the signature (so the scoped\n * view can't be re-pointed by query tamper).\n */\n blocklet?: string | null;\n /** Lifetime in ms (default 1h). */\n ttlMs?: number;\n}\n\nexport interface RawUrlCryptoOptions {\n /** HMAC secret (Node: vault-derived; CF: env secret). */\n secret: string | Uint8Array;\n /** Clock override for tests. */\n now?: number;\n /**\n * TEST SEAM ONLY: skip the issue-side anonymous/private-path denial so the\n * verify-side second defense can be exercised. Never set in production.\n */\n skipPrivatePathCheck?: boolean;\n}\n\nexport type VerifyRawUrlResult =\n | { ok: true; path: string; sessionId: string; blocklet: string | null }\n | { ok: false; reason: string };\n\n/** Anonymous caller normalization — identical on issue and verify ends. */\nfunction normalizeCallerDid(did: string | null | undefined): string {\n return typeof did === \"string\" && did ? did : \"\";\n}\n\nconst _encoder = new TextEncoder();\n\nasync function importKey(secret: string | Uint8Array): Promise<CryptoKey> {\n const raw = typeof secret === \"string\" ? _encoder.encode(secret) : secret;\n return crypto.subtle.importKey(\n \"raw\",\n raw as BufferSource,\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\", \"verify\"],\n );\n}\n\n/** Unambiguous signing payload — JSON array survives any char in fields. */\nfunction payloadFor(\n path: string,\n sid: string,\n callerDid: string,\n exp: number,\n blocklet: string,\n): Uint8Array {\n return _encoder.encode(JSON.stringify([path, sid, callerDid, exp, blocklet]));\n}\n\nfunction toBase64Url(bytes: Uint8Array): string {\n let binary = \"\";\n for (const b of bytes) binary += String.fromCharCode(b);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replace(/=+$/, \"\");\n}\n\nfunction fromBase64Url(s: string): Uint8Array | null {\n try {\n const b64 = s.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\");\n return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n } catch {\n return null;\n }\n}\n\n/**\n * Issue a signed raw URL (path + query, no origin). Returns null when the\n * request is refused (anonymous caller + session-private path) — callers\n * (preview builders) fall back to the no-preview subtree.\n */\nexport async function issueRawUrl(\n params: IssueRawUrlParams,\n opts: RawUrlCryptoOptions,\n): Promise<string | null> {\n const caller = normalizeCallerDid(params.callerDid);\n if (caller === \"\" && !opts.skipPrivatePathCheck && isSessionPrivatePath(params.path)) {\n // Anonymous = bearer URL; private overlay content must not become\n // possession-grants-access (design §3).\n return null;\n }\n const now = opts.now ?? Date.now();\n const exp = now + (params.ttlMs ?? DEFAULT_TTL_MS);\n const blocklet = params.blocklet ?? \"\";\n const key = await importKey(opts.secret);\n const mac = await crypto.subtle.sign(\n \"HMAC\",\n key,\n payloadFor(params.path, params.sessionId, caller, exp, blocklet) as BufferSource,\n );\n const sig = toBase64Url(new Uint8Array(mac));\n const q = new URLSearchParams({\n path: params.path,\n sid: params.sessionId,\n exp: String(exp),\n sig,\n });\n if (blocklet) q.set(\"blocklet\", blocklet);\n return `/api/afs/raw?${q.toString()}`;\n}\n\n/**\n * Verify a raw request URL against the cookie caller. Constant-time HMAC\n * verification via crypto.subtle.verify; every failure is a generic 403 at\n * the endpoint (reasons are for logs/tests, not responses).\n */\nexport async function verifyRawUrl(\n request: Request | URL,\n cookieCallerDid: string | null,\n opts: RawUrlCryptoOptions,\n): Promise<VerifyRawUrlResult> {\n const url = request instanceof URL ? request : new URL(request.url);\n const path = url.searchParams.get(\"path\");\n const sid = url.searchParams.get(\"sid\");\n const expRaw = url.searchParams.get(\"exp\");\n const sig = url.searchParams.get(\"sig\");\n if (!path || !sid || !expRaw || !sig) return { ok: false, reason: \"missing param\" };\n\n const exp = Number(expRaw);\n if (!Number.isFinite(exp)) return { ok: false, reason: \"bad exp\" };\n const now = opts.now ?? Date.now();\n if (now > exp) return { ok: false, reason: \"expired\" };\n\n const sigBytes = fromBase64Url(sig);\n if (!sigBytes) return { ok: false, reason: \"bad sig encoding\" };\n\n const caller = normalizeCallerDid(cookieCallerDid);\n const blocklet = url.searchParams.get(\"blocklet\") ?? \"\";\n const key = await importKey(opts.secret);\n const valid = await crypto.subtle.verify(\n \"HMAC\",\n key,\n sigBytes as BufferSource,\n payloadFor(path, sid, caller, exp, blocklet) as BufferSource,\n );\n if (!valid) return { ok: false, reason: \"signature mismatch (tamper or caller mismatch)\" };\n\n // Second defense (design §3): even a correctly-signed anonymous URL must\n // not reach session-private overlays.\n if (caller === \"\" && isSessionPrivatePath(path)) {\n return { ok: false, reason: \"anonymous bearer URL for session-private path\" };\n }\n\n return { ok: true, path, sessionId: sid, blocklet: blocklet || null };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAM,iBAAiB;;AAoCvB,SAAS,mBAAmB,KAAwC;AAClE,QAAO,OAAO,QAAQ,YAAY,MAAM,MAAM;;AAGhD,MAAM,WAAW,IAAI,aAAa;AAElC,eAAe,UAAU,QAAiD;CACxE,MAAM,MAAM,OAAO,WAAW,WAAW,SAAS,OAAO,OAAO,GAAG;AACnE,QAAO,OAAO,OAAO,UACnB,OACA,KACA;EAAE,MAAM;EAAQ,MAAM;EAAW,EACjC,OACA,CAAC,QAAQ,SAAS,CACnB;;;AAIH,SAAS,WACP,MACA,KACA,WACA,KACA,UACY;AACZ,QAAO,SAAS,OAAO,KAAK,UAAU;EAAC;EAAM;EAAK;EAAW;EAAK;EAAS,CAAC,CAAC;;AAG/E,SAAS,YAAY,OAA2B;CAC9C,IAAI,SAAS;AACb,MAAK,MAAM,KAAK,MAAO,WAAU,OAAO,aAAa,EAAE;AACvD,QAAO,KAAK,OAAO,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,QAAQ,OAAO,GAAG;;AAGlF,SAAS,cAAc,GAA8B;AACnD,KAAI;EACF,MAAM,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC,WAAW,KAAK,IAAI;AACvD,SAAO,WAAW,KAAK,KAAK,IAAI,GAAG,MAAM,EAAE,WAAW,EAAE,CAAC;SACnD;AACN,SAAO;;;;;;;;AASX,eAAsB,YACpB,QACA,MACwB;CACxB,MAAM,SAAS,mBAAmB,OAAO,UAAU;AACnD,KAAI,WAAW,MAAM,CAAC,KAAK,wBAAwB,qBAAqB,OAAO,KAAK,CAGlF,QAAO;CAGT,MAAM,OADM,KAAK,OAAO,KAAK,KAAK,KACf,OAAO,SAAS;CACnC,MAAM,WAAW,OAAO,YAAY;CACpC,MAAM,MAAM,MAAM,UAAU,KAAK,OAAO;CACxC,MAAM,MAAM,MAAM,OAAO,OAAO,KAC9B,QACA,KACA,WAAW,OAAO,MAAM,OAAO,WAAW,QAAQ,KAAK,SAAS,CACjE;CACD,MAAM,MAAM,YAAY,IAAI,WAAW,IAAI,CAAC;CAC5C,MAAM,IAAI,IAAI,gBAAgB;EAC5B,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO,IAAI;EAChB;EACD,CAAC;AACF,KAAI,SAAU,GAAE,IAAI,YAAY,SAAS;AACzC,QAAO,gBAAgB,EAAE,UAAU;;;;;;;AAQrC,eAAsB,aACpB,SACA,iBACA,MAC6B;CAC7B,MAAM,MAAM,mBAAmB,MAAM,UAAU,IAAI,IAAI,QAAQ,IAAI;CACnE,MAAM,OAAO,IAAI,aAAa,IAAI,OAAO;CACzC,MAAM,MAAM,IAAI,aAAa,IAAI,MAAM;CACvC,MAAM,SAAS,IAAI,aAAa,IAAI,MAAM;CAC1C,MAAM,MAAM,IAAI,aAAa,IAAI,MAAM;AACvC,KAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,IAAK,QAAO;EAAE,IAAI;EAAO,QAAQ;EAAiB;CAEnF,MAAM,MAAM,OAAO,OAAO;AAC1B,KAAI,CAAC,OAAO,SAAS,IAAI,CAAE,QAAO;EAAE,IAAI;EAAO,QAAQ;EAAW;AAElE,MADY,KAAK,OAAO,KAAK,KAAK,IACxB,IAAK,QAAO;EAAE,IAAI;EAAO,QAAQ;EAAW;CAEtD,MAAM,WAAW,cAAc,IAAI;AACnC,KAAI,CAAC,SAAU,QAAO;EAAE,IAAI;EAAO,QAAQ;EAAoB;CAE/D,MAAM,SAAS,mBAAmB,gBAAgB;CAClD,MAAM,WAAW,IAAI,aAAa,IAAI,WAAW,IAAI;CACrD,MAAM,MAAM,MAAM,UAAU,KAAK,OAAO;AAOxC,KAAI,CANU,MAAM,OAAO,OAAO,OAChC,QACA,KACA,UACA,WAAW,MAAM,KAAK,QAAQ,KAAK,SAAS,CAC7C,CACW,QAAO;EAAE,IAAI;EAAO,QAAQ;EAAkD;AAI1F,KAAI,WAAW,MAAM,qBAAqB,KAAK,CAC7C,QAAO;EAAE,IAAI;EAAO,QAAQ;EAAiD;AAG/E,QAAO;EAAE,IAAI;EAAM;EAAM,WAAW;EAAK,UAAU,YAAY;EAAM"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
const require_auth_context = require('./auth-context.cjs');
|
|
2
|
+
const require_read_blocklet_scope = require('../scope/read-blocklet-scope.cjs');
|
|
3
|
+
let ufo = require("ufo");
|
|
4
|
+
let _aigne_afs = require("@aigne/afs");
|
|
5
|
+
let _aigne_afs_logger = require("@aigne/afs-logger");
|
|
6
|
+
let _aigne_afs_timing = require("@aigne/afs-timing");
|
|
7
|
+
|
|
8
|
+
//#region src/http/request-context.ts
|
|
9
|
+
/**
|
|
10
|
+
* Shared HTTP request-context + scoped-AFS helper (afs-preview T2.0).
|
|
11
|
+
*
|
|
12
|
+
* `createAfsRpcHandler` historically封装ed blocklet/host resolution, the
|
|
13
|
+
* per-blocklet projection cache, caller/trusted-context resolution, and the
|
|
14
|
+
* per-request overlay inside one closure — unreachable for the raw-bytes
|
|
15
|
+
* endpoint. This module extracts that pipeline so RPC and raw share ONE
|
|
16
|
+
* implementation (copying an incomplete auth/overlay stack = permission
|
|
17
|
+
* bypass; the HTTP/WS dual-overlay lesson).
|
|
18
|
+
*
|
|
19
|
+
* CACHE SEMANTICS (pinned, design §3): the projection cache is
|
|
20
|
+
* PER-HELPER-INSTANCE. rpc and raw each instantiate their own helper —
|
|
21
|
+
* shared code, NOT shared runtime state. raw must never reach into rpc's
|
|
22
|
+
* cache.
|
|
23
|
+
*
|
|
24
|
+
* SESSION ID: `resolveScoped` takes an EXPLICIT `sessionId` parameter. The
|
|
25
|
+
* raw endpoint passes the signature-verified sid; it never flows through
|
|
26
|
+
* any `sessionId ?? "rpc-<blocklet>"` fallback (that fallback lives in the
|
|
27
|
+
* CF rpc overlay closure and stays rpc-only).
|
|
28
|
+
*/
|
|
29
|
+
/** afs:auth structured logger (debug self-guards; off by default). */
|
|
30
|
+
const authLog = (0, _aigne_afs.nsLog)("afs:auth");
|
|
31
|
+
const DEFAULT_PROJECTION_CACHE_LIMIT = 32;
|
|
32
|
+
const DEFAULT_REGISTRY_PATH = "/registry/blocklets";
|
|
33
|
+
/**
|
|
34
|
+
* Ops the default read-only blocklet projection allows through. Superset of
|
|
35
|
+
* the request-type vocabulary: `query` is a read-class SEMANTIC op (judged by
|
|
36
|
+
* `semanticOpForRootAction` when `/.actions/query` rides exec) but NOT a wire
|
|
37
|
+
* op — requests still arrive as `type: "exec"` (zero protocol change,
|
|
38
|
+
* design §3.1).
|
|
39
|
+
*/
|
|
40
|
+
const PROJECTION_READ_OPS = new Set([
|
|
41
|
+
"read",
|
|
42
|
+
"list",
|
|
43
|
+
"stat",
|
|
44
|
+
"search",
|
|
45
|
+
"exec",
|
|
46
|
+
"query"
|
|
47
|
+
]);
|
|
48
|
+
function makeDefaultBlockletAFSFactory(registryPath) {
|
|
49
|
+
return async function defaultCreateBlockletAFS(blocklet, globalAFS) {
|
|
50
|
+
if (await require_read_blocklet_scope.readBlockletScope(globalAFS, blocklet) === "root") return globalAFS;
|
|
51
|
+
const sessionAFS = new _aigne_afs.AFS();
|
|
52
|
+
await sessionAFS.mount(new _aigne_afs.ProjectionProvider({
|
|
53
|
+
name: blocklet,
|
|
54
|
+
globalAFS,
|
|
55
|
+
sourcePath: (0, ufo.joinURL)(registryPath, blocklet),
|
|
56
|
+
allowedOps: PROJECTION_READ_OPS
|
|
57
|
+
}), "/");
|
|
58
|
+
return sessionAFS;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function normalizeHostAliasCandidate(host) {
|
|
62
|
+
const value = host.trim().toLowerCase();
|
|
63
|
+
if (!value) return void 0;
|
|
64
|
+
for (let i = 0; i < value.length; i++) {
|
|
65
|
+
const code = value.charCodeAt(i);
|
|
66
|
+
if (code <= 32 || code === 127) return void 0;
|
|
67
|
+
}
|
|
68
|
+
if (value.includes("/") || value.includes("@") || value.includes("\\")) return void 0;
|
|
69
|
+
if (value.startsWith("[")) return void 0;
|
|
70
|
+
const colonCount = (value.match(/:/g) ?? []).length;
|
|
71
|
+
if (colonCount > 1) return void 0;
|
|
72
|
+
let hostname = value;
|
|
73
|
+
if (colonCount === 1) {
|
|
74
|
+
const [name, port] = value.split(":");
|
|
75
|
+
if (!name || !port || !/^\d+$/.test(port)) return void 0;
|
|
76
|
+
hostname = name;
|
|
77
|
+
}
|
|
78
|
+
hostname = hostname.replace(/\.$/, "");
|
|
79
|
+
return hostname || void 0;
|
|
80
|
+
}
|
|
81
|
+
function createAfsRequestContext(options) {
|
|
82
|
+
const cache = /* @__PURE__ */ new Map();
|
|
83
|
+
const cacheLimit = Math.max(1, options.projectionCacheLimit ?? DEFAULT_PROJECTION_CACHE_LIMIT);
|
|
84
|
+
const registryPath = options.registryPath ?? DEFAULT_REGISTRY_PATH;
|
|
85
|
+
const factory = options.createBlockletAFS ?? makeDefaultBlockletAFSFactory(registryPath);
|
|
86
|
+
async function getBlockletAFS(blocklet) {
|
|
87
|
+
const existing = cache.get(blocklet);
|
|
88
|
+
if (existing) {
|
|
89
|
+
cache.delete(blocklet);
|
|
90
|
+
cache.set(blocklet, existing);
|
|
91
|
+
(0, _aigne_afs_timing.timeMeta)("bafs", "hit");
|
|
92
|
+
return existing;
|
|
93
|
+
}
|
|
94
|
+
const fresh = await (0, _aigne_afs_timing.time)("bafs", () => factory(blocklet, options.globalAFS));
|
|
95
|
+
cache.set(blocklet, fresh);
|
|
96
|
+
while (cache.size > cacheLimit) {
|
|
97
|
+
const oldest = cache.keys().next().value;
|
|
98
|
+
if (oldest === void 0) break;
|
|
99
|
+
cache.delete(oldest);
|
|
100
|
+
}
|
|
101
|
+
return fresh;
|
|
102
|
+
}
|
|
103
|
+
async function resolveBlocklet(request, explicitBlocklet, opts) {
|
|
104
|
+
const explicit = typeof explicitBlocklet === "string" && explicitBlocklet ? explicitBlocklet : null;
|
|
105
|
+
if ((opts?.explicitPriority ?? "trusted") === "trusted" && explicit) return explicit;
|
|
106
|
+
const url = new URL(request.url);
|
|
107
|
+
const queryBlocklet = url.searchParams.get("blocklet");
|
|
108
|
+
if ((opts?.queryPriority ?? "trusted") === "trusted" && queryBlocklet) return queryBlocklet;
|
|
109
|
+
const host = request.headers.get("Host") ?? url.host;
|
|
110
|
+
const aliasHost = normalizeHostAliasCandidate(host);
|
|
111
|
+
if (options.resolveHostAlias && aliasHost) {
|
|
112
|
+
const aliased = await options.resolveHostAlias(aliasHost);
|
|
113
|
+
if (aliased) return aliased;
|
|
114
|
+
}
|
|
115
|
+
const fromHost = (0, _aigne_afs.extractBlockletFromHost)(host, options.domainRoots ? { domainRoots: options.domainRoots } : void 0);
|
|
116
|
+
if (fromHost) return fromHost;
|
|
117
|
+
if (explicit) return explicit;
|
|
118
|
+
if (queryBlocklet) return queryBlocklet;
|
|
119
|
+
return options.fallbackBlocklet ?? null;
|
|
120
|
+
}
|
|
121
|
+
async function resolveCaller(request) {
|
|
122
|
+
const caller = options.resolveCaller ? await (0, _aigne_afs_timing.time)("auth", () => options.resolveCaller(request)) : null;
|
|
123
|
+
authLog.debug({
|
|
124
|
+
message: "caller resolved",
|
|
125
|
+
userDid: caller?.did ?? null,
|
|
126
|
+
authMethod: caller?.authMethod
|
|
127
|
+
});
|
|
128
|
+
return caller;
|
|
129
|
+
}
|
|
130
|
+
async function resolveScoped(request, args) {
|
|
131
|
+
const { blocklet, sessionId, caller } = args;
|
|
132
|
+
const scope = await require_read_blocklet_scope.readBlockletScope(options.globalAFS, blocklet);
|
|
133
|
+
let afs = await getBlockletAFS(blocklet);
|
|
134
|
+
const trusted = options.resolveTrustedAfsContext ? await options.resolveTrustedAfsContext(request, {
|
|
135
|
+
blocklet,
|
|
136
|
+
caller,
|
|
137
|
+
sessionId
|
|
138
|
+
}) : {
|
|
139
|
+
instanceDid: blocklet,
|
|
140
|
+
agentRunOrigin: "interactive"
|
|
141
|
+
};
|
|
142
|
+
trusted.callerOrigin = "network";
|
|
143
|
+
const context = require_auth_context.mergeCallerContext(args.opOptions ?? {}, caller, trusted);
|
|
144
|
+
if (!context.requestId) {
|
|
145
|
+
const rid = (0, _aigne_afs_timing.getTiming)()?.requestId;
|
|
146
|
+
if (rid) context.requestId = rid;
|
|
147
|
+
}
|
|
148
|
+
const identity = { blockletId: blocklet };
|
|
149
|
+
if (caller?.did) identity.userDid = caller.did;
|
|
150
|
+
if (trusted.instanceDid) identity.instanceDid = trusted.instanceDid;
|
|
151
|
+
if (sessionId) identity.sessionId = sessionId;
|
|
152
|
+
(0, _aigne_afs_logger.getLogContext)()?.enrich(identity);
|
|
153
|
+
if (options.overlayForRequest && scope !== "root") try {
|
|
154
|
+
afs = await (0, _aigne_afs_timing.time)("ovl", () => options.overlayForRequest(afs, {
|
|
155
|
+
blocklet,
|
|
156
|
+
caller,
|
|
157
|
+
sessionId,
|
|
158
|
+
scope,
|
|
159
|
+
instanceDid: trusted.instanceDid
|
|
160
|
+
}));
|
|
161
|
+
} catch {}
|
|
162
|
+
return {
|
|
163
|
+
blocklet,
|
|
164
|
+
scope,
|
|
165
|
+
afs,
|
|
166
|
+
caller,
|
|
167
|
+
context
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
resolveBlocklet,
|
|
172
|
+
resolveScoped,
|
|
173
|
+
resolveCaller
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
exports.createAfsRequestContext = createAfsRequestContext;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BlockletScope } from "../scope/types.cjs";
|
|
2
|
+
import { ResolveCallerFn, ResolveTrustedAfsContext } from "./auth-context.cjs";
|
|
3
|
+
import { AFSRoot, CallerInfo } from "@aigne/afs";
|
|
4
|
+
|
|
5
|
+
//#region src/http/request-context.d.ts
|
|
6
|
+
interface AfsRequestContextOptions {
|
|
7
|
+
/** The runtime-global AFS (the projection's source). */
|
|
8
|
+
globalAFS: AFSRoot;
|
|
9
|
+
/** Roots passed to `extractBlockletFromHost` (e.g. `["afsd.io"]`). */
|
|
10
|
+
domainRoots?: string[];
|
|
11
|
+
/** Resolve a normalized Host hostname to a blocklet id (runtime alias map). */
|
|
12
|
+
resolveHostAlias?: (host: string) => Promise<string | undefined> | string | undefined;
|
|
13
|
+
/** Used when neither explicit value, query, nor Host header resolve a blocklet. */
|
|
14
|
+
fallbackBlocklet?: string;
|
|
15
|
+
/** Bound on how many distinct blocklet projections we keep in memory. */
|
|
16
|
+
projectionCacheLimit?: number;
|
|
17
|
+
/** Where the blocklet catalog lives in the global AFS. */
|
|
18
|
+
registryPath?: string;
|
|
19
|
+
/** Test seam / runtime adapter: override the projected-AFS factory. */
|
|
20
|
+
createBlockletAFS?: (blocklet: string, globalAFS: AFSRoot) => Promise<AFSRoot>;
|
|
21
|
+
/** Resolve a verified caller from the inbound request. */
|
|
22
|
+
resolveCaller?: ResolveCallerFn;
|
|
23
|
+
/** Resolve the trusted, host-controlled AFSContext slice. */
|
|
24
|
+
resolveTrustedAfsContext?: ResolveTrustedAfsContext;
|
|
25
|
+
/** Optional PER-REQUEST overlay (per-caller `/user`, per-session `/tmp`, …). */
|
|
26
|
+
overlayForRequest?: (baseAFS: AFSRoot, ctx: {
|
|
27
|
+
blocklet: string;
|
|
28
|
+
caller: CallerInfo | null;
|
|
29
|
+
sessionId: string | null;
|
|
30
|
+
scope: BlockletScope;
|
|
31
|
+
/**
|
|
32
|
+
* Host-resolved instanceDid (the trusted-context slice), present even for an
|
|
33
|
+
* ANONYMOUS caller. Use this — NOT `caller.instanceDid` — for the `/instance`
|
|
34
|
+
* partition key, so anonymous + bound-host reads land on the SAME tenant the
|
|
35
|
+
* WS / DO path uses (instance-resolve F-2).
|
|
36
|
+
*/
|
|
37
|
+
instanceDid?: string;
|
|
38
|
+
}) => AFSRoot | Promise<AFSRoot>;
|
|
39
|
+
}
|
|
40
|
+
interface ScopedRequest {
|
|
41
|
+
blocklet: string;
|
|
42
|
+
scope: BlockletScope;
|
|
43
|
+
/** The per-request AFS view (cached base + uncached per-request overlay). */
|
|
44
|
+
afs: AFSRoot;
|
|
45
|
+
caller: CallerInfo | null;
|
|
46
|
+
/** Merged op context (caller + trusted slice + callerOrigin + requestId). */
|
|
47
|
+
context: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
interface AfsRequestContext {
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the target blocklet. The default treats explicitBlocklet as trusted
|
|
52
|
+
* (signed raw URLs); HTTP RPC passes explicitPriority:"fallback" so the
|
|
53
|
+
* server-resolved Host/alias wins over browser-provided hints.
|
|
54
|
+
*/
|
|
55
|
+
resolveBlocklet(request: Request, explicitBlocklet?: string | null, opts?: {
|
|
56
|
+
explicitPriority?: "trusted" | "fallback";
|
|
57
|
+
queryPriority?: "trusted" | "fallback";
|
|
58
|
+
}): Promise<string | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Build the per-request scoped view + op context. `sessionId` is the
|
|
61
|
+
* caller-supplied session identity (rpc: body.sessionId; raw: the
|
|
62
|
+
* signature-verified sid) — null means "no session".
|
|
63
|
+
*/
|
|
64
|
+
resolveScoped(request: Request, args: {
|
|
65
|
+
blocklet: string;
|
|
66
|
+
sessionId: string | null;
|
|
67
|
+
caller: CallerInfo | null;
|
|
68
|
+
opOptions?: Record<string, unknown>;
|
|
69
|
+
}): Promise<ScopedRequest>;
|
|
70
|
+
/** Resolve the verified caller (or null when no resolver / anonymous). */
|
|
71
|
+
resolveCaller(request: Request): Promise<CallerInfo | null>;
|
|
72
|
+
}
|
|
73
|
+
declare function createAfsRequestContext(options: AfsRequestContextOptions): AfsRequestContext;
|
|
74
|
+
//#endregion
|
|
75
|
+
export { AfsRequestContext, AfsRequestContextOptions, ScopedRequest, createAfsRequestContext };
|
|
76
|
+
//# sourceMappingURL=request-context.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context.d.cts","names":[],"sources":["../../src/http/request-context.ts"],"mappings":";;;;;UAuDiB,wBAAA;EAcf;EAZA,SAAA,EAAW,OAAA;EAYuC;EAVlD,WAAA;EAU8D;EAR9D,gBAAA,IAAoB,IAAA,aAAiB,OAAA;EAUrC;EARA,gBAAA;EAUA;EARA,oBAAA;EAUA;EARA,YAAA;EASE;EAPF,iBAAA,IAAqB,QAAA,UAAkB,SAAA,EAAW,OAAA,KAAY,OAAA,CAAQ,OAAA;EAUlE;EARJ,aAAA,GAAgB,eAAA;EASZ;EAPJ,wBAAA,GAA2B,wBAAA;EAQhB;EANX,iBAAA,IACE,OAAA,EAAS,OAAA,EACT,GAAA;IACE,QAAA;IACA,MAAA,EAAQ,UAAA;IACR,SAAA;IACA,KAAA,EAAO,aAAA;IASmB;;AAGhC;;;;IALM,WAAA;EAAA,MAEC,OAAA,GAAU,OAAA,CAAQ,OAAA;AAAA;AAAA,UAGR,aAAA;EACf,QAAA;EACA,KAAA,EAAO,aAAA;EAAP;EAEA,GAAA,EAAK,OAAA;EACL,MAAA,EAAQ,UAAA;EADH;EAGL,OAAA,EAAS,MAAA;AAAA;AAAA,UAGM,iBAAA;EAHN;;;AAGX;;EAME,eAAA,CACE,OAAA,EAAS,OAAA,EACT,gBAAA,kBACA,IAAA;IACE,gBAAA;IACA,aAAA;EAAA,IAED,OAAA;EAWS;;;;;EALZ,aAAA,CACE,OAAA,EAAS,OAAA,EACT,IAAA;IACE,QAAA;IACA,SAAA;IACA,MAAA,EAAQ,UAAA;IACR,SAAA,GAAY,MAAA;EAAA,IAEb,OAAA,CAAQ,aAAA;EApBT;EAsBF,aAAA,CAAc,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,UAAA;AAAA;AAAA,iBAiD3B,uBAAA,CAAwB,OAAA,EAAS,wBAAA,GAA2B,iBAAA"}
|