@pyric/cli 0.1.0-alpha.11 → 0.1.0-alpha.13
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/dist/cli/serve.js +4 -4
- package/dist/cli/serve.js.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js +1 -1
- package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +2 -2
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/serve/bundler.d.ts +13 -8
- package/dist/serve/bundler.d.ts.map +1 -1
- package/dist/serve/bundler.js +31 -36
- package/dist/serve/bundler.js.map +1 -1
- package/dist/serve/docs-ui/docs/_rhythm/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +1 -1
- package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +1 -1
- package/dist/serve/docs-ui/docs/ai-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/api-reference/index.html +2 -2
- package/dist/serve/docs-ui/docs/api-reference.md +1 -1
- package/dist/serve/docs-ui/docs/app-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/auth-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/ai-logic/index.html +44 -22
- package/dist/serve/docs-ui/docs/build/ai-logic.md +69 -21
- package/dist/serve/docs-ui/docs/build/authentication/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +1 -1
- package/dist/serve/docs-ui/docs/build/realtime-database/index.html +1 -1
- package/dist/serve/docs-ui/docs/conformance-scores/index.html +1 -1
- package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/database-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/firestore-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +2 -1
- package/dist/serve/docs-ui/docs/get-started/how-the-swap-works.md +2 -0
- package/dist/serve/docs-ui/docs/get-started/start-building/index.html +3 -2
- package/dist/serve/docs-ui/docs/get-started/start-building.md +3 -1
- package/dist/serve/docs-ui/docs/index.json +349 -29
- package/dist/serve/docs-ui/docs/messaging-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +28 -0
- package/dist/serve/docs-ui/docs/observe/resolve-runtime-status.md +47 -0
- package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +1 -1
- package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +1 -1
- package/dist/serve/docs-ui/docs/overview/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api/index.html +916 -0
- package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api.md +706 -0
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ai-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api/index.html +168 -76
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +156 -73
- package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +11 -8
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api.md +17 -4
- package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-rules-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api/index.html +37 -14
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api.md +28 -8
- package/dist/serve/docs-ui/docs/pyric-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
- package/dist/serve/docs-ui/docs/rules-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +1 -1
- package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
- package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +1 -1
- package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +1 -1
- package/dist/serve/docs-ui/docs/storage-compat/index.html +1 -1
- package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
- package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
- package/dist/serve/docs-ui/docs/tutorial/index.html +429 -0
- package/dist/serve/docs-ui/docs/tutorial.md +701 -0
- package/dist/serve/docs-ui/llms.txt +3 -1
- package/dist/serve/entries/init.d.ts.map +1 -1
- package/dist/serve/entries/init.js +3 -0
- package/dist/serve/entries/init.js.map +1 -1
- package/dist/serve/entries/runtime.d.ts.map +1 -1
- package/dist/serve/entries/runtime.js +20 -5
- package/dist/serve/entries/runtime.js.map +1 -1
- package/dist/serve/entries/worker-runtime.d.ts +2 -2
- package/dist/serve/entries/worker-runtime.d.ts.map +1 -1
- package/dist/serve/entries/worker-runtime.js +45 -10
- package/dist/serve/entries/worker-runtime.js.map +1 -1
- package/dist/serve/runtime/chip-config.d.ts +19 -0
- package/dist/serve/runtime/chip-config.d.ts.map +1 -0
- package/dist/serve/runtime/chip-config.js +19 -0
- package/dist/serve/runtime/chip-config.js.map +1 -0
- package/dist/serve/runtime/chip-install.d.ts +10 -0
- package/dist/serve/runtime/chip-install.d.ts.map +1 -0
- package/dist/serve/runtime/chip-install.js +15 -0
- package/dist/serve/runtime/chip-install.js.map +1 -0
- package/dist/serve/runtime/chip.d.ts +17 -0
- package/dist/serve/runtime/chip.d.ts.map +1 -0
- package/dist/serve/runtime/chip.js +257 -0
- package/dist/serve/runtime/chip.js.map +1 -0
- package/dist/serve/runtime/manifest.d.ts +22 -0
- package/dist/serve/runtime/manifest.d.ts.map +1 -0
- package/dist/serve/runtime/manifest.js +20 -0
- package/dist/serve/runtime/manifest.js.map +1 -0
- package/dist/serve/runtime/status.d.ts +49 -0
- package/dist/serve/runtime/status.d.ts.map +1 -0
- package/dist/serve/runtime/status.js +164 -0
- package/dist/serve/runtime/status.js.map +1 -0
- package/dist/serve/runtime/worker-connection.d.ts +4 -0
- package/dist/serve/runtime/worker-connection.d.ts.map +1 -0
- package/dist/serve/runtime/worker-connection.js +11 -0
- package/dist/serve/runtime/worker-connection.js.map +1 -0
- package/dist/serve/runtime/worker-generation.d.ts +14 -0
- package/dist/serve/runtime/worker-generation.d.ts.map +1 -0
- package/dist/serve/runtime/worker-generation.js +56 -0
- package/dist/serve/runtime/worker-generation.js.map +1 -0
- package/dist/serve/runtime/worker-replacement.d.ts +18 -0
- package/dist/serve/runtime/worker-replacement.d.ts.map +1 -0
- package/dist/serve/runtime/worker-replacement.js +29 -0
- package/dist/serve/runtime/worker-replacement.js.map +1 -0
- package/dist/serve/standalone-assets.d.ts +2 -2
- package/dist/serve/standalone-assets.d.ts.map +1 -1
- package/dist/serve/standalone-assets.js +1 -1
- package/dist/serve/standalone-assets.js.map +1 -1
- package/dist/serve/studio-ui/assets/{RulesCodeEditor-CxVYcZXw.js → RulesCodeEditor-BDlH-5lp.js} +1 -1
- package/dist/serve/studio-ui/assets/{index-cpSfgQ7H.js → index-Bf9SSE8L.js} +5 -5
- package/dist/serve/studio-ui/assets/{seed-DeuFKi4J.js → seed-D_UjxfOU.js} +1 -1
- package/dist/serve/studio-ui/index.html +1 -1
- package/dist/serve/vite-ai-config.d.ts +25 -0
- package/dist/serve/vite-ai-config.d.ts.map +1 -0
- package/dist/serve/vite-ai-config.js +45 -0
- package/dist/serve/vite-ai-config.js.map +1 -0
- package/dist/serve/vite-plugin.d.ts +17 -36
- package/dist/serve/vite-plugin.d.ts.map +1 -1
- package/dist/serve/vite-plugin.js +38 -57
- package/dist/serve/vite-plugin.js.map +1 -1
- package/dist/serve/vite-rules-source.d.ts +8 -0
- package/dist/serve/vite-rules-source.d.ts.map +1 -0
- package/dist/serve/vite-rules-source.js +23 -0
- package/dist/serve/vite-rules-source.js.map +1 -0
- package/dist/serve/vite-worker-runtime.d.ts +20 -0
- package/dist/serve/vite-worker-runtime.d.ts.map +1 -0
- package/dist/serve/vite-worker-runtime.js +25 -0
- package/dist/serve/vite-worker-runtime.js.map +1 -0
- package/dist/serve/worker/client/connection.d.ts +7 -2
- package/dist/serve/worker/client/connection.d.ts.map +1 -1
- package/dist/serve/worker/client/connection.js +13 -16
- package/dist/serve/worker/client/connection.js.map +1 -1
- package/dist/serve/worker/client/core.d.ts +7 -0
- package/dist/serve/worker/client/core.d.ts.map +1 -1
- package/dist/serve/worker/client/core.js +28 -0
- package/dist/serve/worker/client/core.js.map +1 -1
- package/dist/serve/worker/client/runtime-control.d.ts +8 -0
- package/dist/serve/worker/client/runtime-control.d.ts.map +1 -0
- package/dist/serve/worker/client/runtime-control.js +11 -0
- package/dist/serve/worker/client/runtime-control.js.map +1 -0
- package/dist/serve/worker/entry.js +44 -2
- package/dist/serve/worker/entry.js.map +1 -1
- package/dist/serve/worker/host/core.js +1 -1
- package/dist/serve/worker/host/core.js.map +1 -1
- package/dist/serve/worker/host/firestore-writes.d.ts.map +1 -1
- package/dist/serve/worker/host/firestore-writes.js +3 -2
- package/dist/serve/worker/host/firestore-writes.js.map +1 -1
- package/dist/serve/worker/host/studio.js +1 -1
- package/dist/serve/worker/host/studio.js.map +1 -1
- package/dist/serve/worker/host-context.d.ts +1 -1
- package/dist/serve/worker/host-context.d.ts.map +1 -1
- package/dist/serve/worker/index.d.ts +2 -1
- package/dist/serve/worker/index.d.ts.map +1 -1
- package/dist/serve/worker/index.js +2 -1
- package/dist/serve/worker/index.js.map +1 -1
- package/dist/serve/worker/protocol.d.ts +15 -1
- package/dist/serve/worker/protocol.d.ts.map +1 -1
- package/dist/serve/worker/protocol.js +2 -2
- package/dist/serve/worker/protocol.js.map +1 -1
- package/dist/serve/worker/retirement.d.ts +21 -0
- package/dist/serve/worker/retirement.d.ts.map +1 -0
- package/dist/serve/worker/retirement.js +97 -0
- package/dist/serve/worker/retirement.js.map +1 -0
- package/dist/serve/worker/serve-init.d.ts.map +1 -1
- package/dist/serve/worker/serve-init.js +5 -6
- package/dist/serve/worker/serve-init.js.map +1 -1
- package/dist/vite.d.ts +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js.map +1 -1
- package/package.json +6 -4
- package/src/assurance/.generated/conformance-verdicts.ts +1090 -0
- package/src/assurance/attachment.ts +211 -0
- package/src/assurance/browser.ts +80 -0
- package/src/assurance/campaign.ts +496 -0
- package/src/assurance/capabilities.ts +446 -0
- package/src/assurance/cases.ts +43 -0
- package/src/assurance/index.ts +75 -0
- package/src/assurance/runner.ts +885 -0
- package/src/assurance/tool-names.ts +15 -0
- package/src/assurance/tools.ts +830 -0
- package/src/assurance/types.ts +352 -0
- package/src/assurance/validation.ts +434 -0
- package/src/bridge/client/bridge.ts +550 -0
- package/src/bridge/client/dispatch.ts +137 -0
- package/src/bridge/client.ts +45 -0
- package/src/bridge/protocol.ts +351 -0
- package/src/bridge/server/audit.ts +53 -0
- package/src/bridge/server/bridge.ts +597 -0
- package/src/bridge/server/headless.ts +160 -0
- package/src/bridge/server/json-schema-to-zod.ts +108 -0
- package/src/bridge/server/local-bridge.ts +66 -0
- package/src/bridge/server/logger.ts +50 -0
- package/src/bridge/server/mcp-contract.ts +93 -0
- package/src/bridge/server/mcp.ts +129 -0
- package/src/bridge/server/peer.ts +232 -0
- package/src/bridge/server/standalone.ts +347 -0
- package/src/bridge/server/tool-metadata.ts +99 -0
- package/src/bridge/server.ts +28 -0
- package/src/cli/can-i-use.ts +50 -0
- package/src/cli/cli.test.ts +493 -0
- package/src/cli/database-rules.ts +329 -0
- package/src/cli/dev-runner.ts +282 -0
- package/src/cli/firebase-json.ts +100 -0
- package/src/cli/firestore-indexes.ts +70 -0
- package/src/cli/index.ts +425 -0
- package/src/cli/init.ts +260 -0
- package/src/cli/mcp-proxy.ts +196 -0
- package/src/cli/parse-args.ts +80 -0
- package/src/cli/rules.ts +259 -0
- package/src/cli/scope.ts +67 -0
- package/src/cli/serve.ts +996 -0
- package/src/cli/service-commands.ts +73 -0
- package/src/cli/snapshot.ts +164 -0
- package/src/cli/storage-rules.ts +172 -0
- package/src/cli/verify.ts +416 -0
- package/src/conformance/.generated/can-i-use-browser.ts +113 -0
- package/src/conformance/.generated/can-i-use.ts +117 -0
- package/src/conformance/.generated/conformance-docs.ts +14 -0
- package/src/conformance/browser.ts +24 -0
- package/src/conformance/can-i-use-tool.ts +51 -0
- package/src/conformance/can-i-use.ts +18 -0
- package/src/conformance/docs.ts +8 -0
- package/src/conformance/index.ts +20 -0
- package/src/conformance/tools.ts +16 -0
- package/src/credentials/core/memoize-ttl.ts +142 -0
- package/src/credentials/core/types.ts +10 -0
- package/src/credentials/node/from-adc.ts +96 -0
- package/src/credentials/node/from-service-account.ts +133 -0
- package/src/credentials/node/index.ts +6 -0
- package/src/discover/concurrency.ts +127 -0
- package/src/discover/crawler-adapter.ts +142 -0
- package/src/discover/crawler.ts +1127 -0
- package/src/discover/credential-free.ts +27 -0
- package/src/discover/findCollectionGroup.ts +131 -0
- package/src/discover/firestore-source.ts +59 -0
- package/src/discover/index.ts +5 -0
- package/src/discover/merge.ts +523 -0
- package/src/discover/session.ts +402 -0
- package/src/discover/tools.ts +201 -0
- package/src/discover/types.ts +187 -0
- package/src/discover/wire.ts +324 -0
- package/src/functions-rtdb/child.ts +382 -0
- package/src/functions-rtdb/delivery.ts +7 -0
- package/src/functions-rtdb/discovery.ts +136 -0
- package/src/functions-rtdb/event.ts +64 -0
- package/src/functions-rtdb/execution.ts +111 -0
- package/src/functions-rtdb/in-memory-delivery.ts +40 -0
- package/src/functions-rtdb/project.ts +74 -0
- package/src/functions-rtdb/projection.ts +104 -0
- package/src/functions-rtdb/reference-pattern.ts +20 -0
- package/src/functions-rtdb/remote-delivery.ts +23 -0
- package/src/pkg-version.ts +49 -0
- package/src/register/esm-exports.ts +63 -0
- package/src/register/hooks.ts +30 -0
- package/src/register/index.ts +150 -0
- package/src/register/mapping.ts +33 -0
- package/src/remote/index.ts +1050 -0
- package/src/rtdb/crawl-snapshot.ts +118 -0
- package/src/rtdb/inspection.ts +137 -0
- package/src/rtdb/load-rules-document.ts +56 -0
- package/src/rtdb/rules-generation-tool.ts +38 -0
- package/src/rtdb/rules-json.ts +29 -0
- package/src/serve/activity-guard.ts +29 -0
- package/src/serve/activity-route.ts +164 -0
- package/src/serve/activity-warning.ts +26 -0
- package/src/serve/bridge-mount.ts +200 -0
- package/src/serve/bundler.ts +519 -0
- package/src/serve/capture-store.ts +65 -0
- package/src/serve/discovery.ts +199 -0
- package/src/serve/entries/ai.ts +292 -0
- package/src/serve/entries/app-backend.ts +4 -0
- package/src/serve/entries/app-client.ts +26 -0
- package/src/serve/entries/app-session-store.ts +47 -0
- package/src/serve/entries/app.ts +11 -0
- package/src/serve/entries/auth-helper-core.ts +181 -0
- package/src/serve/entries/auth-helper-dom.ts +134 -0
- package/src/serve/entries/auth-helper-runtime.ts +20 -0
- package/src/serve/entries/auth.ts +255 -0
- package/src/serve/entries/bridge-url.ts +31 -0
- package/src/serve/entries/database.ts +129 -0
- package/src/serve/entries/firestore.ts +232 -0
- package/src/serve/entries/init.ts +49 -0
- package/src/serve/entries/keepalive.ts +46 -0
- package/src/serve/entries/messaging-sw.ts +75 -0
- package/src/serve/entries/messaging.ts +96 -0
- package/src/serve/entries/runtime.ts +556 -0
- package/src/serve/entries/session-store.ts +97 -0
- package/src/serve/entries/storage.ts +92 -0
- package/src/serve/entries/tab-sync-wiring.ts +274 -0
- package/src/serve/entries/worker-runtime.ts +135 -0
- package/src/serve/init-payload.ts +42 -0
- package/src/serve/namespace.ts +675 -0
- package/src/serve/open-browser.ts +68 -0
- package/src/serve/rules.ts +272 -0
- package/src/serve/runtime/chip-config.ts +30 -0
- package/src/serve/runtime/chip-install.ts +27 -0
- package/src/serve/runtime/chip.ts +282 -0
- package/src/serve/runtime/manifest.ts +37 -0
- package/src/serve/runtime/status.ts +216 -0
- package/src/serve/runtime/worker-connection.ts +14 -0
- package/src/serve/runtime/worker-generation.ts +75 -0
- package/src/serve/runtime/worker-replacement.ts +42 -0
- package/src/serve/sandbox-marker.ts +31 -0
- package/src/serve/server.ts +428 -0
- package/src/serve/standalone-assets.ts +180 -0
- package/src/serve/state-store.ts +166 -0
- package/src/serve/studio/disk-project-store.ts +185 -0
- package/src/serve/studio/disk-workspace.ts +162 -0
- package/src/serve/studio/index.ts +20 -0
- package/src/serve/studio/routes.ts +237 -0
- package/src/serve/studio/store-types.ts +48 -0
- package/src/serve/studio/studio-storage.test.ts +289 -0
- package/src/serve/vite-ai-config.ts +77 -0
- package/src/serve/vite-plugin.ts +1075 -0
- package/src/serve/vite-rules-source.ts +28 -0
- package/src/serve/vite-worker-runtime.ts +51 -0
- package/src/serve/worker/activity-bootstrap.ts +24 -0
- package/src/serve/worker/client/admin-firestore.ts +38 -0
- package/src/serve/worker/client/ai.ts +124 -0
- package/src/serve/worker/client/auth.ts +489 -0
- package/src/serve/worker/client/connection.ts +227 -0
- package/src/serve/worker/client/core.ts +384 -0
- package/src/serve/worker/client/disconnect.ts +45 -0
- package/src/serve/worker/client/firestore-reads.ts +181 -0
- package/src/serve/worker/client/firestore-refs.ts +226 -0
- package/src/serve/worker/client/firestore-writes.ts +232 -0
- package/src/serve/worker/client/handles.ts +91 -0
- package/src/serve/worker/client/messaging.ts +119 -0
- package/src/serve/worker/client/presence.ts +174 -0
- package/src/serve/worker/client/rtdb.ts +311 -0
- package/src/serve/worker/client/rules.ts +63 -0
- package/src/serve/worker/client/runtime-control.ts +22 -0
- package/src/serve/worker/client/service-worker-connection.ts +59 -0
- package/src/serve/worker/client/snapshots.ts +86 -0
- package/src/serve/worker/client/storage.ts +195 -0
- package/src/serve/worker/client/studio.ts +88 -0
- package/src/serve/worker/client.ts +57 -0
- package/src/serve/worker/durable-persistence.ts +137 -0
- package/src/serve/worker/entry.ts +223 -0
- package/src/serve/worker/host/admin-firestore.ts +88 -0
- package/src/serve/worker/host/connection.ts +179 -0
- package/src/serve/worker/host/core.ts +387 -0
- package/src/serve/worker/host/dispatch.ts +316 -0
- package/src/serve/worker/host/firestore-reads.ts +117 -0
- package/src/serve/worker/host/firestore-writes.ts +456 -0
- package/src/serve/worker/host/presence.ts +312 -0
- package/src/serve/worker/host/rtdb.ts +136 -0
- package/src/serve/worker/host/rules.ts +128 -0
- package/src/serve/worker/host/storage.ts +312 -0
- package/src/serve/worker/host/studio.ts +75 -0
- package/src/serve/worker/host/subscriptions.ts +238 -0
- package/src/serve/worker/host-ai.ts +165 -0
- package/src/serve/worker/host-auth.ts +469 -0
- package/src/serve/worker/host-context.ts +273 -0
- package/src/serve/worker/host-events.ts +94 -0
- package/src/serve/worker/host-messaging.ts +240 -0
- package/src/serve/worker/host.ts +47 -0
- package/src/serve/worker/index.ts +196 -0
- package/src/serve/worker/presence-timing.ts +15 -0
- package/src/serve/worker/protocol.ts +1124 -0
- package/src/serve/worker/retirement.ts +125 -0
- package/src/serve/worker/serve-init.ts +605 -0
- package/src/serve/worker/service-worker-channel.ts +33 -0
- package/src/serve/worker/service-worker-relay.ts +86 -0
- package/src/serve/writer-lock.ts +53 -0
- package/src/verify/cases.ts +233 -0
- package/src/verify/fixture.ts +258 -0
- package/src/verify/index.ts +519 -0
- package/src/verify/tools.ts +108 -0
- package/src/version/compat-target.ts +17 -0
- package/src/vite.ts +18 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api/index.html +0 -31
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +0 -29
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SharedWorker host — shared resolution layer (host/core.ts).
|
|
3
|
+
*
|
|
4
|
+
* The helpers every firestore-touching family module leans on:
|
|
5
|
+
* - the auth-lens → live-handle resolvers (`lensDb`/`lensRtdb`/`sessionDb`/…),
|
|
6
|
+
* the single place a per-op `actAs` lens or a port session becomes a live
|
|
7
|
+
* Firestore/RTDB handle;
|
|
8
|
+
* - descriptor → live ref/query resolution (`resolveTarget`/`resolveConstraint`),
|
|
9
|
+
* used by both the read ops and the subscription handlers;
|
|
10
|
+
* - cross-port snapshot serialization (`serializeDocSnap`);
|
|
11
|
+
* - `opProvenance`, the issue-time provenance both the ambient-provenance
|
|
12
|
+
* window (dispatch) and the storage ops (explicit thread) read.
|
|
13
|
+
*
|
|
14
|
+
* Genuinely-shared STATE lives on `HostCtx` (host-context.ts) — the dependency
|
|
15
|
+
* root. This module adds the shared FUNCTIONS that resolve against that state;
|
|
16
|
+
* it imports the pyric firestore/database engine, so it is deliberately kept
|
|
17
|
+
* out of host-context.ts (which stays engine-free).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
getFirestore as pyricGetFirestore,
|
|
22
|
+
getAdminFirestore as pyricGetAdminFirestore,
|
|
23
|
+
doc as pyricDoc,
|
|
24
|
+
collection as pyricCollection,
|
|
25
|
+
collectionGroup as pyricCollectionGroup,
|
|
26
|
+
query as pyricQuery,
|
|
27
|
+
where as pyricWhere,
|
|
28
|
+
and as pyricAnd,
|
|
29
|
+
or as pyricOr,
|
|
30
|
+
orderBy as pyricOrderBy,
|
|
31
|
+
limit as pyricLimit,
|
|
32
|
+
limitToLast as pyricLimitToLast,
|
|
33
|
+
startAt as pyricStartAt,
|
|
34
|
+
startAfter as pyricStartAfter,
|
|
35
|
+
endAt as pyricEndAt,
|
|
36
|
+
endBefore as pyricEndBefore,
|
|
37
|
+
type Firestore,
|
|
38
|
+
type DocumentReference,
|
|
39
|
+
type CollectionReference,
|
|
40
|
+
type Query,
|
|
41
|
+
} from 'pyric/firestore';
|
|
42
|
+
import { rehydrateDocValue } from 'pyric/firestore/internal/value-codec';
|
|
43
|
+
import {
|
|
44
|
+
getDatabase as pyricGetDatabase,
|
|
45
|
+
getAdminDatabase as pyricGetAdminDatabase,
|
|
46
|
+
type Database,
|
|
47
|
+
} from 'pyric/database';
|
|
48
|
+
import type { AuthLens, EventProvenance } from 'pyric/sandbox';
|
|
49
|
+
import type { MintedSession } from 'pyric/auth';
|
|
50
|
+
|
|
51
|
+
import type {
|
|
52
|
+
InboundMessage,
|
|
53
|
+
TargetDescriptor,
|
|
54
|
+
QueryConstraintDescriptor,
|
|
55
|
+
} from '../protocol.js';
|
|
56
|
+
import { serializeDocData } from '../protocol.js';
|
|
57
|
+
import { type HostCtx, type PortLike } from '../host-context.js';
|
|
58
|
+
import { portSession } from '../host-auth.js';
|
|
59
|
+
|
|
60
|
+
// ─── Descriptor → live ref resolution ───────────────────────────────────
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Resolve a TargetDescriptor into a live pyric ref or query.
|
|
64
|
+
*
|
|
65
|
+
* WHY WE RESOLVE ON THE WORKER
|
|
66
|
+
* The client never holds live pyric refs — it holds plain `DocRef`/
|
|
67
|
+
* `CollRef`/`GroupRef`/`QueryDescriptor` objects that serialize cleanly
|
|
68
|
+
* across the MessagePort. On every op the worker rebuilds the live ref
|
|
69
|
+
* from these descriptors. This keeps the client completely stateless with
|
|
70
|
+
* respect to sandbox internals and makes retries trivially correct.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveTarget(
|
|
73
|
+
db: Firestore,
|
|
74
|
+
target: TargetDescriptor,
|
|
75
|
+
): DocumentReference | CollectionReference | Query {
|
|
76
|
+
if (target.__ref === 'doc') {
|
|
77
|
+
return pyricDoc(db, target.path);
|
|
78
|
+
}
|
|
79
|
+
if (target.__ref === 'collection') {
|
|
80
|
+
return pyricCollection(db, target.path);
|
|
81
|
+
}
|
|
82
|
+
if (target.__ref === 'group') {
|
|
83
|
+
return pyricCollectionGroup(db, target.collectionId);
|
|
84
|
+
}
|
|
85
|
+
// query descriptor
|
|
86
|
+
const source = resolveTarget(db, target.source) as CollectionReference | Query;
|
|
87
|
+
const constraints = target.constraints.map((c) => resolveConstraint(c));
|
|
88
|
+
return pyricQuery(source, ...constraints);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function resolveConstraint(c: QueryConstraintDescriptor): ReturnType<typeof pyricWhere> {
|
|
92
|
+
switch (c.kind) {
|
|
93
|
+
case 'where':
|
|
94
|
+
// Rehydrate the comparison value (same rationale as prepareWriteData,
|
|
95
|
+
// spike gap 4, applied to READ inputs): over the JSON relay legs a
|
|
96
|
+
// Node-side Timestamp/Bytes/GeoPoint arrives as its marker shape;
|
|
97
|
+
// without rehydration the comparison would see a plain map and the
|
|
98
|
+
// filter would silently mismatch typed stored values.
|
|
99
|
+
return pyricWhere(c.field, c.op as Parameters<typeof pyricWhere>[1], rehydrateDocValue(c.value));
|
|
100
|
+
// Composite filters rebuild through the modular `and`/`or` factories,
|
|
101
|
+
// which validate operands: an empty composite or a nested non-filter
|
|
102
|
+
// throws the same TypeError the in-page SDK raises (surfaces as an
|
|
103
|
+
// error res / snap-error, never a crash).
|
|
104
|
+
case 'and':
|
|
105
|
+
return pyricAnd(...c.filters.map(resolveConstraint));
|
|
106
|
+
case 'or':
|
|
107
|
+
return pyricOr(...c.filters.map(resolveConstraint));
|
|
108
|
+
case 'orderBy':
|
|
109
|
+
return pyricOrderBy(c.field, c.direction);
|
|
110
|
+
case 'limit':
|
|
111
|
+
return pyricLimit(c.n);
|
|
112
|
+
case 'limitToLast':
|
|
113
|
+
return pyricLimitToLast(c.n);
|
|
114
|
+
// Cursor values rehydrate for the same reason as `where` values —
|
|
115
|
+
// `startAfter(<timestamp>)` must position against real Timestamps.
|
|
116
|
+
case 'startAt':
|
|
117
|
+
return pyricStartAt(...c.values.map(rehydrateDocValue));
|
|
118
|
+
case 'startAfter':
|
|
119
|
+
return pyricStartAfter(...c.values.map(rehydrateDocValue));
|
|
120
|
+
case 'endAt':
|
|
121
|
+
return pyricEndAt(...c.values.map(rehydrateDocValue));
|
|
122
|
+
case 'endBefore':
|
|
123
|
+
return pyricEndBefore(...c.values.map(rehydrateDocValue));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ─── Snapshot serialization ───────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Serialize a document snapshot to cross-port form.
|
|
131
|
+
* Uses JSON-via-serializeDocData so Timestamp/Bytes/LatLng survive.
|
|
132
|
+
*/
|
|
133
|
+
export function serializeDocSnap(snap: {
|
|
134
|
+
id: string;
|
|
135
|
+
path?: string;
|
|
136
|
+
ref?: { path?: string };
|
|
137
|
+
exists: boolean | (() => boolean);
|
|
138
|
+
data(): Record<string, unknown> | undefined;
|
|
139
|
+
}): { id: string; path?: string; exists: boolean; data?: { json: string } } {
|
|
140
|
+
const existsBool = typeof snap.exists === 'function' ? snap.exists() : snap.exists;
|
|
141
|
+
const data = existsBool ? snap.data() : undefined;
|
|
142
|
+
return {
|
|
143
|
+
id: snap.id,
|
|
144
|
+
// Doc snapshots carry a top-level `path`; QUERY doc snapshots carry it on
|
|
145
|
+
// `.ref.path`. Read both so query rows serialize their FULL path (Studio's
|
|
146
|
+
// browse resolves the document detail from it).
|
|
147
|
+
path: snap.path ?? snap.ref?.path,
|
|
148
|
+
exists: existsBool,
|
|
149
|
+
data: data ? serializeDocData(data) : undefined,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ─── Auth lens (Pyric Studio) ─────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Resolve the Firestore handle an op runs against, given its `actAs` lens
|
|
157
|
+
* (Pyric Studio auth lens, T2 — implements the C2 protocol seam).
|
|
158
|
+
*
|
|
159
|
+
* Resolution by `actAs.mode` (absent ⇒ the app's session):
|
|
160
|
+
*
|
|
161
|
+
* - `app-session` (and `actAs` absent): `ctx.db` — the shared sandbox-live
|
|
162
|
+
* handle. Reads `sandbox.currentUser` per op, so rules evaluate under
|
|
163
|
+
* whoever the served app is signed in as. This is the unchanged default
|
|
164
|
+
* and the ONLY lens the app itself ever uses.
|
|
165
|
+
*
|
|
166
|
+
* - `{ mode: 'as', uid }` (impersonation — the rules-debugging primitive):
|
|
167
|
+
* a FROZEN-identity `getFirestore(sandbox.withAuth({ uid }))` handle.
|
|
168
|
+
* Security rules APPLY and evaluate as that user — `request.auth.uid`
|
|
169
|
+
* resolves to `uid`. This lets Studio "re-run this denied op as the user
|
|
170
|
+
* who attempted it" (Wave-2 rules-debugging, F4). Handles are cached
|
|
171
|
+
* per-uid on `ctx.lensHandles`.
|
|
172
|
+
*
|
|
173
|
+
* - `{ mode: 'admin' }` (rule bypass): a modular `getAdminFirestore(sandbox)`
|
|
174
|
+
* handle (pyric Gap #2) whose ops skip security-rule evaluation while still
|
|
175
|
+
* reading/writing the same store and emitting events. This is Studio's
|
|
176
|
+
* "edit anything as admin" surface (F2). Cached on `ctx.adminDb`.
|
|
177
|
+
*
|
|
178
|
+
* - `{ mode: 'anon' }` (explicitly unauthenticated): a frozen
|
|
179
|
+
* `getFirestore(sandbox.withAuth(null))` handle — rules apply with
|
|
180
|
+
* `request.auth == null`. The remote arm's `withAuth(null)`; distinct from
|
|
181
|
+
* an ABSENT lens, which resolves to the port's session. Cached on
|
|
182
|
+
* `ctx.anonDb`.
|
|
183
|
+
*
|
|
184
|
+
* WRITE-IMPERSONATION GATING (open micro-decision #1, honoured): the resolver
|
|
185
|
+
* itself is symmetric — an `{ mode: 'as', uid }` lens applies to BOTH reads and
|
|
186
|
+
* writes (a write-as-user is denied/allowed exactly as that user's rules say).
|
|
187
|
+
* The POLICY decision — "read-as-user always; write-as-user only on an explicit
|
|
188
|
+
* reproduce path" — is enforced at the CALLER (the Studio client / UI chooses
|
|
189
|
+
* when to attach a write op's `actAs`), NOT here. Default behaviour stays admin/
|
|
190
|
+
* app-session unless a caller sets `actAs`; no UI is added by T2.
|
|
191
|
+
*/
|
|
192
|
+
export function lensDb(ctx: HostCtx, actAs?: AuthLens): Firestore {
|
|
193
|
+
// Absent / app-session → the app's live session handle.
|
|
194
|
+
if (!actAs || actAs.mode === 'app-session') {
|
|
195
|
+
return ctx.db;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// { mode: 'admin' } → a modular rules-bypass handle (cached per ctx).
|
|
199
|
+
if (actAs.mode === 'admin') {
|
|
200
|
+
return (ctx.adminDb ??= pyricGetAdminFirestore(ctx.sandbox));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// { mode: 'anon' } → a genuinely UNAUTHENTICATED handle
|
|
204
|
+
// (`withAuth(null)` — `request.auth == null` in rules). NOT the same as an
|
|
205
|
+
// absent lens, which resolves to the PORT'S SESSION: a relayed op that
|
|
206
|
+
// means "no auth" must pin this lens or it silently runs as whoever the
|
|
207
|
+
// browser tab is signed in as.
|
|
208
|
+
if (actAs.mode === 'anon') {
|
|
209
|
+
return (ctx.anonDb ??= pyricGetFirestore(ctx.sandbox.withAuth(null)));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// { mode: 'as', uid } → a frozen-identity handle; rules evaluate as `uid`.
|
|
213
|
+
const handles = (ctx.lensHandles ??= new Map());
|
|
214
|
+
const key = lensCacheKey(actAs);
|
|
215
|
+
let handle = handles.get(key);
|
|
216
|
+
if (!handle) {
|
|
217
|
+
handle = pyricGetFirestore(ctx.sandbox.withAuth(authStateForLens(actAs)));
|
|
218
|
+
handles.set(key, handle);
|
|
219
|
+
}
|
|
220
|
+
return handle;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function authStateForLens(actAs: Extract<AuthLens, { mode: 'as' }>): { uid: string; token?: Record<string, unknown> } {
|
|
224
|
+
return actAs.token === undefined
|
|
225
|
+
? { uid: actAs.uid }
|
|
226
|
+
: { uid: actAs.uid, token: actAs.token };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function lensCacheKey(actAs: Extract<AuthLens, { mode: 'as' }>): string {
|
|
230
|
+
return actAs.token === undefined
|
|
231
|
+
? actAs.uid
|
|
232
|
+
: `${actAs.uid}:${JSON.stringify(actAs.token)}`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Cache key for a real port session; claims are part of authorization identity. */
|
|
236
|
+
export function sessionCacheKey(session: MintedSession): string {
|
|
237
|
+
return session.state.token === undefined
|
|
238
|
+
? session.user.uid
|
|
239
|
+
: `${session.user.uid}:${JSON.stringify(session.state.token)}`;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Normalise a per-op `actAs` lens to the {@link AuthLens} provenance shape that
|
|
244
|
+
* the unified sandbox event stream stamps on each event's `authLens` field.
|
|
245
|
+
*
|
|
246
|
+
* Absent ⇒ `{ mode: 'app-session' }` (the app's own session) — matching how
|
|
247
|
+
* `EventProvenance.authLens` reads when omitted. C1 added the field to events;
|
|
248
|
+
* T1 owns the EMIT path that actually writes it. T2's job is to thread the lens
|
|
249
|
+
* THROUGH the host so T1 has the value at emit time: see the call in `handleOp`
|
|
250
|
+
* where the resolved lens is passed to the sandbox via `withLens` when that
|
|
251
|
+
* emit seam exists. Today the sandbox event emitters infer `authLens` from the
|
|
252
|
+
* acting identity (the impersonation handle's frozen `auth` is `{ uid }`, so a
|
|
253
|
+
* rules eval already carries that uid); this helper exists so the host has a
|
|
254
|
+
* single canonical normaliser when the explicit emit-time stamp lands.
|
|
255
|
+
*/
|
|
256
|
+
export function lensProvenance(actAs?: AuthLens): AuthLens {
|
|
257
|
+
return actAs ?? { mode: 'app-session' };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Resolve the data handle for an op/sub carrying NO explicit lens: the
|
|
262
|
+
* PORT'S SESSION (#754). A signed-in port gets a per-session-token cached
|
|
263
|
+
* `getFirestore(sandbox.withAuth(session.state))` handle — rules evaluate
|
|
264
|
+
* under its uid + custom claims, exactly like a globally signed-in user. A
|
|
265
|
+
* signed-out port falls back to `ctx.db` (sandbox-live; `currentUser` is
|
|
266
|
+
* never set in served mode, so that is the unauthenticated view).
|
|
267
|
+
*
|
|
268
|
+
* This is NOT the impersonation lens: the session was minted by validated
|
|
269
|
+
* sign-in on this port (`sandbox.mintSession`), so both reads and writes
|
|
270
|
+
* legitimately run as that user — the write-impersonation gate on the
|
|
271
|
+
* Studio `as` lens does not apply to a port's own session.
|
|
272
|
+
*
|
|
273
|
+
* Claim changes become visible when the client forces an ID-token refresh;
|
|
274
|
+
* host-auth updates the port session, clears all session-bound service
|
|
275
|
+
* caches, and re-establishes that port's listeners under the new token.
|
|
276
|
+
*/
|
|
277
|
+
export function sessionDb(ctx: HostCtx, port: PortLike): Firestore {
|
|
278
|
+
const session = portSession(ctx, port);
|
|
279
|
+
if (!session) return ctx.db;
|
|
280
|
+
const cache = (ctx.sessionDbs ??= new Map());
|
|
281
|
+
const key = sessionCacheKey(session);
|
|
282
|
+
let handle = cache.get(key);
|
|
283
|
+
if (!handle) {
|
|
284
|
+
handle = pyricGetFirestore(ctx.sandbox.withAuth(session.state));
|
|
285
|
+
cache.set(key, handle);
|
|
286
|
+
}
|
|
287
|
+
return handle;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function sessionRtdb(ctx: HostCtx, port: PortLike): Database {
|
|
291
|
+
const session = portSession(ctx, port);
|
|
292
|
+
if (!session) return ensureRtdb(ctx);
|
|
293
|
+
const cache = (ctx.sessionRtdbs ??= new Map());
|
|
294
|
+
const key = sessionCacheKey(session);
|
|
295
|
+
let handle = cache.get(key);
|
|
296
|
+
if (!handle) {
|
|
297
|
+
handle = pyricGetDatabase(ctx.sandbox.withAuth(session.state));
|
|
298
|
+
cache.set(key, handle);
|
|
299
|
+
}
|
|
300
|
+
return handle;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function lensRtdb(ctx: HostCtx, actAs: AuthLens | undefined, port: PortLike): Database {
|
|
304
|
+
if (!actAs || actAs.mode === 'app-session') {
|
|
305
|
+
return sessionRtdb(ctx, port);
|
|
306
|
+
}
|
|
307
|
+
if (actAs.mode === 'admin') {
|
|
308
|
+
return (ctx.adminRtdb ??= pyricGetAdminDatabase(ctx.sandbox));
|
|
309
|
+
}
|
|
310
|
+
// Genuinely unauthenticated — see the `anon` note on lensDb.
|
|
311
|
+
if (actAs.mode === 'anon') {
|
|
312
|
+
return (ctx.anonRtdb ??= pyricGetDatabase(ctx.sandbox.withAuth(null)));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const handles = (ctx.lensRtdbs ??= new Map());
|
|
316
|
+
const key = lensCacheKey(actAs);
|
|
317
|
+
let handle = handles.get(key);
|
|
318
|
+
if (!handle) {
|
|
319
|
+
handle = pyricGetDatabase(ctx.sandbox.withAuth(authStateForLens(actAs)));
|
|
320
|
+
handles.set(key, handle);
|
|
321
|
+
}
|
|
322
|
+
return handle;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function ensureRtdb(ctx: HostCtx): Database {
|
|
326
|
+
return (ctx.rtdb ??= pyricGetDatabase(ctx.sandbox));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ─── Op provenance ─────────────────────────────────────────────────────────
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Op provenance from an inbound message, bound at ISSUE time. This is the
|
|
333
|
+
* source of truth for both the synchronous ambient window used by immediate
|
|
334
|
+
* emitters and the operation-scoped Storage handle used across awaits.
|
|
335
|
+
*
|
|
336
|
+
* - `actor`: a client that DECLARED itself the issuer (`issuer: 'studio'`,
|
|
337
|
+
* stamped by Studio's worker client — `setOpIssuer` in client.ts) gets
|
|
338
|
+
* `actor: { kind: 'studio' }`. Bridge-relayed frames are forwarded
|
|
339
|
+
* with the stamp cleared (client.ts `relayWorkerOp`), so remote traffic
|
|
340
|
+
* carries `relaySource: 'remote'` and remains unattributed rather than
|
|
341
|
+
* being silently promoted to either Studio or page app traffic.
|
|
342
|
+
* - `authLens`: the op's EFFECTIVE lens (`msg.actAs`) whenever present —
|
|
343
|
+
* independent of issuer, because admin is admin regardless of who asked
|
|
344
|
+
* (an agent tool relay's admin op must classify as a rules BYPASS in
|
|
345
|
+
* Traffic, not a rules allow).
|
|
346
|
+
*
|
|
347
|
+
* Plain served-app operations get provenance from their service handles.
|
|
348
|
+
* Firestore subscription registration is the exception: listener lifecycle
|
|
349
|
+
* envelopes originate below that handle, so a normal worker subscription is
|
|
350
|
+
* stamped here as app/app-session. Its later unattributed detach can then be
|
|
351
|
+
* correlated to the accepted registration by the activity monitor.
|
|
352
|
+
*/
|
|
353
|
+
export function opProvenance(
|
|
354
|
+
msg: InboundMessage,
|
|
355
|
+
activityJourneyId?: string,
|
|
356
|
+
): EventProvenance | undefined {
|
|
357
|
+
const issuer = (msg as { issuer?: 'studio' }).issuer;
|
|
358
|
+
const relaySource = (msg as { relaySource?: 'remote' }).relaySource;
|
|
359
|
+
const actAs = (msg as { actAs?: AuthLens }).actAs;
|
|
360
|
+
const target = msg.t === 'sub' ? msg.target : undefined;
|
|
361
|
+
const isAppFirestoreSubscription = issuer !== 'studio'
|
|
362
|
+
&& relaySource !== 'remote'
|
|
363
|
+
&& target !== null
|
|
364
|
+
&& typeof target === 'object'
|
|
365
|
+
&& '__ref' in target;
|
|
366
|
+
if (
|
|
367
|
+
issuer !== 'studio'
|
|
368
|
+
&& relaySource !== 'remote'
|
|
369
|
+
&& !actAs
|
|
370
|
+
&& !isAppFirestoreSubscription
|
|
371
|
+
&& activityJourneyId === undefined
|
|
372
|
+
) return undefined;
|
|
373
|
+
return {
|
|
374
|
+
actor: relaySource === 'remote'
|
|
375
|
+
? { kind: 'unattributed' }
|
|
376
|
+
: issuer === 'studio'
|
|
377
|
+
? { kind: 'studio' }
|
|
378
|
+
: { kind: 'app', ...(activityJourneyId ? { journeyId: activityJourneyId } : {}) },
|
|
379
|
+
authLens: actAs ?? { mode: 'app-session' },
|
|
380
|
+
...(isAppFirestoreSubscription
|
|
381
|
+
? { activity: { listenerId: (msg as { subId: string }).subId } }
|
|
382
|
+
: {}),
|
|
383
|
+
...(msg.t === 'op' && msg.method === 'getDoc' && msg.activity?.groupKind
|
|
384
|
+
? { activity: { groupKind: msg.activity.groupKind } }
|
|
385
|
+
: {}),
|
|
386
|
+
};
|
|
387
|
+
}
|