| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
fix(collab): ship the relay image's runtime dependencies (#1867) * fix(collab): ship the relay image's runtime dependencies The v2.5.0 collab-node image exited at startup with ERR_MODULE_NOT_FOUND for `ws`. The runtime stage copied only /app/node_modules, but that is not where npm puts this worker's `ws`: the root lockfile carries two versions (8.21.0, hoisted for geolibre-desktop's transitive deps, and ^8.21.3 for the relay), so `npm ci --workspace geolibre-collab-node` installs the relay's copy at the nested workers/collab-node/node_modules, which nothing copied. The same stage left node_modules/@geolibre/collab-core dangling, since packages/collab-core was never copied either. Assemble the runtime tree under /runtime in the build stage instead, and copy that: the nested node_modules when it exists (it disappears the moment a dependency bump lets npm hoist `ws` to the root, so the copy is guarded), packages/collab-core so the workspace symlink resolves, and a prod-only reinstall so esbuild and the rest of the dev tree stay behind. The staged bundle is then imported once at build time -- side-effect-free, since server.js only listens when it is process.argv[1] -- so a future layout regression fails the build rather than the container. publish-container.yml only ever built the web Dockerfile, which is how this shipped. Add a CI job that builds the relay image, runs it, and drives scripts/smoke.mjs against it: health, session creation, and a WebSocket join round-trip. A build alone would not have caught this, only starting the container does. Fixes #1866 * Address review feedback - Correct the Dockerfile's framing of packages/collab-core: esbuild inlines @geolibre/collab-core, so the running server never imports it and it was not what broke the image. It is copied only so the symlink npm leaves in node_modules points at something, and the build-time `test` on it asserts the tree was copied whole rather than guarding startup. - Fix the README's stale claim that the failure is invisible to `docker build`: the Dockerfile now imports the staged bundle there, so the smoke test covers what only a running container shows (the process stays up and serves HTTP and a WebSocket upgrade). - Bound the smoke test's health probes with AbortSignal.timeout, capped by the remaining startup budget. A container that accepts the connection and never answers otherwise falls back on undici's minutes-long timeouts and stalls the job past the budget instead of failing at it. Verified against a black-hole listener: fails at the budget rather than hanging. POST /sessions is bounded the same way. | 2 个月前 | |
fix(collab): allow hosted app origins (#2011) * fix(collab): allow hosted app origins The production web and studio hosts were missing from the relay defaults, causing session creation to fail with HTTP 403. Keep both relay implementations aligned and cover the hosted origins with a regression test. * fix(collab): allow deployment preview origins PR previews run on the project-owned Cloudflare Pages hostname and opengeos.org, so the production relay must accept those origins too. Keep custom operator allowlists authoritative and reject look-alike preview domains. * Address CodeRabbit review feedback - Document every default collaboration origin category so the operator note matches the relay policy. * Address review feedback - Remove blanket trust for the shared opengeos.org preview origin. - Restrict Cloudflare previews to one label, HTTPS, and the default port. - Make custom ALLOWED_ORIGINS settings authoritative over local defaults. - Cover nested, custom-port, shared-host, and configured-origin cases. - Document the exact default preview-origin policy and exclusions. | 2 个月前 | |
fix(collab): allow hosted app origins (#2011) * fix(collab): allow hosted app origins The production web and studio hosts were missing from the relay defaults, causing session creation to fail with HTTP 403. Keep both relay implementations aligned and cover the hosted origins with a regression test. * fix(collab): allow deployment preview origins PR previews run on the project-owned Cloudflare Pages hostname and opengeos.org, so the production relay must accept those origins too. Keep custom operator allowlists authoritative and reject look-alike preview domains. * Address CodeRabbit review feedback - Document every default collaboration origin category so the operator note matches the relay policy. * Address review feedback - Remove blanket trust for the shared opengeos.org preview origin. - Restrict Cloudflare previews to one label, HTTPS, and the default port. - Make custom ALLOWED_ORIGINS settings authoritative over local defaults. - Cover nested, custom-port, shared-host, and configured-origin cases. - Document the exact default preview-origin policy and exclusions. | 2 个月前 | |
fix: load rasters with large TIFF metadata (#2209) * fix: load rasters with large TIFF metadata Decode large ASCII TIFF tags in bounded chunks so browser argument limits do not reject otherwise valid cloud-hosted rasters. * Address Copilot and Claude review feedback - Apply dependency patches only when the raster dependency is installed. - Stage patch inputs before Docker installs so web images receive the fix. - Add a large TIFF metadata regression test and document sliced-view offsets. * style: auto-format (ruff + oxfmt) [pre-commit.ci] * Address CodeRabbit review feedback - Assert the exact decoded GDAL metadata value. - Cover ASCII decoding from a DataView with a non-zero byte offset. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> | 1 个月前 | |
fix(collab): ship the relay image's runtime dependencies (#1867) * fix(collab): ship the relay image's runtime dependencies The v2.5.0 collab-node image exited at startup with ERR_MODULE_NOT_FOUND for `ws`. The runtime stage copied only /app/node_modules, but that is not where npm puts this worker's `ws`: the root lockfile carries two versions (8.21.0, hoisted for geolibre-desktop's transitive deps, and ^8.21.3 for the relay), so `npm ci --workspace geolibre-collab-node` installs the relay's copy at the nested workers/collab-node/node_modules, which nothing copied. The same stage left node_modules/@geolibre/collab-core dangling, since packages/collab-core was never copied either. Assemble the runtime tree under /runtime in the build stage instead, and copy that: the nested node_modules when it exists (it disappears the moment a dependency bump lets npm hoist `ws` to the root, so the copy is guarded), packages/collab-core so the workspace symlink resolves, and a prod-only reinstall so esbuild and the rest of the dev tree stay behind. The staged bundle is then imported once at build time -- side-effect-free, since server.js only listens when it is process.argv[1] -- so a future layout regression fails the build rather than the container. publish-container.yml only ever built the web Dockerfile, which is how this shipped. Add a CI job that builds the relay image, runs it, and drives scripts/smoke.mjs against it: health, session creation, and a WebSocket join round-trip. A build alone would not have caught this, only starting the container does. Fixes #1866 * Address review feedback - Correct the Dockerfile's framing of packages/collab-core: esbuild inlines @geolibre/collab-core, so the running server never imports it and it was not what broke the image. It is copied only so the symlink npm leaves in node_modules points at something, and the build-time `test` on it asserts the tree was copied whole rather than guarding startup. - Fix the README's stale claim that the failure is invisible to `docker build`: the Dockerfile now imports the staged bundle there, so the smoke test covers what only a running container shows (the process stays up and serves HTTP and a WebSocket upgrade). - Bound the smoke test's health probes with AbortSignal.timeout, capped by the remaining startup budget. A container that accepts the connection and never answers otherwise falls back on undici's minutes-long timeouts and stalls the job past the budget instead of failing at it. Verified against a black-hole listener: fails at the budget rather than hanging. POST /sessions is bounded the same way. | 2 个月前 | |
build(deps): bump the npm-minor-patch group across 1 directory with 38 updates (#2982) * build(deps): bump the npm-minor-patch group across 1 directory with 38 updates Bumps the npm-minor-patch group with 38 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.6.3` | `26.6.4` | | [eslint](https://github.com/eslint/eslint) | `10.11.0` | `10.12.0` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.70.1` | `8.71.0` | | [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript) | `0.128.0` | `0.131.0` | | [@auth0/auth0-react](https://github.com/auth0/auth0-react) | `2.27.0` | `2.28.2` | | [@aws-sdk/client-bedrock](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-bedrock) | `3.1141.0` | `3.1146.0` | | [@carbonplan/zarr-layer](https://github.com/carbonplan/zarr-layer) | `0.10.0` | `0.11.0` | | [@cereusdb/standard](https://github.com/tobilg/cereusdb/tree/HEAD/packages/standard) | `0.2.0` | `0.3.0` | | [@cesium/engine](https://github.com/CesiumGS/cesium) | `26.3.0` | `26.4.0` | | [@cesium/widgets](https://github.com/CesiumGS/cesium) | `16.2.0` | `16.3.0` | | [@clerk/react](https://github.com/clerk/javascript/tree/HEAD/packages/react) | `6.17.2` | `6.17.5` | | [@developmentseed/deck.gl-geotiff](https://github.com/developmentseed/deck.gl-raster) | `0.7.0` | `0.8.1` | | [@developmentseed/deck.gl-raster](https://github.com/developmentseed/deck.gl-raster) | `0.7.0` | `0.8.1` | | [@google/genai](https://github.com/googleapis/js-genai) | `2.24.0` | `2.27.0` | | [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk) | `1.30.1` | `1.32.0` | | [@tauri-apps/api](https://github.com/tauri-apps/tauri) | `2.11.1` | `2.12.1` | | [@tauri-apps/plugin-deep-link](https://github.com/tauri-apps/plugins-workspace) | `2.4.10` | `2.6.1` | | [@tauri-apps/plugin-dialog](https://github.com/tauri-apps/plugins-workspace) | `2.7.3` | `2.8.1` | | [@tauri-apps/plugin-fs](https://github.com/tauri-apps/plugins-workspace) | `2.5.2` | `2.6.0` | | [@tauri-apps/plugin-geolocation](https://github.com/tauri-apps/plugins-workspace) | `2.3.3` | `2.4.1` | | [@tauri-apps/plugin-http](https://github.com/tauri-apps/plugins-workspace) | `2.6.1` | `2.8.0` | | [@tauri-apps/plugin-opener](https://github.com/tauri-apps/plugins-workspace) | `2.5.5` | `2.7.0` | | [cesium](https://github.com/CesiumGS/cesium) | `1.145.0` | `1.146.0` | | [html2canvas-pro](https://github.com/yorickshan/html2canvas-pro) | `2.4.5` | `2.5.0` | | [openai](https://github.com/openai/openai-node) | `7.23.0` | `7.27.0` | | [@tauri-apps/cli](https://github.com/tauri-apps/tauri) | `2.11.5` | `2.12.1` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.3.1` | `8.3.2` | | [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) | `5.11.1` | `5.11.2` | | [mapbox-gl](https://github.com/mapbox/mapbox-gl-js) | `3.31.0` | `3.32.0` | | [zarr-cesium](https://github.com/NOC-OI/zarr-cesium) | `0.3.3` | `0.3.5` | | [@developmentseed/morecantile](https://github.com/developmentseed/deck.gl-raster) | `0.7.0` | `0.8.1` | | [hyparquet](https://github.com/hyparam/hyparquet) | `1.31.1` | `1.31.2` | | [webdggrid](https://github.com/am2222/webDggrid) | `1.9.0` | `1.9.2` | | [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.48.0` | `1.50.0` | | [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) | `4.141.0` | `4.147.0` | | [@cloudflare/workers-types](https://github.com/cloudflare/workerd) | `5.20260926.1` | `5.20261003.1` | | [ws](https://github.com/websockets/ws) | `8.21.3` | `8.22.0` | | [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) | `8.18.1` | `8.18.2` | | [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) | `8.18.1` | `8.18.2` | Updates `@types/node` from 26.6.3 to 26.6.4 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `eslint` from 10.11.0 to 10.12.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v10.11.0...v10.12.0) Updates `typescript-eslint` from 8.70.1 to 8.71.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.71.0/packages/typescript-eslint) Updates `@anthropic-ai/sdk` from 0.128.0 to 0.131.0 - [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases) - [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md) - [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.128.0...sdk-v0.131.0) Updates `@auth0/auth0-react` from 2.27.0 to 2.28.2 - [Release notes](https://github.com/auth0/auth0-react/releases) - [Changelog](https://github.com/auth0/auth0-react/blob/main/CHANGELOG.md) - [Commits](https://github.com/auth0/auth0-react/compare/v2.27.0...v2.28.2) Updates `@aws-sdk/client-bedrock` from 3.1141.0 to 3.1146.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-bedrock/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.1146.0/clients/client-bedrock) Updates `@carbonplan/zarr-layer` from 0.10.0 to 0.11.0 - [Release notes](https://github.com/carbonplan/zarr-layer/releases) - [Commits](https://github.com/carbonplan/zarr-layer/compare/v0.10.0...v0.11.0) Updates `@cereusdb/standard` from 0.2.0 to 0.3.0 - [Release notes](https://github.com/tobilg/cereusdb/releases) - [Commits](https://github.com/tobilg/cereusdb/commits/v0.3.0/packages/standard) Updates `@cesium/engine` from 26.3.0 to 26.4.0 - [Release notes](https://github.com/CesiumGS/cesium/releases) - [Changelog](https://github.com/CesiumGS/cesium/blob/main/CHANGES.md) - [Commits](https://github.com/CesiumGS/cesium/commits) Updates `@cesium/widgets` from 16.2.0 to 16.3.0 - [Release notes](https://github.com/CesiumGS/cesium/releases) - [Changelog](https://github.com/CesiumGS/cesium/blob/main/CHANGES.md) - [Commits](https://github.com/CesiumGS/cesium/commits) Updates `@clerk/react` from 6.17.2 to 6.17.5 - [Release notes](https://github.com/clerk/javascript/releases) - [Changelog](https://github.com/clerk/javascript/blob/main/packages/react/CHANGELOG.md) - [Commits](https://github.com/clerk/javascript/commits/@clerk/react@6.17.5/packages/react) Updates `@developmentseed/deck.gl-geotiff` from 0.7.0 to 0.8.1 - [Release notes](https://github.com/developmentseed/deck.gl-raster/releases) - [Changelog](https://github.com/developmentseed/deck.gl-raster/blob/main/CHANGELOG.md) - [Commits](https://github.com/developmentseed/deck.gl-raster/compare/v0.7.0...v0.8.1) Updates `@developmentseed/deck.gl-raster` from 0.7.0 to 0.8.1 - [Release notes](https://github.com/developmentseed/deck.gl-raster/releases) - [Changelog](https://github.com/developmentseed/deck.gl-raster/blob/main/CHANGELOG.md) - [Commits](https://github.com/developmentseed/deck.gl-raster/compare/v0.7.0...v0.8.1) Updates `@google/genai` from 2.24.0 to 2.27.0 - [Release notes](https://github.com/googleapis/js-genai/releases) - [Changelog](https://github.com/googleapis/js-genai/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/js-genai/compare/v2.24.0...v2.27.0) Updates `@modelcontextprotocol/sdk` from 1.30.1 to 1.32.0 - [Release notes](https://github.com/modelcontextprotocol/typescript-sdk/releases) - [Commits](https://github.com/modelcontextprotocol/typescript-sdk/compare/1.30.1...1.32.0) Updates `@tauri-apps/api` from 2.11.1 to 2.12.1 - [Release notes](https://github.com/tauri-apps/tauri/releases) - [Commits](https://github.com/tauri-apps/tauri/compare/@tauri-apps/api-v2.11.1...@tauri-apps/api-v2.12.1) Updates `@tauri-apps/plugin-deep-link` from 2.4.10 to 2.6.1 - [Release notes](https://github.com/tauri-apps/plugins-workspace/releases) - [Commits](https://github.com/tauri-apps/plugins-workspace/compare/deep-link-v2.4.10...http-v2.6.1) Updates `@tauri-apps/plugin-dialog` from 2.7.3 to 2.8.1 - [Release notes](https://github.com/tauri-apps/plugins-workspace/releases) - [Commits](https://github.com/tauri-apps/plugins-workspace/compare/dialog-v2.7.3...dialog-v2.8.1) Updates `@tauri-apps/plugin-fs` from 2.5.2 to 2.6.0 - [Release notes](https://github.com/tauri-apps/plugins-workspace/releases) - [Commits](https://github.com/tauri-apps/plugins-workspace/compare/fs-v2.5.2...fs-v2.6.0) Updates `@tauri-apps/plugin-geolocation` from 2.3.3 to 2.4.1 - [Release notes](https://github.com/tauri-apps/plugins-workspace/releases) - [Commits](https://github.com/tauri-apps/plugins-workspace/compare/nfc-v2.3.3...fs-v2.4.1) Updates `@tauri-apps/plugin-http` from 2.6.1 to 2.8.0 - [Release notes](https://github.com/tauri-apps/plugins-workspace/releases) - [Commits](https://github.com/tauri-apps/plugins-workspace/compare/http-v2.6.1...log-v2.8.0) Updates `@tauri-apps/plugin-opener` from 2.5.5 to 2.7.0 - [Release notes](https://github.com/tauri-apps/plugins-workspace/releases) - [Commits](https://github.com/tauri-apps/plugins-workspace/compare/http-v2.5.5...log-v2.7.0) Updates `cesium` from 1.145.0 to 1.146.0 - [Release notes](https://github.com/CesiumGS/cesium/releases) - [Changelog](https://github.com/CesiumGS/cesium/blob/main/CHANGES.md) - [Commits](https://github.com/CesiumGS/cesium/compare/1.145...1.146) Updates `html2canvas-pro` from 2.4.5 to 2.5.0 - [Release notes](https://github.com/yorickshan/html2canvas-pro/releases) - [Changelog](https://github.com/yorickshan/html2canvas-pro/blob/main/CHANGELOG.md) - [Commits](https://github.com/yorickshan/html2canvas-pro/compare/v2.4.5...v2.5.0) Updates `openai` from 7.23.0 to 7.27.0 - [Release notes](https://github.com/openai/openai-node/releases) - [Changelog](https://github.com/openai/openai-node/blob/main/CHANGELOG.md) - [Commits](https://github.com/openai/openai-node/compare/v7.23.0...v7.27.0) Updates `@tauri-apps/cli` from 2.11.5 to 2.12.1 - [Release notes](https://github.com/tauri-apps/tauri/releases) - [Commits](https://github.com/tauri-apps/tauri/compare/@tauri-apps/cli-v2.11.5...@tauri-apps/cli-v2.12.1) Updates `vite` from 8.3.1 to 8.3.2 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.3.2/packages/vite) Updates `fast-xml-parser` from 5.11.1 to 5.11.2 - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.11.1...v5.11.2) Updates `mapbox-gl` from 3.31.0 to 3.32.0 - [Release notes](https://github.com/mapbox/mapbox-gl-js/releases) - [Changelog](https://github.com/mapbox/mapbox-gl-js/blob/main/CHANGELOG.md) - [Commits](https://github.com/mapbox/mapbox-gl-js/compare/v3.31.0...v3.32.0) Updates `zarr-cesium` from 0.3.3 to 0.3.5 - [Release notes](https://github.com/NOC-OI/zarr-cesium/releases) - [Commits](https://github.com/NOC-OI/zarr-cesium/compare/v0.3.3...v0.3.5) Updates `@developmentseed/morecantile` from 0.7.0 to 0.8.1 - [Release notes](https://github.com/developmentseed/deck.gl-raster/releases) - [Changelog](https://github.com/developmentseed/deck.gl-raster/blob/main/CHANGELOG.md) - [Commits](https://github.com/developmentseed/deck.gl-raster/compare/v0.7.0...v0.8.1) Updates `hyparquet` from 1.31.1 to 1.31.2 - [Changelog](https://github.com/hyparam/hyparquet/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyparam/hyparquet/compare/v1.31.1...v1.31.2) Updates `webdggrid` from 1.9.0 to 1.9.2 - [Release notes](https://github.com/am2222/webDggrid/releases) - [Changelog](https://github.com/am2222/webDggrid/blob/main/CHANGELOG.md) - [Commits](https://github.com/am2222/webDggrid/compare/v1.9.0...v1.9.2) Updates `lucide-react` from 1.48.0 to 1.50.0 - [Release notes](https://github.com/lucide-icons/lucide/releases) - [Commits](https://github.com/lucide-icons/lucide/commits/1.50.0/packages/lucide-react) Updates `wrangler` from 4.141.0 to 4.147.0 - [Release notes](https://github.com/cloudflare/workers-sdk/releases) - [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.147.0/packages/wrangler) Updates `@cloudflare/workers-types` from 5.20260926.1 to 5.20261003.1 - [Release notes](https://github.com/cloudflare/workerd/releases) - [Changelog](https://github.com/cloudflare/workerd/blob/main/RELEASE.md) - [Commits](https://github.com/cloudflare/workerd/commits) Updates `ws` from 8.21.3 to 8.22.0 - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/8.21.3...8.22.0) Updates `@types/ws` from 8.18.1 to 8.18.2 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ws) Updates `@types/ws` from 8.18.1 to 8.18.2 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ws) --- updated-dependencies: - dependency-name: "@anthropic-ai/sdk" dependency-version: 0.131.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@auth0/auth0-react" dependency-version: 2.28.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@aws-sdk/client-bedrock" dependency-version: 3.1146.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@carbonplan/zarr-layer" dependency-version: 0.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@cereusdb/standard" dependency-version: 0.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@cesium/engine" dependency-version: 26.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@cesium/widgets" dependency-version: 16.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@clerk/react" dependency-version: 6.17.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: "@cloudflare/workers-types" dependency-version: 5.20261003.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@developmentseed/deck.gl-geotiff" dependency-version: 0.8.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@developmentseed/deck.gl-raster" dependency-version: 0.8.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@developmentseed/morecantile" dependency-version: 0.8.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@google/genai" dependency-version: 2.27.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@modelcontextprotocol/sdk" dependency-version: 1.32.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/api" dependency-version: 2.12.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/cli" dependency-version: 2.12.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/plugin-deep-link" dependency-version: 2.6.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/plugin-dialog" dependency-version: 2.8.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/plugin-fs" dependency-version: 2.6.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/plugin-geolocation" dependency-version: 2.4.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/plugin-http" dependency-version: 2.8.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@tauri-apps/plugin-opener" dependency-version: 2.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: "@types/node" dependency-version: 26.6.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: "@types/ws" dependency-version: 8.18.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: "@types/ws" dependency-version: 8.18.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: cesium dependency-version: 1.146.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: eslint dependency-version: 10.12.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: fast-xml-parser dependency-version: 5.11.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: html2canvas-pro dependency-version: 2.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: hyparquet dependency-version: 1.31.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: lucide-react dependency-version: 1.50.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: mapbox-gl dependency-version: 3.32.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: openai dependency-version: 7.27.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: typescript-eslint dependency-version: 8.71.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: vite dependency-version: 8.3.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: webdggrid dependency-version: 1.9.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor-patch - dependency-name: wrangler dependency-version: 4.147.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: ws dependency-version: 8.22.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: npm-minor-patch - dependency-name: zarr-cesium dependency-version: 0.3.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: npm-minor-patch ... Signed-off-by: dependabot[bot] <support@github.com> * fix(deps): adapt to Cesium 1.146, deck.gl-geotiff 0.8 and zarr-layer 0.11 - Import the math/core types CesiumJS 1.146 moved to @cesium/core (Cartesian3, Color, Event, ...) from there; @cesium/engine now re-exports them only as deprecated value shims. - deck.gl-geotiff 0.8 exports inferTextureFormat at the top level instead of under a texture namespace. - Refresh the allowlisted CesiumJS default Ion token hash (1.146). - zarr-layer 0.11 routes opacity through optionalForCustom. - Bump tauri-plugin-dialog to 2.8 to match the JS guest; keep @tauri-apps/plugin-geolocation on 2.3.x to match the vendored crate, and tell Dependabot not to move it. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: giswqs <giswqs@gmail.com> | 16 天前 | |
feat(server): add a self-hostable projects API and collaboration relay (#1690) * feat(server): add a self-hostable projects API and collaboration relay Sharing, accounts, and live collaboration could only ever run on share.geolibre.app and Cloudflare, so a self-hoster running the Docker image got the map and the sidecar but none of it. Write the projects and identity contract down, add a FastAPI reference implementation of it, lift the collab session logic out of the Durable Object into a shared core, and host that core from a plain Node relay as well. One conformance suite runs against both relays so their permission behavior cannot drift. Closes #1685 Closes #1686 * fix(server): unbreak the Docker stack found by an end-to-end run Three defects only a real `docker compose up` surfaces. The entrypoint embeds its runtime-config program in a single-quoted `python -c`, so the apostrophes in `'/'.join(...)` closed that argument and every web container died at boot on a SyntaxError. The server image created only /data, so a named volume mounted at /data/objects came up root-owned and the unprivileged user could not write any project. Forking required a request body despite documenting a private default, so a bodyless "fork this" answered 422. * Address Copilot, Claude, and CodeRabbit review feedback Relay, crash and correctness: - Reject non-object JSON before reading .type. `null` is valid JSON, so one frame from any client threw inside the ws listener and killed the process, taking every other session with it. Reproduced against the container, which Docker then restarted. handleMessage is also wrapped defensively. - Answer presence frames before the per-message SQLite read. It is a synchronous SELECT * over the snapshot and chat blobs, and this relay hosts every session in one process, so a cursor burst added latency to unrelated sessions. - Add an error listener to the session-create request stream and destroy the request past the size cap, rather than reading on forever. - Sweep sessions that were created but never joined; only the socket-close path deleted rows, so an unjoined code lived in SQLite forever. - Add a ping/pong heartbeat, so a connection dropped without a close frame stops pinning the roster and blocking idle cleanup, and terminate sockets that never finish the closing handshake instead of hanging shutdown. - Make saveSnapshot atomic with UPDATE ... RETURNING rev. - Trim in sanitizeDisplayName: a whitespace-only name is truthy and reached the roster, participant broadcasts, and chat author fields. Server correctness and hardening: - USERNAME_RE accepted a 1-character name; the middle group was optional. - Bound username and password length. Both endpoints taking them are unauthenticated and feed scrypt, so size drove CPU and memory. - Never pair a wildcard CORS origin with allow_credentials. - Enable SQLite foreign keys, so deleting an account no longer strands tokens. - Reject explicit null visibility/tags in PATCH, which returned 500 not 422. - Increment views and forkCount in SQL; the contract promises atomicity. - Allocate version numbers from max(number) with retry, so concurrent content updates cannot collide on a key and overwrite each other. - Stream thumbnail uploads instead of buffering the whole body before the check. - Build the app in a uvicorn factory; importing the module created a stray database and storage directory, including under pytest. - Return the documented account shape from /api/users/me. Packaging and docs: - Run the relay container as non-root with a healthcheck, and document the one-time chown for volumes created by an earlier root-owned image. - Re-exclude collab-node build artifacts after the .dockerignore negations. - Extend tsconfig.base.json, use the workspace "*" dependency convention, drop the duplicated SocketAttachment members and the dead socketByClientId, and share HEX_COLOR_RE/finite from one internal module. - Document `mine=true`, correct the users/{username}/projects auth description to the filtered-200 behavior the code and its tests implement, and state plainly that rate limiting and token expiry are left to the operator. - Cover unlisted visibility, explicit-null PATCH, username length, the configurable snapshot ceiling, and sanitizeView; drop the fixed sleep and the hardcoded /tmp path from the relay test. * Address CodeRabbit review feedback - Count the session-create body in UTF-8 bytes including the current chunk, and check before appending. Testing the accumulated length first accepted one final chunk of any size once the running total was still under the cap. - Answer the 413 before dropping the connection. Destroying the request immediately tore down the socket before the response could flush, so a client saw a reset instead of the status; verified against the container. - Use a level-two heading in the relay README (MD001). * Address Claude review feedback - Reject a declared Content-Length past the largest accepted body before reading it. The JSON `content` routes let Pydantic materialize the whole payload before parse_content could answer 413, the exposure the thumbnail route already avoided by streaming. - Retry slug allocation on IntegrityError in create_project. unique_slug SELECTs and the insert follows, so two concurrent creates with one title from the same account raced into a 500 rather than a clean retry. - Match the Worker in the Node relay's comment-mutation path: validate the action shape before checking permissions, so a malformed frame from a view-only guest answers bad-message on both relays rather than forbidden on one, and bound the mutated project against the snapshot ceiling before persisting it. The per-comment caps alone allow a worst case far past it. - Cover both in the relay suite, which did not exercise comment-mutation at all. * Address CodeRabbit review feedback - Size the Content-Length ceiling for worst-case JSON escaping. parse_content bounds the decoded string, and JSON may spend six wire bytes on one ASCII byte via \u00XX, so the 2x slack would have refused valid uploads at the documented limit before they were ever parsed. - Stop allocating a 101 MiB payload in the oversized-body test. The middleware decides from the header, so the request now carries two bytes and only claims to be huge. Drops the unused monkeypatch argument (ARG001). - Add a test that a fully \u-escaped document within the decoded limit is accepted, with the limits shrunk so the multiplier is what decides the outcome; it fails against the previous 2x ceiling. * Address CodeRabbit review feedback - Reject an oversized POST /sessions body on the declared Content-Length before registering the body handlers, so a request claiming a large body cannot hold the connection open while it uploads slowly. The running byte count stays for clients that omit or understate the header, and both paths now share one MAX_SESSION_BODY_BYTES constant. - Add the integration test that was asked for. It writes the request over a raw socket, because fetch refuses to send fewer bytes than it declared, and that mismatch is exactly the case under test; without the guard it times out waiting for a response instead of getting an immediate 413. This was an outside-diff-range comment in the review body rather than an inline thread, which is why it was missed in the earlier rounds. * Address Claude review feedback - Translate an IntegrityError on account creation into the documented 409. The uniqueness check and the commit are not atomic, and no IntegrityError handler is registered, so the loser of a race escaped as a raw 500. - Eager-load owner and versions on the two listing queries. project_json reads both lazily, so a page fired one query per row; measured 28 statements for 25 projects before, 4 after. - Hash on a dummy password when the account is not found, so login costs the same either way. Short-circuiting skipped scrypt for an unknown username, which enumerates accounts by response time regardless of a request-count limiter. - Handle SIGTERM and SIGINT in the relay entrypoint. Nothing outside the tests called close(), so docker stop killed the process outright and the graceful shutdown path never ran in production. - Hoist the stored-chat validators into @geolibre/collab-core and use them in both relays. The Node store only JSON-parsed the column, so a corrupt record would reach joiners and crash a client on coordinate.lat.toFixed; the Worker had guarded this alone. Covered in the conformance suite. - Warn that POSTGRES_PASSWORD is substituted into a DSN verbatim. Verified the two characters that actually break: "@" reparses the host, and "%" silently percent-decodes to a different password. "/" and ":" are fine, so the note names only what genuinely fails. * Address CodeRabbit review feedback - Register CORSMiddleware after limit_body so it stays outermost. Starlette wraps in reverse registration order, so the 413 was returned without CORS headers and a browser could not read the documented error body. Confirmed before and after, and pinned in the test. - Pin the geolibre uid/gid to 1000, which the documented volume-repair chown assumes; the base image merely happened to allocate it. - Require POSTGRES_PASSWORD instead of committing a shared default for the account that owns all project metadata, and document that Postgres only applies it at volume initialization, so rotating it later needs ALTER USER or a fresh volume. - Document binding the projects server and relay to loopback behind a proxy, with an override file; pointing the browser URLs at a proxy does not stop direct access to those listeners. - Deduplicate reply ids in validateComment. The relay's reply action already skipped a duplicate id, leaving inline replies as the one path that could persist two replies sharing an id. - Use COPY --chown in the relay image instead of a recursive chown of /app, which rewrote node_modules into a second layer. - Declare engines.node >=22.13, below which node:sqlite is flag-gated. - Reuse normalizeMode for the stored mode rather than an inline ternary that would silently downgrade a future third mode. - Document GEOLIBRE_HOST and GEOLIBRE_PORT, and that the fork request body is optional. - Pin the override-specific refusal message in the conformance suite, and correct two comments in the Worker that described code the extraction removed. * Address Claude review feedback - Filter non-object entries out of project.comments and target.replies in the Node relay. Snapshot content is opaque, so a client could plant null with an ordinary snapshot frame and every subsequent .id read threw, leaving commenting permanently broken for that session while the Worker tolerated the same data. Reproduced against the container, then covered in the relay suite. - Attach an error listener to the raw upgrade socket before writing to it. A net.Socket with no listener throws on the next TCP error, which is uncaught and stops the relay, and this is the pre-auth path most exposed to arbitrary traffic. - Retry the slug and version allocations on OperationalError too. On the SQLite default a concurrent writer surfaces as "database is locked" rather than IntegrityError, which the loops did not catch. - Add a catch-all exception handler returning the documented JSON error shape. Only HTTPException and RequestValidationError were registered, so anything else escaped as a plain-text 500. - Document that the Content-Length guard sees only a declared length, so a chunked or HTTP/2 request is still parsed in full, and that request size should also be capped at the proxy. * style: auto-format (ruff + oxfmt) [pre-commit.ci] --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> | 2 个月前 |
GeoLibre Node collaboration relay
This is the Docker-friendly, single-process host for GeoLibre's collaboration
protocol. It uses the same @geolibre/collab-core policy as the hosted
Cloudflare Worker and persists session state in SQLite.
npm run build -w geolibre-collab-node
PORT=8787 COLLAB_DB_PATH=./data/collab.sqlite npm start -w geolibre-collab-node
Configuration:
PORT— HTTP/WebSocket port (default8787)HOST— listen address (default0.0.0.0)COLLAB_DB_PATH— SQLite file (default./data/collab.sqlite)COLLAB_MAX_SNAPSHOT_BYTES— maximum UTF-8 snapshot frame size (default1000000, matching the hosted Worker)COLLAB_IDLE_TTL_MS— time after the last participant disconnects before the session and its persisted data are deleted (default two hours)
Endpoints are POST /sessions, GET /sessions/:id/ws, and GET /health.
Persist the directory containing COLLAB_DB_PATH, and terminate TLS at the
ingress so browsers can connect with wss://.
Checking a deployment
scripts/smoke.mjs exercises the three endpoints against a running relay —
health, session creation, and a WebSocket join round-trip — and needs nothing
beyond Node:
node workers/collab-node/scripts/smoke.mjs http://127.0.0.1:8787
CI runs it against the freshly built image. The Dockerfile already imports the
staged bundle during docker build, so a missing ws or a broken
@geolibre/collab-core target fails there; this script covers the rest, which
only a running container shows: that the process starts and stays up, and that
it actually serves HTTP and completes a WebSocket upgrade.
Volume ownership
The container runs as the unprivileged node user, and the image creates
/data so a fresh named volume inherits that ownership. Docker only does this
for a volume it creates: a volume that already has content from an image that
ran as root keeps its root ownership, and the relay then exits at boot with
SQLITE_READONLY: attempt to write a readonly database. Repair it once with
docker run --rm -v geolibre_geolibre-collab:/data busybox chown -R 1000:1000 /data
The same applies to the projects server's volume, using its geolibre user.