@pyric/cli 0.1.0-alpha.9
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/LICENSE +216 -0
- package/README.md +156 -0
- package/README.md.orig +138 -0
- package/dist/assurance/attachment.d.ts +24 -0
- package/dist/assurance/attachment.d.ts.map +1 -0
- package/dist/assurance/attachment.js +138 -0
- package/dist/assurance/attachment.js.map +1 -0
- package/dist/assurance/browser.d.ts +7 -0
- package/dist/assurance/browser.d.ts.map +1 -0
- package/dist/assurance/browser.js +68 -0
- package/dist/assurance/browser.js.map +1 -0
- package/dist/assurance/campaign.d.ts +41 -0
- package/dist/assurance/campaign.d.ts.map +1 -0
- package/dist/assurance/campaign.js +364 -0
- package/dist/assurance/campaign.js.map +1 -0
- package/dist/assurance/capabilities.d.ts +7 -0
- package/dist/assurance/capabilities.d.ts.map +1 -0
- package/dist/assurance/capabilities.js +295 -0
- package/dist/assurance/capabilities.js.map +1 -0
- package/dist/assurance/cases.d.ts +14 -0
- package/dist/assurance/cases.d.ts.map +1 -0
- package/dist/assurance/cases.js +27 -0
- package/dist/assurance/cases.js.map +1 -0
- package/dist/assurance/generated-capabilities.d.ts +52 -0
- package/dist/assurance/generated-capabilities.d.ts.map +1 -0
- package/dist/assurance/generated-capabilities.js +329 -0
- package/dist/assurance/generated-capabilities.js.map +1 -0
- package/dist/assurance/index.d.ts +11 -0
- package/dist/assurance/index.d.ts.map +1 -0
- package/dist/assurance/index.js +9 -0
- package/dist/assurance/index.js.map +1 -0
- package/dist/assurance/runner.d.ts +3 -0
- package/dist/assurance/runner.d.ts.map +1 -0
- package/dist/assurance/runner.js +633 -0
- package/dist/assurance/runner.js.map +1 -0
- package/dist/assurance/tool-names.d.ts +4 -0
- package/dist/assurance/tool-names.d.ts.map +1 -0
- package/dist/assurance/tool-names.js +14 -0
- package/dist/assurance/tool-names.js.map +1 -0
- package/dist/assurance/tools.d.ts +19 -0
- package/dist/assurance/tools.d.ts.map +1 -0
- package/dist/assurance/tools.js +740 -0
- package/dist/assurance/tools.js.map +1 -0
- package/dist/assurance/types.d.ts +348 -0
- package/dist/assurance/types.d.ts.map +1 -0
- package/dist/assurance/types.js +7 -0
- package/dist/assurance/types.js.map +1 -0
- package/dist/assurance/validation.d.ts +8 -0
- package/dist/assurance/validation.d.ts.map +1 -0
- package/dist/assurance/validation.js +269 -0
- package/dist/assurance/validation.js.map +1 -0
- package/dist/bridge/client/bridge.d.ts +133 -0
- package/dist/bridge/client/bridge.d.ts.map +1 -0
- package/dist/bridge/client/bridge.js +429 -0
- package/dist/bridge/client/bridge.js.map +1 -0
- package/dist/bridge/client/dispatch.d.ts +41 -0
- package/dist/bridge/client/dispatch.d.ts.map +1 -0
- package/dist/bridge/client/dispatch.js +111 -0
- package/dist/bridge/client/dispatch.js.map +1 -0
- package/dist/bridge/client.d.ts +24 -0
- package/dist/bridge/client.d.ts.map +1 -0
- package/dist/bridge/client.js +26 -0
- package/dist/bridge/client.js.map +1 -0
- package/dist/bridge/protocol.d.ts +227 -0
- package/dist/bridge/protocol.d.ts.map +1 -0
- package/dist/bridge/protocol.js +131 -0
- package/dist/bridge/protocol.js.map +1 -0
- package/dist/bridge/server/audit.d.ts +19 -0
- package/dist/bridge/server/audit.d.ts.map +1 -0
- package/dist/bridge/server/audit.js +46 -0
- package/dist/bridge/server/audit.js.map +1 -0
- package/dist/bridge/server/bridge.d.ts +126 -0
- package/dist/bridge/server/bridge.d.ts.map +1 -0
- package/dist/bridge/server/bridge.js +383 -0
- package/dist/bridge/server/bridge.js.map +1 -0
- package/dist/bridge/server/headless.d.ts +36 -0
- package/dist/bridge/server/headless.d.ts.map +1 -0
- package/dist/bridge/server/headless.js +142 -0
- package/dist/bridge/server/headless.js.map +1 -0
- package/dist/bridge/server/json-schema-to-zod.d.ts +37 -0
- package/dist/bridge/server/json-schema-to-zod.d.ts.map +1 -0
- package/dist/bridge/server/json-schema-to-zod.js +93 -0
- package/dist/bridge/server/json-schema-to-zod.js.map +1 -0
- package/dist/bridge/server/local-bridge.d.ts +33 -0
- package/dist/bridge/server/local-bridge.d.ts.map +1 -0
- package/dist/bridge/server/local-bridge.js +41 -0
- package/dist/bridge/server/local-bridge.js.map +1 -0
- package/dist/bridge/server/logger.d.ts +28 -0
- package/dist/bridge/server/logger.d.ts.map +1 -0
- package/dist/bridge/server/logger.js +42 -0
- package/dist/bridge/server/logger.js.map +1 -0
- package/dist/bridge/server/mcp-contract.d.ts +21 -0
- package/dist/bridge/server/mcp-contract.d.ts.map +1 -0
- package/dist/bridge/server/mcp-contract.js +62 -0
- package/dist/bridge/server/mcp-contract.js.map +1 -0
- package/dist/bridge/server/mcp.d.ts +26 -0
- package/dist/bridge/server/mcp.d.ts.map +1 -0
- package/dist/bridge/server/mcp.js +102 -0
- package/dist/bridge/server/mcp.js.map +1 -0
- package/dist/bridge/server/peer.d.ts +39 -0
- package/dist/bridge/server/peer.d.ts.map +1 -0
- package/dist/bridge/server/peer.js +189 -0
- package/dist/bridge/server/peer.js.map +1 -0
- package/dist/bridge/server/standalone.d.ts +49 -0
- package/dist/bridge/server/standalone.d.ts.map +1 -0
- package/dist/bridge/server/standalone.js +267 -0
- package/dist/bridge/server/standalone.js.map +1 -0
- package/dist/bridge/server/tool-metadata.d.ts +38 -0
- package/dist/bridge/server/tool-metadata.d.ts.map +1 -0
- package/dist/bridge/server/tool-metadata.js +81 -0
- package/dist/bridge/server/tool-metadata.js.map +1 -0
- package/dist/bridge/server.d.ts +21 -0
- package/dist/bridge/server.d.ts.map +1 -0
- package/dist/bridge/server.js +18 -0
- package/dist/bridge/server.js.map +1 -0
- package/dist/cli/database-rules.d.ts +43 -0
- package/dist/cli/database-rules.d.ts.map +1 -0
- package/dist/cli/database-rules.js +261 -0
- package/dist/cli/database-rules.js.map +1 -0
- package/dist/cli/dev-runner.d.ts +112 -0
- package/dist/cli/dev-runner.d.ts.map +1 -0
- package/dist/cli/dev-runner.js +239 -0
- package/dist/cli/dev-runner.js.map +1 -0
- package/dist/cli/firebase-json.d.ts +66 -0
- package/dist/cli/firebase-json.d.ts.map +1 -0
- package/dist/cli/firebase-json.js +60 -0
- package/dist/cli/firebase-json.js.map +1 -0
- package/dist/cli/firestore-indexes.d.ts +21 -0
- package/dist/cli/firestore-indexes.d.ts.map +1 -0
- package/dist/cli/firestore-indexes.js +39 -0
- package/dist/cli/firestore-indexes.js.map +1 -0
- package/dist/cli/index.d.ts +56 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +379 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +50 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +182 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mcp-proxy.d.ts +10 -0
- package/dist/cli/mcp-proxy.d.ts.map +1 -0
- package/dist/cli/mcp-proxy.js +129 -0
- package/dist/cli/mcp-proxy.js.map +1 -0
- package/dist/cli/parse-args.d.ts +20 -0
- package/dist/cli/parse-args.d.ts.map +1 -0
- package/dist/cli/parse-args.js +69 -0
- package/dist/cli/parse-args.js.map +1 -0
- package/dist/cli/rules.d.ts +55 -0
- package/dist/cli/rules.d.ts.map +1 -0
- package/dist/cli/rules.js +199 -0
- package/dist/cli/rules.js.map +1 -0
- package/dist/cli/scope.d.ts +12 -0
- package/dist/cli/scope.d.ts.map +1 -0
- package/dist/cli/scope.js +44 -0
- package/dist/cli/scope.js.map +1 -0
- package/dist/cli/serve.d.ts +122 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +844 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/service-commands.d.ts +8 -0
- package/dist/cli/service-commands.d.ts.map +1 -0
- package/dist/cli/service-commands.js +58 -0
- package/dist/cli/service-commands.js.map +1 -0
- package/dist/cli/snapshot.d.ts +22 -0
- package/dist/cli/snapshot.d.ts.map +1 -0
- package/dist/cli/snapshot.js +139 -0
- package/dist/cli/snapshot.js.map +1 -0
- package/dist/cli/storage-rules.d.ts +21 -0
- package/dist/cli/storage-rules.d.ts.map +1 -0
- package/dist/cli/storage-rules.js +121 -0
- package/dist/cli/storage-rules.js.map +1 -0
- package/dist/cli/verify.d.ts +23 -0
- package/dist/cli/verify.d.ts.map +1 -0
- package/dist/cli/verify.js +349 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/credentials/core/memoize-ttl.d.ts +58 -0
- package/dist/credentials/core/memoize-ttl.d.ts.map +1 -0
- package/dist/credentials/core/memoize-ttl.js +88 -0
- package/dist/credentials/core/memoize-ttl.js.map +1 -0
- package/dist/credentials/core/types.d.ts +11 -0
- package/dist/credentials/core/types.d.ts.map +1 -0
- package/dist/credentials/core/types.js +2 -0
- package/dist/credentials/core/types.js.map +1 -0
- package/dist/credentials/node/from-adc.d.ts +10 -0
- package/dist/credentials/node/from-adc.d.ts.map +1 -0
- package/dist/credentials/node/from-adc.js +76 -0
- package/dist/credentials/node/from-adc.js.map +1 -0
- package/dist/credentials/node/from-service-account.d.ts +24 -0
- package/dist/credentials/node/from-service-account.d.ts.map +1 -0
- package/dist/credentials/node/from-service-account.js +108 -0
- package/dist/credentials/node/from-service-account.js.map +1 -0
- package/dist/credentials/node/index.d.ts +7 -0
- package/dist/credentials/node/index.d.ts.map +1 -0
- package/dist/credentials/node/index.js +7 -0
- package/dist/credentials/node/index.js.map +1 -0
- package/dist/discover/concurrency.d.ts +42 -0
- package/dist/discover/concurrency.d.ts.map +1 -0
- package/dist/discover/concurrency.js +113 -0
- package/dist/discover/concurrency.js.map +1 -0
- package/dist/discover/crawler-adapter.d.ts +48 -0
- package/dist/discover/crawler-adapter.d.ts.map +1 -0
- package/dist/discover/crawler-adapter.js +92 -0
- package/dist/discover/crawler-adapter.js.map +1 -0
- package/dist/discover/crawler.d.ts +294 -0
- package/dist/discover/crawler.d.ts.map +1 -0
- package/dist/discover/crawler.js +764 -0
- package/dist/discover/crawler.js.map +1 -0
- package/dist/discover/credential-free.d.ts +19 -0
- package/dist/discover/credential-free.d.ts.map +1 -0
- package/dist/discover/credential-free.js +18 -0
- package/dist/discover/credential-free.js.map +1 -0
- package/dist/discover/findCollectionGroup.d.ts +44 -0
- package/dist/discover/findCollectionGroup.d.ts.map +1 -0
- package/dist/discover/findCollectionGroup.js +81 -0
- package/dist/discover/findCollectionGroup.js.map +1 -0
- package/dist/discover/firestore-source.d.ts +60 -0
- package/dist/discover/firestore-source.d.ts.map +1 -0
- package/dist/discover/firestore-source.js +11 -0
- package/dist/discover/firestore-source.js.map +1 -0
- package/dist/discover/index.d.ts +3 -0
- package/dist/discover/index.d.ts.map +1 -0
- package/dist/discover/index.js +5 -0
- package/dist/discover/index.js.map +1 -0
- package/dist/discover/merge.d.ts +108 -0
- package/dist/discover/merge.d.ts.map +1 -0
- package/dist/discover/merge.js +394 -0
- package/dist/discover/merge.js.map +1 -0
- package/dist/discover/session.d.ts +116 -0
- package/dist/discover/session.d.ts.map +1 -0
- package/dist/discover/session.js +331 -0
- package/dist/discover/session.js.map +1 -0
- package/dist/discover/tools.d.ts +58 -0
- package/dist/discover/tools.d.ts.map +1 -0
- package/dist/discover/tools.js +115 -0
- package/dist/discover/tools.js.map +1 -0
- package/dist/discover/types.d.ts +190 -0
- package/dist/discover/types.d.ts.map +1 -0
- package/dist/discover/types.js +12 -0
- package/dist/discover/types.js.map +1 -0
- package/dist/discover/wire.d.ts +70 -0
- package/dist/discover/wire.d.ts.map +1 -0
- package/dist/discover/wire.js +309 -0
- package/dist/discover/wire.js.map +1 -0
- package/dist/functions-rtdb/child.d.ts +52 -0
- package/dist/functions-rtdb/child.d.ts.map +1 -0
- package/dist/functions-rtdb/child.js +283 -0
- package/dist/functions-rtdb/child.js.map +1 -0
- package/dist/functions-rtdb/delivery.d.ts +4 -0
- package/dist/functions-rtdb/delivery.d.ts.map +1 -0
- package/dist/functions-rtdb/delivery.js +2 -0
- package/dist/functions-rtdb/delivery.js.map +1 -0
- package/dist/functions-rtdb/discovery.d.ts +41 -0
- package/dist/functions-rtdb/discovery.d.ts.map +1 -0
- package/dist/functions-rtdb/discovery.js +86 -0
- package/dist/functions-rtdb/discovery.js.map +1 -0
- package/dist/functions-rtdb/event.d.ts +20 -0
- package/dist/functions-rtdb/event.d.ts.map +1 -0
- package/dist/functions-rtdb/event.js +45 -0
- package/dist/functions-rtdb/event.js.map +1 -0
- package/dist/functions-rtdb/execution.d.ts +20 -0
- package/dist/functions-rtdb/execution.d.ts.map +1 -0
- package/dist/functions-rtdb/execution.js +70 -0
- package/dist/functions-rtdb/execution.js.map +1 -0
- package/dist/functions-rtdb/in-memory-delivery.d.ts +9 -0
- package/dist/functions-rtdb/in-memory-delivery.d.ts.map +1 -0
- package/dist/functions-rtdb/in-memory-delivery.js +36 -0
- package/dist/functions-rtdb/in-memory-delivery.js.map +1 -0
- package/dist/functions-rtdb/project.d.ts +7 -0
- package/dist/functions-rtdb/project.d.ts.map +1 -0
- package/dist/functions-rtdb/project.js +54 -0
- package/dist/functions-rtdb/project.js.map +1 -0
- package/dist/functions-rtdb/projection.d.ts +14 -0
- package/dist/functions-rtdb/projection.d.ts.map +1 -0
- package/dist/functions-rtdb/projection.js +65 -0
- package/dist/functions-rtdb/projection.js.map +1 -0
- package/dist/functions-rtdb/reference-pattern.d.ts +5 -0
- package/dist/functions-rtdb/reference-pattern.d.ts.map +1 -0
- package/dist/functions-rtdb/reference-pattern.js +14 -0
- package/dist/functions-rtdb/reference-pattern.js.map +1 -0
- package/dist/functions-rtdb/remote-delivery.d.ts +9 -0
- package/dist/functions-rtdb/remote-delivery.d.ts.map +1 -0
- package/dist/functions-rtdb/remote-delivery.js +11 -0
- package/dist/functions-rtdb/remote-delivery.js.map +1 -0
- package/dist/pkg-version.d.ts +2 -0
- package/dist/pkg-version.d.ts.map +1 -0
- package/dist/pkg-version.js +47 -0
- package/dist/pkg-version.js.map +1 -0
- package/dist/register/esm-exports.d.ts +26 -0
- package/dist/register/esm-exports.d.ts.map +1 -0
- package/dist/register/esm-exports.js +61 -0
- package/dist/register/esm-exports.js.map +1 -0
- package/dist/register/hooks.d.ts +13 -0
- package/dist/register/hooks.d.ts.map +1 -0
- package/dist/register/hooks.js +15 -0
- package/dist/register/hooks.js.map +1 -0
- package/dist/register/index.d.ts +5 -0
- package/dist/register/index.d.ts.map +1 -0
- package/dist/register/index.js +124 -0
- package/dist/register/index.js.map +1 -0
- package/dist/register/mapping.d.ts +19 -0
- package/dist/register/mapping.d.ts.map +1 -0
- package/dist/register/mapping.js +35 -0
- package/dist/register/mapping.js.map +1 -0
- package/dist/remote/index.d.ts +232 -0
- package/dist/remote/index.d.ts.map +1 -0
- package/dist/remote/index.js +720 -0
- package/dist/remote/index.js.map +1 -0
- package/dist/rtdb/crawl-snapshot.d.ts +17 -0
- package/dist/rtdb/crawl-snapshot.d.ts.map +1 -0
- package/dist/rtdb/crawl-snapshot.js +72 -0
- package/dist/rtdb/crawl-snapshot.js.map +1 -0
- package/dist/rtdb/inspection.d.ts +8 -0
- package/dist/rtdb/inspection.d.ts.map +1 -0
- package/dist/rtdb/inspection.js +111 -0
- package/dist/rtdb/inspection.js.map +1 -0
- package/dist/rtdb/load-rules-document.d.ts +25 -0
- package/dist/rtdb/load-rules-document.d.ts.map +1 -0
- package/dist/rtdb/load-rules-document.js +38 -0
- package/dist/rtdb/load-rules-document.js.map +1 -0
- package/dist/rtdb/rules-generation-tool.d.ts +4 -0
- package/dist/rtdb/rules-generation-tool.d.ts.map +1 -0
- package/dist/rtdb/rules-generation-tool.js +35 -0
- package/dist/rtdb/rules-generation-tool.js.map +1 -0
- package/dist/rtdb/rules-json.d.ts +8 -0
- package/dist/rtdb/rules-json.d.ts.map +1 -0
- package/dist/rtdb/rules-json.js +17 -0
- package/dist/rtdb/rules-json.js.map +1 -0
- package/dist/serve/bridge-mount.d.ts +36 -0
- package/dist/serve/bridge-mount.d.ts.map +1 -0
- package/dist/serve/bridge-mount.js +162 -0
- package/dist/serve/bridge-mount.js.map +1 -0
- package/dist/serve/bundler.d.ts +110 -0
- package/dist/serve/bundler.d.ts.map +1 -0
- package/dist/serve/bundler.js +432 -0
- package/dist/serve/bundler.js.map +1 -0
- package/dist/serve/capture-store.d.ts +27 -0
- package/dist/serve/capture-store.d.ts.map +1 -0
- package/dist/serve/capture-store.js +47 -0
- package/dist/serve/capture-store.js.map +1 -0
- package/dist/serve/discovery.d.ts +71 -0
- package/dist/serve/discovery.d.ts.map +1 -0
- package/dist/serve/discovery.js +158 -0
- package/dist/serve/discovery.js.map +1 -0
- package/dist/serve/docs-ui/_astro/_slug_.CQYSemvw.css +1 -0
- package/dist/serve/docs-ui/docs/_rhythm/index.html +99 -0
- package/dist/serve/docs-ui/docs/_rhythm.md +101 -0
- package/dist/serve/docs-ui/docs/api-reference/index.html +64 -0
- package/dist/serve/docs-ui/docs/api-reference.md +67 -0
- package/dist/serve/docs-ui/docs/audit-your-rules/index.html +34 -0
- package/dist/serve/docs-ui/docs/audit-your-rules.md +50 -0
- package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +498 -0
- package/dist/serve/docs-ui/docs/create-pyric-reference-api.md +345 -0
- package/dist/serve/docs-ui/docs/firestore-rules-limits/index.html +59 -0
- package/dist/serve/docs-ui/docs/firestore-rules-limits.md +54 -0
- package/dist/serve/docs-ui/docs/how-the-swap-works/index.html +47 -0
- package/dist/serve/docs-ui/docs/how-the-swap-works.md +43 -0
- package/dist/serve/docs-ui/docs/how-we-know-it-matches-firebase/index.html +131 -0
- package/dist/serve/docs-ui/docs/how-we-know-it-matches-firebase.md +169 -0
- package/dist/serve/docs-ui/docs/index.html +2 -0
- package/dist/serve/docs-ui/docs/index.json +18637 -0
- package/dist/serve/docs-ui/docs/overview/index.html +23 -0
- package/dist/serve/docs-ui/docs/overview.md +40 -0
- package/dist/serve/docs-ui/docs/pyric-admin-app/index.html +19 -0
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +185 -0
- package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api.md +206 -0
- package/dist/serve/docs-ui/docs/pyric-admin-app.md +27 -0
- package/dist/serve/docs-ui/docs/pyric-admin-auth/index.html +24 -0
- package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api/index.html +617 -0
- package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api.md +441 -0
- package/dist/serve/docs-ui/docs/pyric-admin-auth.md +29 -0
- package/dist/serve/docs-ui/docs/pyric-admin-database/index.html +26 -0
- package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api/index.html +583 -0
- package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api.md +597 -0
- package/dist/serve/docs-ui/docs/pyric-admin-database.md +31 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore/index.html +38 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-explanation-error-translation/index.html +57 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-explanation-error-translation.md +95 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-explanation-per-call-delegate/index.html +58 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-explanation-per-call-delegate.md +94 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-explanation-why-mirror-admin-shape/index.html +59 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-explanation-why-mirror-admin-shape.md +88 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-run-a-transaction/index.html +53 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-run-a-transaction.md +76 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-seed-and-set-rules/index.html +62 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-seed-and-set-rules.md +96 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-translate-denials/index.html +80 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-translate-denials.md +98 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-use-onsnapshot/index.html +57 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-use-onsnapshot.md +88 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-write-a-batch/index.html +50 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-how-to-write-a-batch.md +73 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api/index.html +32 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api.md +30 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-onsnapshot/index.html +68 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-onsnapshot.md +81 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-re-exported-types/index.html +76 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-re-exported-types.md +103 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-sandbox-firestore/index.html +40 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-sandbox-firestore.md +77 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-tutorials-01-first-admin-session/index.html +118 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore-tutorials-01-first-admin-session.md +166 -0
- package/dist/serve/docs-ui/docs/pyric-admin-firestore.md +53 -0
- package/dist/serve/docs-ui/docs/pyric-admin-storage/index.html +25 -0
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +317 -0
- package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api.md +285 -0
- package/dist/serve/docs-ui/docs/pyric-admin-storage.md +30 -0
- package/dist/serve/docs-ui/docs/pyric-ai-compat/index.html +436 -0
- package/dist/serve/docs-ui/docs/pyric-ai-compat.md +471 -0
- package/dist/serve/docs-ui/docs/pyric-ai-reference-api/index.html +5831 -0
- package/dist/serve/docs-ui/docs/pyric-ai-reference-api.md +5440 -0
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +159 -0
- package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api.md +122 -0
- package/dist/serve/docs-ui/docs/pyric-app-compat/index.html +180 -0
- package/dist/serve/docs-ui/docs/pyric-app-compat.md +199 -0
- package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +420 -0
- package/dist/serve/docs-ui/docs/pyric-app-reference-api.md +326 -0
- package/dist/serve/docs-ui/docs/pyric-auth/index.html +59 -0
- package/dist/serve/docs-ui/docs/pyric-auth-compat/index.html +804 -0
- package/dist/serve/docs-ui/docs/pyric-auth-compat.md +847 -0
- package/dist/serve/docs-ui/docs/pyric-auth-reference-api/index.html +5452 -0
- package/dist/serve/docs-ui/docs/pyric-auth-reference-api.md +5271 -0
- package/dist/serve/docs-ui/docs/pyric-auth-reference-feature-matrix/index.html +781 -0
- package/dist/serve/docs-ui/docs/pyric-auth-reference-feature-matrix.md +198 -0
- package/dist/serve/docs-ui/docs/pyric-auth-reference-sandbox-test-driver/index.html +71 -0
- package/dist/serve/docs-ui/docs/pyric-auth-reference-sandbox-test-driver.md +108 -0
- package/dist/serve/docs-ui/docs/pyric-auth.md +86 -0
- package/dist/serve/docs-ui/docs/pyric-cli/index.html +40 -0
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +98 -0
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api.md +88 -0
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api/index.html +2355 -0
- package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api.md +1554 -0
- package/dist/serve/docs-ui/docs/pyric-cli-bridge/index.html +69 -0
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api/index.html +546 -0
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api.md +485 -0
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +506 -0
- package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api.md +419 -0
- package/dist/serve/docs-ui/docs/pyric-cli-bridge.md +99 -0
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +67 -0
- package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api.md +59 -0
- package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api/index.html +2355 -0
- package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api.md +2036 -0
- package/dist/serve/docs-ui/docs/pyric-cli-functions-rtdb-compat/index.html +112 -0
- package/dist/serve/docs-ui/docs/pyric-cli-functions-rtdb-compat.md +124 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-build-a-standalone-binary/index.html +91 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-build-a-standalone-binary.md +105 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-promote-sandbox-state-to-a-fixture/index.html +52 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-promote-sandbox-state-to-a-fixture.md +98 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-run-rtdb-onvaluecreated/index.html +66 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-run-rtdb-onvaluecreated.md +100 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-serve-persistence-and-multi-tab/index.html +228 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-serve-persistence-and-multi-tab.md +179 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-use-the-vite-plugin/index.html +341 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-use-the-vite-plugin.md +309 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-verify-against-a-captured-session/index.html +128 -0
- package/dist/serve/docs-ui/docs/pyric-cli-how-to-verify-against-a-captured-session.md +207 -0
- package/dist/serve/docs-ui/docs/pyric-cli-reference-cli/index.html +404 -0
- package/dist/serve/docs-ui/docs/pyric-cli-reference-cli.md +249 -0
- package/dist/serve/docs-ui/docs/pyric-cli-reference-package-and-resolution/index.html +93 -0
- package/dist/serve/docs-ui/docs/pyric-cli-reference-package-and-resolution.md +65 -0
- package/dist/serve/docs-ui/docs/pyric-cli-reference-verify/index.html +81 -0
- package/dist/serve/docs-ui/docs/pyric-cli-reference-verify.md +110 -0
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +10 -0
- package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api.md +16 -0
- package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api/index.html +1044 -0
- package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api.md +952 -0
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api/index.html +5041 -0
- package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +4739 -0
- package/dist/serve/docs-ui/docs/pyric-cli-tutorials-server-adoption/index.html +219 -0
- package/dist/serve/docs-ui/docs/pyric-cli-tutorials-server-adoption.md +251 -0
- package/dist/serve/docs-ui/docs/pyric-cli-tutorials-wire-claude-code/index.html +136 -0
- package/dist/serve/docs-ui/docs/pyric-cli-tutorials-wire-claude-code.md +217 -0
- package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api/index.html +926 -0
- package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api.md +586 -0
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +102 -0
- package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api.md +76 -0
- package/dist/serve/docs-ui/docs/pyric-cli.md +42 -0
- package/dist/serve/docs-ui/docs/pyric-conformance-scores/index.html +180 -0
- package/dist/serve/docs-ui/docs/pyric-conformance-scores.md +184 -0
- package/dist/serve/docs-ui/docs/pyric-database/index.html +43 -0
- package/dist/serve/docs-ui/docs/pyric-database-compat/index.html +1224 -0
- package/dist/serve/docs-ui/docs/pyric-database-compat.md +1289 -0
- package/dist/serve/docs-ui/docs/pyric-database-explanation-rules-authoring-and-deploy-are-separate/index.html +16 -0
- package/dist/serve/docs-ui/docs/pyric-database-explanation-rules-authoring-and-deploy-are-separate.md +23 -0
- package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +1851 -0
- package/dist/serve/docs-ui/docs/pyric-database-reference-api.md +1842 -0
- package/dist/serve/docs-ui/docs/pyric-database-reference-constraints/index.html +381 -0
- package/dist/serve/docs-ui/docs/pyric-database-reference-constraints.md +168 -0
- package/dist/serve/docs-ui/docs/pyric-database-reference-rules-tooling/index.html +218 -0
- package/dist/serve/docs-ui/docs/pyric-database-reference-rules-tooling.md +303 -0
- package/dist/serve/docs-ui/docs/pyric-database-tutorials-01-author-rtdb-rules-with-constraints/index.html +125 -0
- package/dist/serve/docs-ui/docs/pyric-database-tutorials-01-author-rtdb-rules-with-constraints.md +171 -0
- package/dist/serve/docs-ui/docs/pyric-database.md +26 -0
- package/dist/serve/docs-ui/docs/pyric-explanation-versioning-and-compatibility/index.html +40 -0
- package/dist/serve/docs-ui/docs/pyric-explanation-versioning-and-compatibility.md +68 -0
- package/dist/serve/docs-ui/docs/pyric-firestore/index.html +48 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-compat/index.html +868 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-compat.md +939 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-explanation-rules-tooling-is-separate/index.html +92 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-explanation-rules-tooling-is-separate.md +70 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-explanation-target-symbol-opacity/index.html +59 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-explanation-target-symbol-opacity.md +91 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-explanation-two-backends-one-surface/index.html +43 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-explanation-two-backends-one-surface.md +58 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-migrate-from-firebase-firestore/index.html +58 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-migrate-from-firebase-firestore.md +86 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-pick-a-backend/index.html +52 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-pick-a-backend.md +83 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-run-a-transaction/index.html +42 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-run-a-transaction.md +59 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-use-onsnapshot/index.html +66 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-use-onsnapshot.md +96 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-use-sandbox-ops/index.html +61 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-how-to-use-sandbox-ops.md +92 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-api/index.html +3623 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-api.md +3399 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-feature-matrix/index.html +80 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-feature-matrix.md +66 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-getfirestore/index.html +46 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-getfirestore.md +73 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-query-constraints/index.html +80 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-query-constraints.md +129 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-sandbox-ops/index.html +58 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-sandbox-ops.md +88 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-tool-factories/index.html +51 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-reference-tool-factories.md +71 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-tutorials-01-write-a-sandbox-demo/index.html +130 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-tutorials-01-write-a-sandbox-demo.md +180 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-tutorials-02-swap-to-prod-backend/index.html +59 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-tutorials-02-swap-to-prod-backend.md +92 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api/index.html +30 -0
- package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +30 -0
- package/dist/serve/docs-ui/docs/pyric-firestore.md +72 -0
- package/dist/serve/docs-ui/docs/pyric-messaging-compat/index.html +300 -0
- package/dist/serve/docs-ui/docs/pyric-messaging-compat.md +321 -0
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +508 -0
- package/dist/serve/docs-ui/docs/pyric-messaging-reference-api.md +374 -0
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +482 -0
- package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api.md +348 -0
- package/dist/serve/docs-ui/docs/pyric-rules/index.html +87 -0
- package/dist/serve/docs-ui/docs/pyric-rules-compat/index.html +328 -0
- package/dist/serve/docs-ui/docs/pyric-rules-compat.md +347 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-agent-failure-modes/index.html +50 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-agent-failure-modes.md +78 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-lint-vs-validate-vs-simulate-vs-test/index.html +79 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-lint-vs-validate-vs-simulate-vs-test.md +69 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-runtime-budget-and-shared-gates/index.html +67 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-runtime-budget-and-shared-gates.md +75 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-sentinel-expression-engine/index.html +49 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-sentinel-expression-engine.md +74 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-simulator-vs-rules-test-api/index.html +95 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-simulator-vs-rules-test-api.md +80 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-the-2-plus-modules-extension/index.html +58 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-the-2-plus-modules-extension.md +79 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-value-wrappers-design/index.html +63 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-value-wrappers-design.md +84 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-why-this-package-exists/index.html +34 -0
- package/dist/serve/docs-ui/docs/pyric-rules-explanation-why-this-package-exists.md +43 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-compare-rulesets-for-weakening/index.html +55 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-compare-rulesets-for-weakening.md +77 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-inspect-rules-via-the-ast/index.html +90 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-inspect-rules-via-the-ast.md +129 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-lint-rules-source/index.html +55 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-lint-rules-source.md +84 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-pin-request-time/index.html +49 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-pin-request-time.md +64 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-register-tools-with-an-agent/index.html +61 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-register-tools-with-an-agent.md +87 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-resolve-module-imports/index.html +93 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-resolve-module-imports.md +105 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-simulate-rules-locally/index.html +89 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-simulate-rules-locally.md +134 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-test-rules-against-firebase/index.html +66 -0
- package/dist/serve/docs-ui/docs/pyric-rules-how-to-test-rules-against-firebase.md +102 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-api/index.html +2629 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-api.md +2213 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-ast/index.html +85 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-ast.md +121 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-conformance-gaps/index.html +277 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-conformance-gaps.md +360 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-errors/index.html +76 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-errors.md +123 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-lint-rules/index.html +148 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-lint-rules.md +159 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-simulator-context/index.html +66 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-simulator-context.md +104 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-stdlib-modules/index.html +241 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-stdlib-modules.md +143 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-test-case-schema/index.html +94 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-test-case-schema.md +121 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-validator-findings/index.html +87 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-validator-findings.md +117 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-value-wrappers/index.html +102 -0
- package/dist/serve/docs-ui/docs/pyric-rules-reference-value-wrappers.md +152 -0
- package/dist/serve/docs-ui/docs/pyric-rules.md +93 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox/index.html +67 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +120 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api.md +110 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-every-op-is-a-request/index.html +141 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-every-op-is-a-request.md +161 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-identity-is-a-context/index.html +66 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-identity-is-a-context.md +110 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-internal-adapter-protocol/index.html +71 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-internal-adapter-protocol.md +111 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-listener-re-evaluation/index.html +56 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-listener-re-evaluation.md +82 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-local-backend-vs-firestore-offline/index.html +64 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-local-backend-vs-firestore-offline.md +56 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-why-adapters-are-siblings/index.html +92 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-why-adapters-are-siblings.md +90 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-why-this-package-exists/index.html +69 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-explanation-why-this-package-exists.md +57 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +202 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api.md +134 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-multiple-isolated-sandboxes/index.html +63 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-multiple-isolated-sandboxes.md +89 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-observe-events/index.html +159 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-observe-events.md +168 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-pick-an-adapter/index.html +79 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-pick-an-adapter.md +75 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-replay-events/index.html +88 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-replay-events.md +92 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-reset-between-tests/index.html +68 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-reset-between-tests.md +92 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-seed-data-and-rules/index.html +91 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-seed-data-and-rules.md +122 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-switch-users/index.html +50 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-switch-users.md +78 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-use-admin-reads/index.html +54 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-how-to-use-admin-reads.md +85 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api/index.html +5019 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api.md +4060 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-divergences/index.html +125 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-divergences.md +151 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-error-codes/index.html +110 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-error-codes.md +118 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-internal-protocol/index.html +72 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-internal-protocol.md +109 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-sandbox-and-context/index.html +90 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-sandbox-and-context.md +140 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-sandbox-event/index.html +146 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-sandbox-event.md +204 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-snapshot-and-admin/index.html +53 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-reference-snapshot-and-admin.md +89 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-tutorials-01-your-first-sandbox-session/index.html +115 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox-tutorials-01-your-first-sandbox-session.md +176 -0
- package/dist/serve/docs-ui/docs/pyric-sandbox.md +69 -0
- package/dist/serve/docs-ui/docs/pyric-storage/index.html +65 -0
- package/dist/serve/docs-ui/docs/pyric-storage-compat/index.html +676 -0
- package/dist/serve/docs-ui/docs/pyric-storage-compat.md +699 -0
- package/dist/serve/docs-ui/docs/pyric-storage-explanation-implementation-scope/index.html +52 -0
- package/dist/serve/docs-ui/docs/pyric-storage-explanation-implementation-scope.md +85 -0
- package/dist/serve/docs-ui/docs/pyric-storage-explanation-session-archive-use-case/index.html +58 -0
- package/dist/serve/docs-ui/docs/pyric-storage-explanation-session-archive-use-case.md +82 -0
- package/dist/serve/docs-ui/docs/pyric-storage-explanation-why-indexeddb/index.html +50 -0
- package/dist/serve/docs-ui/docs/pyric-storage-explanation-why-indexeddb.md +82 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-enforce-rules/index.html +120 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-enforce-rules.md +127 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-list-and-delete/index.html +53 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-list-and-delete.md +86 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-switch-backends/index.html +43 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-switch-backends.md +65 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-test-rule-expressions/index.html +70 -0
- package/dist/serve/docs-ui/docs/pyric-storage-how-to-test-rule-expressions.md +88 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-api/index.html +2120 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-api.md +1687 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-conformance-gaps/index.html +137 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-conformance-gaps.md +171 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-error-codes/index.html +37 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-error-codes.md +57 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-rules-subset/index.html +96 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-rules-subset.md +134 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-storage-options/index.html +39 -0
- package/dist/serve/docs-ui/docs/pyric-storage-reference-storage-options.md +61 -0
- package/dist/serve/docs-ui/docs/pyric-storage.md +67 -0
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +638 -0
- package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api.md +430 -0
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +813 -0
- package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api.md +634 -0
- package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api/index.html +1708 -0
- package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api.md +1300 -0
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +177 -0
- package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api.md +111 -0
- package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api/index.html +1542 -0
- package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api.md +903 -0
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1024 -0
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api.md +640 -0
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api/index.html +2753 -0
- package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api.md +2171 -0
- package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api/index.html +1005 -0
- package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api.md +693 -0
- package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api/index.html +1388 -0
- package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api.md +1340 -0
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +131 -0
- package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api.md +76 -0
- package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api/index.html +648 -0
- package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api.md +508 -0
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1457 -0
- package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api.md +1029 -0
- package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api/index.html +2476 -0
- package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api.md +1919 -0
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1241 -0
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api.md +817 -0
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api/index.html +2289 -0
- package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api.md +1489 -0
- package/dist/serve/docs-ui/docs/read-a-denial/index.html +40 -0
- package/dist/serve/docs-ui/docs/read-a-denial.md +62 -0
- package/dist/serve/docs-ui/docs/receive-messages/index.html +28 -0
- package/dist/serve/docs-ui/docs/receive-messages.md +43 -0
- package/dist/serve/docs-ui/docs/rtdb-rules-in-typescript/index.html +67 -0
- package/dist/serve/docs-ui/docs/rtdb-rules-in-typescript.md +101 -0
- package/dist/serve/docs-ui/docs/rules-patterns/index.html +68 -0
- package/dist/serve/docs-ui/docs/rules-patterns.md +104 -0
- package/dist/serve/docs-ui/docs/rules-standard-library/index.html +87 -0
- package/dist/serve/docs-ui/docs/rules-standard-library.md +93 -0
- package/dist/serve/docs-ui/docs/run-ai-logic-locally/index.html +27 -0
- package/dist/serve/docs-ui/docs/run-ai-logic-locally.md +43 -0
- package/dist/serve/docs-ui/docs/secure-it-with-rules/index.html +69 -0
- package/dist/serve/docs-ui/docs/secure-it-with-rules.md +101 -0
- package/dist/serve/docs-ui/docs/see-whats-happening/index.html +73 -0
- package/dist/serve/docs-ui/docs/see-whats-happening.md +77 -0
- package/dist/serve/docs-ui/docs/set-up-the-project/index.html +14 -0
- package/dist/serve/docs-ui/docs/set-up-the-project.md +19 -0
- package/dist/serve/docs-ui/docs/set-up-your-agent/index.html +42 -0
- package/dist/serve/docs-ui/docs/set-up-your-agent.md +86 -0
- package/dist/serve/docs-ui/docs/shape-your-data/index.html +44 -0
- package/dist/serve/docs-ui/docs/shape-your-data.md +88 -0
- package/dist/serve/docs-ui/docs/ship-to-production/index.html +36 -0
- package/dist/serve/docs-ui/docs/ship-to-production.md +80 -0
- package/dist/serve/docs-ui/docs/sign-in-and-manage-users/index.html +31 -0
- package/dist/serve/docs-ui/docs/sign-in-and-manage-users.md +50 -0
- package/dist/serve/docs-ui/docs/simulate-and-lint/index.html +95 -0
- package/dist/serve/docs-ui/docs/simulate-and-lint.md +99 -0
- package/dist/serve/docs-ui/docs/skills/index.html +20 -0
- package/dist/serve/docs-ui/docs/skills.md +34 -0
- package/dist/serve/docs-ui/docs/start-building/index.html +32 -0
- package/dist/serve/docs-ui/docs/start-building.md +64 -0
- package/dist/serve/docs-ui/docs/store-and-query-data/index.html +16 -0
- package/dist/serve/docs-ui/docs/store-and-query-data.md +33 -0
- package/dist/serve/docs-ui/docs/store-files/index.html +13 -0
- package/dist/serve/docs-ui/docs/store-files.md +25 -0
- package/dist/serve/docs-ui/docs/sync-realtime-data/index.html +15 -0
- package/dist/serve/docs-ui/docs/sync-realtime-data.md +27 -0
- package/dist/serve/docs-ui/docs/test-in-node/index.html +74 -0
- package/dist/serve/docs-ui/docs/test-in-node.md +100 -0
- package/dist/serve/docs-ui/docs/ui/index.html +76 -0
- package/dist/serve/docs-ui/docs/ui-auth-authsigninhelper/index.html +194 -0
- package/dist/serve/docs-ui/docs/ui-auth-authsigninhelper.md +114 -0
- package/dist/serve/docs-ui/docs/ui-auth-authusers/index.html +263 -0
- package/dist/serve/docs-ui/docs/ui-auth-authusers.md +183 -0
- package/dist/serve/docs-ui/docs/ui-firestore-collectionlist/index.html +92 -0
- package/dist/serve/docs-ui/docs/ui-firestore-collectionlist.md +79 -0
- package/dist/serve/docs-ui/docs/ui-firestore-deletewithconfirm/index.html +128 -0
- package/dist/serve/docs-ui/docs/ui-firestore-deletewithconfirm.md +104 -0
- package/dist/serve/docs-ui/docs/ui-firestore-documenteditor/index.html +154 -0
- package/dist/serve/docs-ui/docs/ui-firestore-documenteditor.md +117 -0
- package/dist/serve/docs-ui/docs/ui-firestore-documentlist/index.html +132 -0
- package/dist/serve/docs-ui/docs/ui-firestore-documentlist.md +92 -0
- package/dist/serve/docs-ui/docs/ui-firestore-documentpreview/index.html +159 -0
- package/dist/serve/docs-ui/docs/ui-firestore-documentpreview.md +84 -0
- package/dist/serve/docs-ui/docs/ui-firestore-querybuilder/index.html +104 -0
- package/dist/serve/docs-ui/docs/ui-firestore-querybuilder.md +103 -0
- package/dist/serve/docs-ui/docs/ui-firestore-referencepicker/index.html +113 -0
- package/dist/serve/docs-ui/docs/ui-firestore-referencepicker.md +93 -0
- package/dist/serve/docs-ui/docs/ui-primitives-badge/index.html +56 -0
- package/dist/serve/docs-ui/docs/ui-primitives-badge.md +40 -0
- package/dist/serve/docs-ui/docs/ui-primitives-confirmdialog/index.html +140 -0
- package/dist/serve/docs-ui/docs/ui-primitives-confirmdialog.md +108 -0
- package/dist/serve/docs-ui/docs/ui-primitives-copybutton/index.html +58 -0
- package/dist/serve/docs-ui/docs/ui-primitives-copybutton.md +37 -0
- package/dist/serve/docs-ui/docs/ui-primitives-jsonview/index.html +58 -0
- package/dist/serve/docs-ui/docs/ui-primitives-jsonview.md +47 -0
- package/dist/serve/docs-ui/docs/ui-primitives-segmentedcontrol/index.html +70 -0
- package/dist/serve/docs-ui/docs/ui-primitives-segmentedcontrol.md +50 -0
- package/dist/serve/docs-ui/docs/ui-primitives-toast/index.html +87 -0
- package/dist/serve/docs-ui/docs/ui-primitives-toast.md +82 -0
- package/dist/serve/docs-ui/docs/ui-primitives-virtuallist/index.html +85 -0
- package/dist/serve/docs-ui/docs/ui-primitives-virtuallist.md +54 -0
- package/dist/serve/docs-ui/docs/ui-storage/index.html +150 -0
- package/dist/serve/docs-ui/docs/ui-storage-deleteselectionwithconfirm/index.html +126 -0
- package/dist/serve/docs-ui/docs/ui-storage-deleteselectionwithconfirm.md +88 -0
- package/dist/serve/docs-ui/docs/ui-storage-objectbrowser/index.html +137 -0
- package/dist/serve/docs-ui/docs/ui-storage-objectbrowser.md +90 -0
- package/dist/serve/docs-ui/docs/ui-storage-objectinspector/index.html +139 -0
- package/dist/serve/docs-ui/docs/ui-storage-objectinspector.md +93 -0
- package/dist/serve/docs-ui/docs/ui-storage-pathbreadcrumb/index.html +72 -0
- package/dist/serve/docs-ui/docs/ui-storage-pathbreadcrumb.md +57 -0
- package/dist/serve/docs-ui/docs/ui-storage-rules-aware-affordances/index.html +60 -0
- package/dist/serve/docs-ui/docs/ui-storage-rules-aware-affordances.md +52 -0
- package/dist/serve/docs-ui/docs/ui-storage-uploaddropzone/index.html +93 -0
- package/dist/serve/docs-ui/docs/ui-storage-uploaddropzone.md +78 -0
- package/dist/serve/docs-ui/docs/ui-storage-usestoragerulesgate/index.html +144 -0
- package/dist/serve/docs-ui/docs/ui-storage-usestoragerulesgate.md +101 -0
- package/dist/serve/docs-ui/docs/ui-storage.md +165 -0
- package/dist/serve/docs-ui/docs/ui-traffic/index.html +88 -0
- package/dist/serve/docs-ui/docs/ui-traffic-ruleheatmap/index.html +79 -0
- package/dist/serve/docs-ui/docs/ui-traffic-ruleheatmap.md +60 -0
- package/dist/serve/docs-ui/docs/ui-traffic-trafficdetail/index.html +78 -0
- package/dist/serve/docs-ui/docs/ui-traffic-trafficdetail.md +59 -0
- package/dist/serve/docs-ui/docs/ui-traffic-trafficlog/index.html +118 -0
- package/dist/serve/docs-ui/docs/ui-traffic-trafficlog.md +69 -0
- package/dist/serve/docs-ui/docs/ui-traffic-trafficstats/index.html +51 -0
- package/dist/serve/docs-ui/docs/ui-traffic-trafficstats.md +46 -0
- package/dist/serve/docs-ui/docs/ui-traffic.md +102 -0
- package/dist/serve/docs-ui/docs/ui.md +90 -0
- package/dist/serve/docs-ui/docs/watch-and-review/index.html +25 -0
- package/dist/serve/docs-ui/docs/watch-and-review.md +40 -0
- package/dist/serve/docs-ui/docs/what-your-agent-can-do/index.html +81 -0
- package/dist/serve/docs-ui/docs/what-your-agent-can-do.md +78 -0
- package/dist/serve/docs-ui/docs/whats-experimental/index.html +22 -0
- package/dist/serve/docs-ui/docs/whats-experimental.md +33 -0
- package/dist/serve/docs-ui/docs/whats-possible/index.html +63 -0
- package/dist/serve/docs-ui/docs/whats-possible.md +53 -0
- package/dist/serve/docs-ui/docs/which-data-service/index.html +8 -0
- package/dist/serve/docs-ui/docs/which-data-service.md +11 -0
- package/dist/serve/docs-ui/docs/write-a-rules-test-suite/index.html +85 -0
- package/dist/serve/docs-ui/docs/write-a-rules-test-suite.md +119 -0
- package/dist/serve/docs-ui/index.html +1 -0
- package/dist/serve/docs-ui/llms.txt +308 -0
- package/dist/serve/entries/ai.d.ts +4 -0
- package/dist/serve/entries/ai.d.ts.map +1 -0
- package/dist/serve/entries/ai.js +184 -0
- package/dist/serve/entries/ai.js.map +1 -0
- package/dist/serve/entries/app-backend.d.ts +2 -0
- package/dist/serve/entries/app-backend.d.ts.map +1 -0
- package/dist/serve/entries/app-backend.js +4 -0
- package/dist/serve/entries/app-backend.js.map +1 -0
- package/dist/serve/entries/app-client.d.ts +5 -0
- package/dist/serve/entries/app-client.d.ts.map +1 -0
- package/dist/serve/entries/app-client.js +23 -0
- package/dist/serve/entries/app-client.js.map +1 -0
- package/dist/serve/entries/app-session-store.d.ts +14 -0
- package/dist/serve/entries/app-session-store.d.ts.map +1 -0
- package/dist/serve/entries/app-session-store.js +37 -0
- package/dist/serve/entries/app-session-store.js.map +1 -0
- package/dist/serve/entries/app.d.ts +2 -0
- package/dist/serve/entries/app.d.ts.map +1 -0
- package/dist/serve/entries/app.js +10 -0
- package/dist/serve/entries/app.js.map +1 -0
- package/dist/serve/entries/auth-helper-core.d.ts +52 -0
- package/dist/serve/entries/auth-helper-core.d.ts.map +1 -0
- package/dist/serve/entries/auth-helper-core.js +118 -0
- package/dist/serve/entries/auth-helper-core.js.map +1 -0
- package/dist/serve/entries/auth-helper-dom.d.ts +14 -0
- package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -0
- package/dist/serve/entries/auth-helper-dom.js +116 -0
- package/dist/serve/entries/auth-helper-dom.js.map +1 -0
- package/dist/serve/entries/auth-helper-runtime.d.ts +5 -0
- package/dist/serve/entries/auth-helper-runtime.d.ts.map +1 -0
- package/dist/serve/entries/auth-helper-runtime.js +11 -0
- package/dist/serve/entries/auth-helper-runtime.js.map +1 -0
- package/dist/serve/entries/auth.d.ts +77 -0
- package/dist/serve/entries/auth.d.ts.map +1 -0
- package/dist/serve/entries/auth.js +201 -0
- package/dist/serve/entries/auth.js.map +1 -0
- package/dist/serve/entries/bridge-url.d.ts +25 -0
- package/dist/serve/entries/bridge-url.d.ts.map +1 -0
- package/dist/serve/entries/bridge-url.js +30 -0
- package/dist/serve/entries/bridge-url.js.map +1 -0
- package/dist/serve/entries/database.d.ts +46 -0
- package/dist/serve/entries/database.d.ts.map +1 -0
- package/dist/serve/entries/database.js +80 -0
- package/dist/serve/entries/database.js.map +1 -0
- package/dist/serve/entries/firestore.d.ts +104 -0
- package/dist/serve/entries/firestore.d.ts.map +1 -0
- package/dist/serve/entries/firestore.js +202 -0
- package/dist/serve/entries/firestore.js.map +1 -0
- package/dist/serve/entries/init.d.ts +2 -0
- package/dist/serve/entries/init.d.ts.map +1 -0
- package/dist/serve/entries/init.js +40 -0
- package/dist/serve/entries/init.js.map +1 -0
- package/dist/serve/entries/keepalive.d.ts +20 -0
- package/dist/serve/entries/keepalive.d.ts.map +1 -0
- package/dist/serve/entries/keepalive.js +38 -0
- package/dist/serve/entries/keepalive.js.map +1 -0
- package/dist/serve/entries/messaging-sw.d.ts +10 -0
- package/dist/serve/entries/messaging-sw.d.ts.map +1 -0
- package/dist/serve/entries/messaging-sw.js +36 -0
- package/dist/serve/entries/messaging-sw.js.map +1 -0
- package/dist/serve/entries/messaging.d.ts +11 -0
- package/dist/serve/entries/messaging.d.ts.map +1 -0
- package/dist/serve/entries/messaging.js +53 -0
- package/dist/serve/entries/messaging.js.map +1 -0
- package/dist/serve/entries/runtime.d.ts +46 -0
- package/dist/serve/entries/runtime.d.ts.map +1 -0
- package/dist/serve/entries/runtime.js +435 -0
- package/dist/serve/entries/runtime.js.map +1 -0
- package/dist/serve/entries/session-store.d.ts +48 -0
- package/dist/serve/entries/session-store.d.ts.map +1 -0
- package/dist/serve/entries/session-store.js +82 -0
- package/dist/serve/entries/session-store.js.map +1 -0
- package/dist/serve/entries/storage.d.ts +25 -0
- package/dist/serve/entries/storage.d.ts.map +1 -0
- package/dist/serve/entries/storage.js +61 -0
- package/dist/serve/entries/storage.js.map +1 -0
- package/dist/serve/entries/tab-sync-wiring.d.ts +88 -0
- package/dist/serve/entries/tab-sync-wiring.d.ts.map +1 -0
- package/dist/serve/entries/tab-sync-wiring.js +217 -0
- package/dist/serve/entries/tab-sync-wiring.js.map +1 -0
- package/dist/serve/entries/worker-runtime.d.ts +10 -0
- package/dist/serve/entries/worker-runtime.d.ts.map +1 -0
- package/dist/serve/entries/worker-runtime.js +59 -0
- package/dist/serve/entries/worker-runtime.js.map +1 -0
- package/dist/serve/init-payload.d.ts +21 -0
- package/dist/serve/init-payload.d.ts.map +1 -0
- package/dist/serve/init-payload.js +2 -0
- package/dist/serve/init-payload.js.map +1 -0
- package/dist/serve/namespace.d.ts +73 -0
- package/dist/serve/namespace.d.ts.map +1 -0
- package/dist/serve/namespace.js +470 -0
- package/dist/serve/namespace.js.map +1 -0
- package/dist/serve/open-browser.d.ts +23 -0
- package/dist/serve/open-browser.d.ts.map +1 -0
- package/dist/serve/open-browser.js +58 -0
- package/dist/serve/open-browser.js.map +1 -0
- package/dist/serve/rules.d.ts +77 -0
- package/dist/serve/rules.d.ts.map +1 -0
- package/dist/serve/rules.js +202 -0
- package/dist/serve/rules.js.map +1 -0
- package/dist/serve/sandbox-marker.d.ts +9 -0
- package/dist/serve/sandbox-marker.d.ts.map +1 -0
- package/dist/serve/sandbox-marker.js +31 -0
- package/dist/serve/sandbox-marker.js.map +1 -0
- package/dist/serve/server.d.ts +135 -0
- package/dist/serve/server.d.ts.map +1 -0
- package/dist/serve/server.js +328 -0
- package/dist/serve/server.js.map +1 -0
- package/dist/serve/standalone-assets.d.ts +67 -0
- package/dist/serve/standalone-assets.d.ts.map +1 -0
- package/dist/serve/standalone-assets.js +134 -0
- package/dist/serve/standalone-assets.js.map +1 -0
- package/dist/serve/state-store.d.ts +45 -0
- package/dist/serve/state-store.d.ts.map +1 -0
- package/dist/serve/state-store.js +120 -0
- package/dist/serve/state-store.js.map +1 -0
- package/dist/serve/studio/disk-project-store.d.ts +9 -0
- package/dist/serve/studio/disk-project-store.d.ts.map +1 -0
- package/dist/serve/studio/disk-project-store.js +173 -0
- package/dist/serve/studio/disk-project-store.js.map +1 -0
- package/dist/serve/studio/disk-workspace.d.ts +14 -0
- package/dist/serve/studio/disk-workspace.d.ts.map +1 -0
- package/dist/serve/studio/disk-workspace.js +152 -0
- package/dist/serve/studio/disk-workspace.js.map +1 -0
- package/dist/serve/studio/index.d.ts +10 -0
- package/dist/serve/studio/index.d.ts.map +1 -0
- package/dist/serve/studio/index.js +9 -0
- package/dist/serve/studio/index.js.map +1 -0
- package/dist/serve/studio/routes.d.ts +40 -0
- package/dist/serve/studio/routes.d.ts.map +1 -0
- package/dist/serve/studio/routes.js +182 -0
- package/dist/serve/studio/routes.js.map +1 -0
- package/dist/serve/studio/store-types.d.ts +45 -0
- package/dist/serve/studio/store-types.d.ts.map +1 -0
- package/dist/serve/studio/store-types.js +11 -0
- package/dist/serve/studio/store-types.js.map +1 -0
- package/dist/serve/studio-ui/assets/RulesCodeEditor-BZpD57II.js +23 -0
- package/dist/serve/studio-ui/assets/index-Bsa-TQNK.css +1 -0
- package/dist/serve/studio-ui/assets/index-DGaVuOhE.js +1211 -0
- package/dist/serve/studio-ui/assets/seed-CTmn6YuO.js +2 -0
- package/dist/serve/studio-ui/index.html +32 -0
- package/dist/serve/studio-ui/pyric-logo.svg +76 -0
- package/dist/serve/vite-plugin.d.ts +57 -0
- package/dist/serve/vite-plugin.d.ts.map +1 -0
- package/dist/serve/vite-plugin.js +658 -0
- package/dist/serve/vite-plugin.js.map +1 -0
- package/dist/serve/worker/client/admin-firestore.d.ts +18 -0
- package/dist/serve/worker/client/admin-firestore.d.ts.map +1 -0
- package/dist/serve/worker/client/admin-firestore.js +26 -0
- package/dist/serve/worker/client/admin-firestore.js.map +1 -0
- package/dist/serve/worker/client/ai.d.ts +31 -0
- package/dist/serve/worker/client/ai.d.ts.map +1 -0
- package/dist/serve/worker/client/ai.js +89 -0
- package/dist/serve/worker/client/ai.js.map +1 -0
- package/dist/serve/worker/client/auth.d.ts +168 -0
- package/dist/serve/worker/client/auth.d.ts.map +1 -0
- package/dist/serve/worker/client/auth.js +322 -0
- package/dist/serve/worker/client/auth.js.map +1 -0
- package/dist/serve/worker/client/connection.d.ts +80 -0
- package/dist/serve/worker/client/connection.d.ts.map +1 -0
- package/dist/serve/worker/client/connection.js +148 -0
- package/dist/serve/worker/client/connection.js.map +1 -0
- package/dist/serve/worker/client/core.d.ts +109 -0
- package/dist/serve/worker/client/core.d.ts.map +1 -0
- package/dist/serve/worker/client/core.js +248 -0
- package/dist/serve/worker/client/core.js.map +1 -0
- package/dist/serve/worker/client/disconnect.d.ts +7 -0
- package/dist/serve/worker/client/disconnect.d.ts.map +1 -0
- package/dist/serve/worker/client/disconnect.js +26 -0
- package/dist/serve/worker/client/disconnect.js.map +1 -0
- package/dist/serve/worker/client/firestore-reads.d.ts +49 -0
- package/dist/serve/worker/client/firestore-reads.d.ts.map +1 -0
- package/dist/serve/worker/client/firestore-reads.js +139 -0
- package/dist/serve/worker/client/firestore-reads.js.map +1 -0
- package/dist/serve/worker/client/firestore-refs.d.ts +54 -0
- package/dist/serve/worker/client/firestore-refs.d.ts.map +1 -0
- package/dist/serve/worker/client/firestore-refs.js +167 -0
- package/dist/serve/worker/client/firestore-refs.js.map +1 -0
- package/dist/serve/worker/client/firestore-writes.d.ts +70 -0
- package/dist/serve/worker/client/firestore-writes.d.ts.map +1 -0
- package/dist/serve/worker/client/firestore-writes.js +169 -0
- package/dist/serve/worker/client/firestore-writes.js.map +1 -0
- package/dist/serve/worker/client/handles.d.ts +73 -0
- package/dist/serve/worker/client/handles.d.ts.map +1 -0
- package/dist/serve/worker/client/handles.js +4 -0
- package/dist/serve/worker/client/handles.js.map +1 -0
- package/dist/serve/worker/client/messaging.d.ts +16 -0
- package/dist/serve/worker/client/messaging.d.ts.map +1 -0
- package/dist/serve/worker/client/messaging.js +60 -0
- package/dist/serve/worker/client/messaging.js.map +1 -0
- package/dist/serve/worker/client/presence.d.ts +43 -0
- package/dist/serve/worker/client/presence.d.ts.map +1 -0
- package/dist/serve/worker/client/presence.js +132 -0
- package/dist/serve/worker/client/presence.js.map +1 -0
- package/dist/serve/worker/client/rtdb.d.ts +36 -0
- package/dist/serve/worker/client/rtdb.d.ts.map +1 -0
- package/dist/serve/worker/client/rtdb.js +241 -0
- package/dist/serve/worker/client/rtdb.js.map +1 -0
- package/dist/serve/worker/client/rules.d.ts +24 -0
- package/dist/serve/worker/client/rules.d.ts.map +1 -0
- package/dist/serve/worker/client/rules.js +44 -0
- package/dist/serve/worker/client/rules.js.map +1 -0
- package/dist/serve/worker/client/service-worker-connection.d.ts +3 -0
- package/dist/serve/worker/client/service-worker-connection.d.ts.map +1 -0
- package/dist/serve/worker/client/service-worker-connection.js +53 -0
- package/dist/serve/worker/client/service-worker-connection.js.map +1 -0
- package/dist/serve/worker/client/snapshots.d.ts +32 -0
- package/dist/serve/worker/client/snapshots.d.ts.map +1 -0
- package/dist/serve/worker/client/snapshots.js +46 -0
- package/dist/serve/worker/client/snapshots.js.map +1 -0
- package/dist/serve/worker/client/storage.d.ts +64 -0
- package/dist/serve/worker/client/storage.d.ts.map +1 -0
- package/dist/serve/worker/client/storage.js +125 -0
- package/dist/serve/worker/client/storage.js.map +1 -0
- package/dist/serve/worker/client/studio.d.ts +32 -0
- package/dist/serve/worker/client/studio.d.ts.map +1 -0
- package/dist/serve/worker/client/studio.js +61 -0
- package/dist/serve/worker/client/studio.js.map +1 -0
- package/dist/serve/worker/client.d.ts +43 -0
- package/dist/serve/worker/client.d.ts.map +1 -0
- package/dist/serve/worker/client.js +44 -0
- package/dist/serve/worker/client.js.map +1 -0
- package/dist/serve/worker/entry.d.ts +40 -0
- package/dist/serve/worker/entry.d.ts.map +1 -0
- package/dist/serve/worker/entry.js +144 -0
- package/dist/serve/worker/entry.js.map +1 -0
- package/dist/serve/worker/host/admin-firestore.d.ts +17 -0
- package/dist/serve/worker/host/admin-firestore.d.ts.map +1 -0
- package/dist/serve/worker/host/admin-firestore.js +92 -0
- package/dist/serve/worker/host/admin-firestore.js.map +1 -0
- package/dist/serve/worker/host/connection.d.ts +40 -0
- package/dist/serve/worker/host/connection.d.ts.map +1 -0
- package/dist/serve/worker/host/connection.js +153 -0
- package/dist/serve/worker/host/connection.js.map +1 -0
- package/dist/serve/worker/host/core.d.ts +159 -0
- package/dist/serve/worker/host/core.d.ts.map +1 -0
- package/dist/serve/worker/host/core.js +296 -0
- package/dist/serve/worker/host/core.js.map +1 -0
- package/dist/serve/worker/host/dispatch.d.ts +34 -0
- package/dist/serve/worker/host/dispatch.d.ts.map +1 -0
- package/dist/serve/worker/host/dispatch.js +267 -0
- package/dist/serve/worker/host/dispatch.js.map +1 -0
- package/dist/serve/worker/host/firestore-reads.d.ts +17 -0
- package/dist/serve/worker/host/firestore-reads.d.ts.map +1 -0
- package/dist/serve/worker/host/firestore-reads.js +108 -0
- package/dist/serve/worker/host/firestore-reads.js.map +1 -0
- package/dist/serve/worker/host/firestore-writes.d.ts +37 -0
- package/dist/serve/worker/host/firestore-writes.d.ts.map +1 -0
- package/dist/serve/worker/host/firestore-writes.js +409 -0
- package/dist/serve/worker/host/firestore-writes.js.map +1 -0
- package/dist/serve/worker/host/presence.d.ts +38 -0
- package/dist/serve/worker/host/presence.d.ts.map +1 -0
- package/dist/serve/worker/host/presence.js +280 -0
- package/dist/serve/worker/host/presence.js.map +1 -0
- package/dist/serve/worker/host/rtdb.d.ts +18 -0
- package/dist/serve/worker/host/rtdb.d.ts.map +1 -0
- package/dist/serve/worker/host/rtdb.js +128 -0
- package/dist/serve/worker/host/rtdb.js.map +1 -0
- package/dist/serve/worker/host/rules.d.ts +17 -0
- package/dist/serve/worker/host/rules.d.ts.map +1 -0
- package/dist/serve/worker/host/rules.js +118 -0
- package/dist/serve/worker/host/rules.js.map +1 -0
- package/dist/serve/worker/host/storage.d.ts +19 -0
- package/dist/serve/worker/host/storage.d.ts.map +1 -0
- package/dist/serve/worker/host/storage.js +260 -0
- package/dist/serve/worker/host/storage.js.map +1 -0
- package/dist/serve/worker/host/studio.d.ts +13 -0
- package/dist/serve/worker/host/studio.d.ts.map +1 -0
- package/dist/serve/worker/host/studio.js +30 -0
- package/dist/serve/worker/host/studio.js.map +1 -0
- package/dist/serve/worker/host/subscriptions.d.ts +21 -0
- package/dist/serve/worker/host/subscriptions.d.ts.map +1 -0
- package/dist/serve/worker/host/subscriptions.js +162 -0
- package/dist/serve/worker/host/subscriptions.js.map +1 -0
- package/dist/serve/worker/host-ai.d.ts +59 -0
- package/dist/serve/worker/host-ai.d.ts.map +1 -0
- package/dist/serve/worker/host-ai.js +158 -0
- package/dist/serve/worker/host-ai.js.map +1 -0
- package/dist/serve/worker/host-auth.d.ts +47 -0
- package/dist/serve/worker/host-auth.d.ts.map +1 -0
- package/dist/serve/worker/host-auth.js +464 -0
- package/dist/serve/worker/host-auth.js.map +1 -0
- package/dist/serve/worker/host-context.d.ts +220 -0
- package/dist/serve/worker/host-context.d.ts.map +1 -0
- package/dist/serve/worker/host-context.js +45 -0
- package/dist/serve/worker/host-context.js.map +1 -0
- package/dist/serve/worker/host-events.d.ts +21 -0
- package/dist/serve/worker/host-events.d.ts.map +1 -0
- package/dist/serve/worker/host-events.js +87 -0
- package/dist/serve/worker/host-events.js.map +1 -0
- package/dist/serve/worker/host-messaging.d.ts +60 -0
- package/dist/serve/worker/host-messaging.d.ts.map +1 -0
- package/dist/serve/worker/host-messaging.js +226 -0
- package/dist/serve/worker/host-messaging.js.map +1 -0
- package/dist/serve/worker/host.d.ts +36 -0
- package/dist/serve/worker/host.d.ts.map +1 -0
- package/dist/serve/worker/host.js +39 -0
- package/dist/serve/worker/host.js.map +1 -0
- package/dist/serve/worker/index.d.ts +22 -0
- package/dist/serve/worker/index.d.ts.map +1 -0
- package/dist/serve/worker/index.js +61 -0
- package/dist/serve/worker/index.js.map +1 -0
- package/dist/serve/worker/presence-timing.d.ts +14 -0
- package/dist/serve/worker/presence-timing.d.ts.map +1 -0
- package/dist/serve/worker/presence-timing.js +14 -0
- package/dist/serve/worker/presence-timing.js.map +1 -0
- package/dist/serve/worker/protocol.d.ts +1150 -0
- package/dist/serve/worker/protocol.d.ts.map +1 -0
- package/dist/serve/worker/protocol.js +228 -0
- package/dist/serve/worker/protocol.js.map +1 -0
- package/dist/serve/worker/serve-init.d.ts +201 -0
- package/dist/serve/worker/serve-init.d.ts.map +1 -0
- package/dist/serve/worker/serve-init.js +579 -0
- package/dist/serve/worker/serve-init.js.map +1 -0
- package/dist/serve/worker/service-worker-channel.d.ts +23 -0
- package/dist/serve/worker/service-worker-channel.d.ts.map +1 -0
- package/dist/serve/worker/service-worker-channel.js +9 -0
- package/dist/serve/worker/service-worker-channel.js.map +1 -0
- package/dist/serve/worker/service-worker-relay.d.ts +22 -0
- package/dist/serve/worker/service-worker-relay.d.ts.map +1 -0
- package/dist/serve/worker/service-worker-relay.js +63 -0
- package/dist/serve/worker/service-worker-relay.js.map +1 -0
- package/dist/serve/writer-lock.d.ts +32 -0
- package/dist/serve/writer-lock.d.ts.map +1 -0
- package/dist/serve/writer-lock.js +43 -0
- package/dist/serve/writer-lock.js.map +1 -0
- package/dist/verify/cases.d.ts +37 -0
- package/dist/verify/cases.d.ts.map +1 -0
- package/dist/verify/cases.js +173 -0
- package/dist/verify/cases.js.map +1 -0
- package/dist/verify/fixture.d.ts +100 -0
- package/dist/verify/fixture.d.ts.map +1 -0
- package/dist/verify/fixture.js +156 -0
- package/dist/verify/fixture.js.map +1 -0
- package/dist/verify/index.d.ts +102 -0
- package/dist/verify/index.d.ts.map +1 -0
- package/dist/verify/index.js +318 -0
- package/dist/verify/index.js.map +1 -0
- package/dist/verify/tools.d.ts +7 -0
- package/dist/verify/tools.d.ts.map +1 -0
- package/dist/verify/tools.js +83 -0
- package/dist/verify/tools.js.map +1 -0
- package/dist/version/compat-target.d.ts +18 -0
- package/dist/version/compat-target.d.ts.map +1 -0
- package/dist/version/compat-target.js +18 -0
- package/dist/version/compat-target.js.map +1 -0
- package/dist/vite.d.ts +12 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +16 -0
- package/dist/vite.js.map +1 -0
- package/package.json +133 -0
|
@@ -0,0 +1,1289 @@
|
|
|
1
|
+
<!-- Generated from packages/conformance/registry/*.ts. Do not edit by hand; run bun run compat:generate. -->
|
|
2
|
+
|
|
3
|
+
# `pyric/database` compatibility matrix
|
|
4
|
+
|
|
5
|
+
<div class="compat-stat">
|
|
6
|
+
<p class="compat-stat-surface"><strong>Public surface:</strong> runtime 79.5% (35/44) <span aria-hidden="true">·</span> types 53.3% (8/15)</p>
|
|
7
|
+
<p class="compat-stat-figure">
|
|
8
|
+
<span class="compat-stat-pct">76.6%</span>
|
|
9
|
+
<span class="compat-stat-label">of tracked behaviors conform</span>
|
|
10
|
+
</p>
|
|
11
|
+
<p class="compat-stat-denom">154 of 201 tracked behaviors</p>
|
|
12
|
+
<div class="compat-stat-bar" role="img" aria-label="Behavior distribution: 154 conform, 9 documented divergences, 0 bugs, 26 unsupported, 12 unverified.">
|
|
13
|
+
<span class="compat-stat-seg" data-status="ok" style="flex-grow: 154" aria-hidden="true"></span>
|
|
14
|
+
<span class="compat-stat-seg" data-status="diverged" style="flex-grow: 9" aria-hidden="true"></span>
|
|
15
|
+
<span class="compat-stat-seg" data-status="unsupported" style="flex-grow: 26" aria-hidden="true"></span>
|
|
16
|
+
<span class="compat-stat-seg" data-status="unverified" style="flex-grow: 12" aria-hidden="true"></span>
|
|
17
|
+
</div>
|
|
18
|
+
<ul class="compat-stat-key" aria-label="Behavior state counts">
|
|
19
|
+
<li class="compat-stat-item"><span class="compat-dot" data-status="ok" aria-hidden="true"></span><span><strong>154</strong> conform</span></li>
|
|
20
|
+
<li class="compat-stat-item"><span class="compat-dot" data-status="diverged" aria-hidden="true"></span><span><strong>9</strong> documented divergences</span></li>
|
|
21
|
+
<li class="compat-stat-item"><span class="compat-dot" data-status="bug" aria-hidden="true"></span><span><strong>0</strong> bugs</span></li>
|
|
22
|
+
<li class="compat-stat-item"><span class="compat-dot" data-status="unsupported" aria-hidden="true"></span><span><strong>26</strong> unsupported</span></li>
|
|
23
|
+
<li class="compat-stat-item"><span class="compat-dot" data-status="unverified" aria-hidden="true"></span><span><strong>12</strong> unverified</span></li>
|
|
24
|
+
</ul>
|
|
25
|
+
<p class="compat-stat-note">Public surface measures whether exports exist. Fidelity measures whether tracked behavior matches production.</p>
|
|
26
|
+
</div>
|
|
27
|
+
[Read how the axes differ.](../pyric-conformance-scores/)
|
|
28
|
+
|
|
29
|
+
> ⚠ **EXPERIMENTAL — not v1-supported.** The v1-supported, conformance-held surface is **auth + firestore + rules**. The modular `firebase/database` mirror rows below are verified sandbox-side by unit probes, but most are not yet captured against a live production project. Do not depend on RTDB parity for a production swap yet.
|
|
30
|
+
|
|
31
|
+
`pyric/database` is the sandbox-only modular mirror. Package resolution selects it during Pyric development; production code continues to import the unchanged `firebase/database` package. The mirror never dispatches to production at runtime.
|
|
32
|
+
|
|
33
|
+
The pure RTDB rules engine remains on the unstable `pyric/rules/internal/rtdb` seam for simulator, replay, grammar, and constraints consumers. Its compiled rules tree carries no service or database environment metadata. Production data access and deployment are intentionally absent.
|
|
34
|
+
|
|
35
|
+
## Status legend
|
|
36
|
+
|
|
37
|
+
<div class="compat-key">
|
|
38
|
+
<span class="compat-key-item"><span class="compat-dot" data-status="ok"></span><strong>Conforming</strong> — observable behavior matches Firebase, locked by a passing probe</span>
|
|
39
|
+
<span class="compat-key-item"><span class="compat-dot" data-status="diverged"></span><strong>Diverged (documented)</strong> — intentional difference with a written reason</span>
|
|
40
|
+
<span class="compat-key-item"><span class="compat-dot" data-status="bug"></span><strong>Bug</strong> — should match Firebase but does not</span>
|
|
41
|
+
<span class="compat-key-item"><span class="compat-dot" data-status="unsupported"></span><strong>Unsupported</strong> — not implemented or intentionally outside the mirror</span>
|
|
42
|
+
<span class="compat-key-item"><span class="compat-dot" data-status="unverified"></span><strong>Unverified</strong> — not yet backed by sufficient evidence</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
Probe references: `unit:<file>` means a Bun test under `packages/pyric/test/database/`; `oracle:<name>` cites a recorded observation under `packages/conformance/observations/`.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Archived production-toolkit observations
|
|
50
|
+
|
|
51
|
+
These unsupported tombstones preserve immutable oracle `rowIds` for the removed host, REST, data, crawl, generation, and deployment toolkit. They are historical evidence, not current API claims.
|
|
52
|
+
|
|
53
|
+
<div class="compat-list">
|
|
54
|
+
<details class="compat-row" data-status="unsupported">
|
|
55
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed REST host</code><span class="compat-sub"><span class="compat-behavior">Historical <code>.json</code> REST transport contract for the removed production host.</span></span></span></summary>
|
|
56
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
57
|
+
</details>
|
|
58
|
+
<details class="compat-row" data-status="unsupported">
|
|
59
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical admin read and set/get behavior for the removed production data handler.</span></span></span></summary>
|
|
60
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observations; implementation removed.</div></div>
|
|
61
|
+
</details>
|
|
62
|
+
<details class="compat-row" data-status="unsupported">
|
|
63
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical user read return shape for the removed production data handler.</span></span></span></summary>
|
|
64
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
65
|
+
</details>
|
|
66
|
+
<details class="compat-row" data-status="unsupported">
|
|
67
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical rules-denial normalization for the removed production data handler.</span></span></span></summary>
|
|
68
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observations; implementation removed.</div></div>
|
|
69
|
+
</details>
|
|
70
|
+
<details class="compat-row" data-status="unsupported">
|
|
71
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical rules-denied read behavior for the removed production data handler.</span></span></span></summary>
|
|
72
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
73
|
+
</details>
|
|
74
|
+
<details class="compat-row" data-status="unsupported">
|
|
75
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical set/get round trip for the removed production data handler.</span></span></span></summary>
|
|
76
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
77
|
+
</details>
|
|
78
|
+
<details class="compat-row" data-status="unsupported">
|
|
79
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical set-null removal behavior for the removed production data handler.</span></span></span></summary>
|
|
80
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
81
|
+
</details>
|
|
82
|
+
<details class="compat-row" data-status="unsupported">
|
|
83
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical rules-denied write behavior for the removed production data handler.</span></span></span></summary>
|
|
84
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
85
|
+
</details>
|
|
86
|
+
<details class="compat-row" data-status="unsupported">
|
|
87
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical multi-path update behavior for the removed production data handler.</span></span></span></summary>
|
|
88
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
89
|
+
</details>
|
|
90
|
+
<details class="compat-row" data-status="unsupported">
|
|
91
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical push key behavior for the removed production data handler.</span></span></span></summary>
|
|
92
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
93
|
+
</details>
|
|
94
|
+
<details class="compat-row" data-status="unsupported">
|
|
95
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical push auto-ID format for the removed production data handler.</span></span></span></summary>
|
|
96
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
97
|
+
</details>
|
|
98
|
+
<details class="compat-row" data-status="unsupported">
|
|
99
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical remove-versus-set-null behavior for the removed production data handler.</span></span></span></summary>
|
|
100
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
101
|
+
</details>
|
|
102
|
+
<details class="compat-row" data-status="unsupported">
|
|
103
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub"><span class="compat-behavior">Historical idempotent removal behavior for the removed production data handler.</span></span></span></summary>
|
|
104
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
105
|
+
</details>
|
|
106
|
+
<details class="compat-row" data-status="unsupported">
|
|
107
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed rules fetch handler</code><span class="compat-sub"><span class="compat-behavior">Historical deployed-rules JSON round trip for the removed production fetch handler.</span></span></span></summary>
|
|
108
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
109
|
+
</details>
|
|
110
|
+
<details class="compat-row" data-status="unsupported">
|
|
111
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed rules deployment handler</code><span class="compat-sub"><span class="compat-behavior">Historical rules deployment propagation timing for the removed production deploy handler.</span></span></span></summary>
|
|
112
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
113
|
+
</details>
|
|
114
|
+
<details class="compat-row" data-status="unsupported">
|
|
115
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">Removed REST crawler</code><span class="compat-sub"><span class="compat-behavior">Historical shallow REST response shape for the removed production crawler.</span></span></span></summary>
|
|
116
|
+
<div class="compat-evidence"><div class="compat-probe">Archived oracle observation; implementation removed.</div></div>
|
|
117
|
+
</details>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
## `simulateRtdbRules(compiled, input)` — in-process rule evaluator
|
|
121
|
+
|
|
122
|
+
<div class="compat-list">
|
|
123
|
+
<details class="compat-row" data-status="unsupported">
|
|
124
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">The removed stateful simulator returned a generate-before-simulate error when no IR had been generated</span></span></span></summary>
|
|
125
|
+
<div class="compat-evidence"><div class="compat-probe">The stateless <code>simulateRtdbRules(compiled, input)</code> API requires a compiled rules tree and has no generate-before-simulate lifecycle.</div></div>
|
|
126
|
+
</details>
|
|
127
|
+
<details class="compat-row" data-status="ok">
|
|
128
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">Returns <code>{ success: false, error: { code: 'INVALID_INPUT' } }</code> when input doesn't parse against <code>SimulationInputSchema</code> (e.g. path missing leading slash, operation not in read / write / validate)</span></span></span></summary>
|
|
129
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
130
|
+
</details>
|
|
131
|
+
<details class="compat-row" data-status="ok">
|
|
132
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">Walks ancestors from root → target; the first ancestor whose rule expression evaluates to <code>true</code> grants access — matches RTDB's documented "rules cascade from root, true at any ancestor grants" semantics</span></span></span></summary>
|
|
133
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
134
|
+
</details>
|
|
135
|
+
<details class="compat-row" data-status="ok">
|
|
136
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">Path variables (<code>$userId</code>) are bound from the URL path and exposed in <code>pathVariableBindings</code> (also without the <code>$</code> prefix for ergonomic access in expressions)</span></span></span></summary>
|
|
137
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
138
|
+
</details>
|
|
139
|
+
<details class="compat-row" data-status="ok">
|
|
140
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior"><code>auth</code> context: when <code>null</code>, <code>auth</code> is null inside expressions; when present, <code>auth.uid</code> and <code>auth.token.*</code> are bound</span></span></span></summary>
|
|
141
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code>, <code>unit:grammar/simulator.test.ts</code></div></div>
|
|
142
|
+
</details>
|
|
143
|
+
<details class="compat-row" data-status="ok">
|
|
144
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior"><code>mockData</code> becomes the value of <code>data</code> at every path during evaluation; <code>newData</code> is the proposed value for write/validate</span></span></span></summary>
|
|
145
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
146
|
+
</details>
|
|
147
|
+
<details class="compat-row" data-status="ok">
|
|
148
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior"><code>data.child("…")</code>, <code>data.parent()</code>, <code>data.exists()</code>, <code>data.val()</code> evaluate against the in-process snapshot — matches the documented <code>DataSnapshot</code> rule-context surface</span></span></span></summary>
|
|
149
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:grammar/simulator.test.ts</code></div></div>
|
|
150
|
+
</details>
|
|
151
|
+
<details class="compat-row" data-status="diverged">
|
|
152
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">Cross-path <code>root.child(…).val()</code> reads return <code>null</code> for paths NOT present in <code>mockData</code> — divergence from real prod rules where the engine reads the live database</span></span></span></summary>
|
|
153
|
+
<div class="compat-evidence"><div class="compat-probe">divergence: the simulator uses ONLY what's in <code>mockData</code>. Real rules engine reads from the live RTDB. Documented in <code>validated.ts</code> ("simulation uses empty mockData, so cross-path rule lookups … will evaluate as false")</div></div>
|
|
154
|
+
</details>
|
|
155
|
+
<details class="compat-row" data-status="ok">
|
|
156
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">An expression that fails to parse (<code>parsed.valid === false</code>) produces an unsupported result rather than silently granting or fabricating a deny</span></span></span></summary>
|
|
157
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
158
|
+
</details>
|
|
159
|
+
<details class="compat-row" data-status="ok">
|
|
160
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">When no ancestor rule allows, the result is <code>{ allowed: false }</code> with <code>matchedPath</code> set to the deepest matched node</span></span></span></summary>
|
|
161
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
162
|
+
</details>
|
|
163
|
+
<details class="compat-row" data-status="ok">
|
|
164
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">When NO ancestor has a rule for the operation at all, returns <code>{ success: false, error: { code: 'NO_MATCHING_RULE' } }</code></span></span></span></summary>
|
|
165
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
166
|
+
</details>
|
|
167
|
+
<details class="compat-row" data-status="ok">
|
|
168
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">Evaluation errors (grammar mismatch, unknown identifier) surface as <code>EVALUATION_ERROR</code></span></span></span></summary>
|
|
169
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:simulation/handler.test.ts</code></div></div>
|
|
170
|
+
</details>
|
|
171
|
+
<details class="compat-row" data-status="ok">
|
|
172
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub"><span class="compat-behavior">Simulator's allow/deny decision matches the real RTDB rules engine for the same <code>{ rules, mockData, auth, operation, path, newData }</code> tuple, modulo the documented cross-path divergence on row #66</span></span></span></summary>
|
|
173
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-simulator-vs-prod-agreement.json</code> — 8 test rules × 29 (rule, op) tuples; 28 agreements, 1 disagreement at capture time (<code>r4-validate-structure</code>: the simulator did not evaluate <code>.validate</code> on writes). The <code>.validate</code> walk is now implemented (<code>src/rules/rtdb/simulation/handler.ts</code>, reached from all backend write sites; grammar array-literals + <code>hasChildren(keys)</code> fixed alongside), closing the recorded disagreement — replayed as prod-conforming denial in <code>oracle-conformance.test.ts</code>. The frozen capture documents the historical divergence</div></div>
|
|
174
|
+
</details>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
## Constraint authoring surface (`atoms` / `policies` / `compose` / `ruleset`)
|
|
178
|
+
|
|
179
|
+
<div class="compat-list">
|
|
180
|
+
<details class="compat-row" data-status="ok">
|
|
181
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>atoms</code> exports the documented set of primitive predicates (<code>authenticated</code>, <code>ownPath</code>, <code>ownField</code>, <code>isNew</code>, <code>hasChildren</code>, <code>hasChild</code>, <code>fieldIsString/Number/Boolean</code>, <code>fieldEnum</code>, <code>immutable</code>, <code>immutableSelf</code>, <code>rootExists</code>, <code>rootEquals</code>) — each returns an <code>Expr</code></span></span></summary>
|
|
182
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:constraints/atoms.test.ts</code></div></div>
|
|
183
|
+
</details>
|
|
184
|
+
<details class="compat-row" data-status="ok">
|
|
185
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>policies</code> exports composite predicates that compose atoms: <code>pathOwnerOnly</code>, <code>fieldOwnerOnly</code>, <code>ownerOrNew</code>, <code>hasRole</code>, <code>isMember</code>, <code>required</code>, <code>transition</code></span></span></summary>
|
|
186
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:constraints/policies.test.ts</code></div></div>
|
|
187
|
+
</details>
|
|
188
|
+
<details class="compat-row" data-status="ok">
|
|
189
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>compose</code> exports the boolean combinators <code>all</code>, <code>any</code>, <code>not</code>, <code>deny</code>, <code>always</code>, plus the raw <code>expr</code> constructor</span></span></summary>
|
|
190
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:constraints/compose.test.ts</code></div></div>
|
|
191
|
+
</details>
|
|
192
|
+
<details class="compat-row" data-status="ok">
|
|
193
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>ruleset(...)</code> builds an environment-independent compiled RTDB rules tree from path definitions + expression objects</span></span></summary>
|
|
194
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:constraints/ruleset.test.ts</code></div></div>
|
|
195
|
+
</details>
|
|
196
|
+
<details class="compat-row" data-status="ok">
|
|
197
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Game-domain helpers (<code>turnGuard</code>, <code>flip</code>, <code>winCheckHelper</code>) compose into legal rule expressions</span></span></summary>
|
|
198
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:constraints/game.test.ts</code></div></div>
|
|
199
|
+
</details>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
## Compiled RTDB rules tree ↔ rules JSON
|
|
203
|
+
|
|
204
|
+
<div class="compat-list">
|
|
205
|
+
<details class="compat-row" data-status="ok">
|
|
206
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">compileRtdbRules</code><span class="compat-sub"><span class="compat-behavior"><code>compileRtdbRules(rulesJson)</code> produces an environment-independent tree where each node carries its path, parsed expressions, and child nodes</span></span></span></summary>
|
|
207
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:compiled-rules.test.ts</code></div></div>
|
|
208
|
+
</details>
|
|
209
|
+
<details class="compat-row" data-status="ok">
|
|
210
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">serializeRtdbRules</code><span class="compat-sub"><span class="compat-behavior"><code>serializeRtdbRules(compiled)</code> produces the Firebase rules-JSON payload for the compiled tree</span></span></span></summary>
|
|
211
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:compiled-rules.test.ts</code></div></div>
|
|
212
|
+
</details>
|
|
213
|
+
<details class="compat-row" data-status="ok">
|
|
214
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">compileRtdbRules / serializeRtdbRules</code><span class="compat-sub"><span class="compat-behavior">Round-trip <code>compileRtdbRules(serializeRtdbRules(compiled))</code> produces an equivalent rules tree (locked path/expression-text equality, not object identity)</span></span></span></summary>
|
|
215
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:compiled-rules.test.ts</code></div></div>
|
|
216
|
+
</details>
|
|
217
|
+
<details class="compat-row" data-status="ok">
|
|
218
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">compileRtdbRules / serializeRtdbRules</code><span class="compat-sub"><span class="compat-behavior">Path-variable segments (<code>$userId</code>, <code>$gameId</code>) preserved across the round-trip</span></span></span></summary>
|
|
219
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:compiled-rules.test.ts</code></div></div>
|
|
220
|
+
</details>
|
|
221
|
+
<details class="compat-row" data-status="ok">
|
|
222
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><code class="compat-api">compileRtdbRules / serializeRtdbRules</code><span class="compat-sub"><span class="compat-behavior"><code>.indexOn</code> arrays preserved across the round-trip</span></span></span></summary>
|
|
223
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:compiled-rules.test.ts</code></div></div>
|
|
224
|
+
</details>
|
|
225
|
+
</div>
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Modular SDK surface
|
|
230
|
+
|
|
231
|
+
`pyric/database` is the sandbox-only mirror of `firebase/database`'s
|
|
232
|
+
tree-shakable free-function shape (`getDatabase`, `ref`, `child`, `get`,
|
|
233
|
+
`set`, `update`, `remove`, `push`, listeners, queries, transactions, and
|
|
234
|
+
sentinels). Package resolution selects production or sandbox before either
|
|
235
|
+
module loads; this mirror has no production target or runtime dependency on
|
|
236
|
+
`firebase/database`.
|
|
237
|
+
|
|
238
|
+
Two sandbox identity modes are selected by the value passed to
|
|
239
|
+
`getDatabase`:
|
|
240
|
+
|
|
241
|
+
- **Sandbox** — `getDatabase(ctx: SandboxContext)`. Frozen identity baked into
|
|
242
|
+
the handle at construction.
|
|
243
|
+
- **Sandbox-live** — `getDatabase(sandbox: Sandbox)`. Identity read per
|
|
244
|
+
operation from `sandbox.currentUser`.
|
|
245
|
+
|
|
246
|
+
The implementation lives in `packages/pyric/src/database/modular.ts`; the
|
|
247
|
+
in-process backend lives in `packages/pyric/src/database/sandbox/`. Rows below
|
|
248
|
+
are scoped to the modular mirror. The pure rules-engine rows above are internal
|
|
249
|
+
tooling coverage and are not exports of `pyric/database`.
|
|
250
|
+
|
|
251
|
+
<div class="compat-list">
|
|
252
|
+
<details class="compat-row" data-status="ok">
|
|
253
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase(ctx)</code> builds a sandbox-target <code>Database</code>; frozen <code>ctx.auth</code> baked in</span></span></summary>
|
|
254
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("getDatabase(ctx) returns a tagged Database handle")</div></div>
|
|
255
|
+
</details>
|
|
256
|
+
<details class="compat-row" data-status="ok">
|
|
257
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase(sandbox)</code> builds a sandbox-live target; reads <code>sandbox.currentUser</code> per op</span></span></summary>
|
|
258
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("reads sandbox.currentUser at op time, not at getDatabase time")</div></div>
|
|
259
|
+
</details>
|
|
260
|
+
<details class="compat-row" data-status="unsupported">
|
|
261
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior">An in-module production target is intentionally absent; direct calls with a real <code>FirebaseApp</code> reject with package-resolution guidance</span></span></summary>
|
|
262
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular.test.ts</code>; production remains the responsibility of the unchanged <code>firebase/database</code> package</div></div>
|
|
263
|
+
</details>
|
|
264
|
+
<details class="compat-row" data-status="ok">
|
|
265
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>ref(db, path?)</code> returns a path-tagged <code>DatabaseReference</code>; default is root</span></span></summary>
|
|
266
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("ref(db) returns a root ref" + "ref(db, ...) returns a path ref")</div></div>
|
|
267
|
+
</details>
|
|
268
|
+
<details class="compat-row" data-status="ok">
|
|
269
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>child(ref, 'sub/path')</code> composes paths; result inherits the parent's target</span></span></summary>
|
|
270
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("child(ref, 'sub') composes paths")</div></div>
|
|
271
|
+
</details>
|
|
272
|
+
<details class="compat-row" data-status="ok">
|
|
273
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>ref.parent</code> returns the parent ref; <code>root.parent === null</code></span></span></summary>
|
|
274
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("ref.parent returns the parent ref; root.parent is null")</div></div>
|
|
275
|
+
</details>
|
|
276
|
+
<details class="compat-row" data-status="ok">
|
|
277
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>ref.root</code> returns the root ref of the same target</span></span></summary>
|
|
278
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("ref.root returns the root ref")</div></div>
|
|
279
|
+
</details>
|
|
280
|
+
<details class="compat-row" data-status="ok">
|
|
281
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>get(ref)</code> returns a <code>DataSnapshot</code>-shaped object with <code>val()</code>, <code>exists()</code>, <code>key</code>, <code>child()</code>, <code>hasChildren()</code>, <code>numChildren()</code>, <code>toJSON()</code></span></span></summary>
|
|
282
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> (snapshot shape tests)</div></div>
|
|
283
|
+
</details>
|
|
284
|
+
<details class="compat-row" data-status="ok">
|
|
285
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>get</code> on an absent path resolves to <code>{ val: null, exists: false }</code> (matches <code>DataSnapshot.val()</code> contract)</span></span></summary>
|
|
286
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("reads return null for an absent path")</div></div>
|
|
287
|
+
</details>
|
|
288
|
+
<details class="compat-row" data-status="ok">
|
|
289
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>set(ref, value)</code> replaces the value at the path</span></span></summary>
|
|
290
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("round-trips a primitive value" + "round-trips nested objects"); matches oracle observation <code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
|
|
291
|
+
</details>
|
|
292
|
+
<details class="compat-row" data-status="ok">
|
|
293
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>set(ref, null)</code> deletes the subtree at the path</span></span></summary>
|
|
294
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("set(ref, null) deletes the path"); matches oracle observation <code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></div></div>
|
|
295
|
+
</details>
|
|
296
|
+
<details class="compat-row" data-status="ok">
|
|
297
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>remove(ref)</code> is equivalent to <code>set(ref, null)</code> (same end state)</span></span></summary>
|
|
298
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("remove and set(null) produce identical end-state"); matches oracle observation <code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></div></div>
|
|
299
|
+
</details>
|
|
300
|
+
<details class="compat-row" data-status="ok">
|
|
301
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>update(ref, patch)</code> shallow-merges top-level keys at the ref's path</span></span></summary>
|
|
302
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("shallow-merges top-level keys")</div></div>
|
|
303
|
+
</details>
|
|
304
|
+
<details class="compat-row" data-status="ok">
|
|
305
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>null</code> value in a shallow update deletes that key</span></span></summary>
|
|
306
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("null values in a shallow update delete the key")</div></div>
|
|
307
|
+
</details>
|
|
308
|
+
<details class="compat-row" data-status="ok">
|
|
309
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>update(rootRef, { '/a/x': v1, '/b/y': v2 })</code> is a multi-path atomic write — all paths land or none do</span></span></summary>
|
|
310
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:upstream-rtdb-probes.test.ts</code> ("one update nulls, mutates, and displaces within a limitToFirst window") + <code>unit:modular/sandbox-target.test.ts</code> (atomic multipath + rules denial); matches the matrix #23 prod contract</div></div>
|
|
311
|
+
</details>
|
|
312
|
+
<details class="compat-row" data-status="ok">
|
|
313
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Overlapping multi-path updates (one path is a descendant of another) reject before any path is written</span></span></summary>
|
|
314
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("rejects overlapping paths")</div></div>
|
|
315
|
+
</details>
|
|
316
|
+
<details class="compat-row" data-status="ok">
|
|
317
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref)</code> mints a 20-char auto-id key starting with <code>-</code>, lexicographically sortable</span></span></summary>
|
|
318
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("mints 20-char keys starting with \"-\"" + "sequential push keys are lex-sortable"); matches oracle observation <code>packages/conformance/observations/rtdb/rtdb-push-autoid-format.json</code></div></div>
|
|
319
|
+
</details>
|
|
320
|
+
<details class="compat-row" data-status="ok">
|
|
321
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref, value)</code> writes <code>value</code> at the new child path</span></span></summary>
|
|
322
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("push(ref, value) writes the value at the new child path")</div></div>
|
|
323
|
+
</details>
|
|
324
|
+
<details class="compat-row" data-status="ok">
|
|
325
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>pushKey()</code> mints a fresh push-shaped key without writing — used by callers building multi-path updates that need the key first</span></span></summary>
|
|
326
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("pushKey() mints a fresh key without writing")</div></div>
|
|
327
|
+
</details>
|
|
328
|
+
<details class="compat-row" data-status="ok">
|
|
329
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> returns the <code>{ ".sv": "timestamp" }</code> sentinel marker the wire encoder recognises</span></span></summary>
|
|
330
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("serverTimestamp() returns the documented shape"); matches the prod wire contract</div></div>
|
|
331
|
+
</details>
|
|
332
|
+
<details class="compat-row" data-status="ok">
|
|
333
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> resolves to a number (epoch ms) on read-back</span></span></summary>
|
|
334
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("resolves to a number on read-back"); matches oracle observation <code>packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json</code> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
|
|
335
|
+
</details>
|
|
336
|
+
<details class="compat-row" data-status="ok">
|
|
337
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> sentinels resolve when nested inside multi-path update payloads</span></span></summary>
|
|
338
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("resolves sentinels nested deep inside an update payload")</div></div>
|
|
339
|
+
</details>
|
|
340
|
+
<details class="compat-row" data-status="ok">
|
|
341
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied write throws a plain <code>Error</code> (NOT a <code>FirebaseError</code>) with <code>.code === 'PERMISSION_DENIED'</code> (uppercase snake-case) and <code>.message === 'PERMISSION_DENIED: Permission denied'</code></span></span></summary>
|
|
342
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("rules-denied set throws a plain Error with PERMISSION_DENIED code"); matches oracle observation <code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code> (against blockingfun, fb-js-sdk 12.13.0)</div></div>
|
|
343
|
+
</details>
|
|
344
|
+
<details class="compat-row" data-status="ok">
|
|
345
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied read throws the same plain-<code>Error</code> <code>PERMISSION_DENIED</code> shape as a denied write</span></span></summary>
|
|
346
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("rules-denied get throws the same plain Error shape"); matches oracle observation <code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></div></div>
|
|
347
|
+
</details>
|
|
348
|
+
<details class="compat-row" data-status="ok">
|
|
349
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied remove throws the same plain-<code>Error</code> <code>PERMISSION_DENIED</code> shape</span></span></summary>
|
|
350
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-target.test.ts</code> ("rules-denied remove throws the same plain Error shape")</div></div>
|
|
351
|
+
</details>
|
|
352
|
+
<details class="compat-row" data-status="ok">
|
|
353
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue(ref, cb)</code> fires immediately on subscribe with the current value at the path</span></span></summary>
|
|
354
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("fires on subscribe with the current value")</div></div>
|
|
355
|
+
</details>
|
|
356
|
+
<details class="compat-row" data-status="ok">
|
|
357
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue</code> fires again after every write that CHANGES the value at the watched path; a write that leaves the watched subtree byte-identical (a no-change re-write, or an ancestor/descendant write that doesn't alter this path) is suppressed (DB-B8)</span></span></summary>
|
|
358
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("fires after every write that touches the watched path") + <code>unit:modular/no-change-suppression.test.ts</code> ("re-writing the same value does NOT re-fire" + "ancestor write leaving the subtree unchanged does NOT fire")</div></div>
|
|
359
|
+
</details>
|
|
360
|
+
<details class="compat-row" data-status="ok">
|
|
361
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue</code> fires after a descendant write (the listener sees subtree changes)</span></span></summary>
|
|
362
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("fires on a descendant write")</div></div>
|
|
363
|
+
</details>
|
|
364
|
+
<details class="compat-row" data-status="ok">
|
|
365
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue</code> initial-fire for an absent path delivers <code>val=null, exists=false</code> (matches matrix expectation locked by oracle for sentinel/listener shape)</span></span></summary>
|
|
366
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("absent path: initial fire delivers val=null, exists=false")</div></div>
|
|
367
|
+
</details>
|
|
368
|
+
<details class="compat-row" data-status="ok">
|
|
369
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The <code>onValue</code> return value is an unsubscribe function; calling it stops further fires</span></span></summary>
|
|
370
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("fires after every write that touches the watched path" — checks unsubscribed listener doesn't fire on subsequent write)</div></div>
|
|
371
|
+
</details>
|
|
372
|
+
<details class="compat-row" data-status="ok">
|
|
373
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildAdded</code> / <code>onChildChanged</code> / <code>onChildRemoved</code> / <code>onChildMoved</code> — plain-ref subscription surface</span></span></summary>
|
|
374
|
+
<div class="compat-evidence"><div class="compat-probe">Tier 2: sandbox aligned with oracle observations under <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchild*.json</code>. See M41–M48 for the per-event behavioral claims.</div></div>
|
|
375
|
+
</details>
|
|
376
|
+
<details class="compat-row" data-status="ok">
|
|
377
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildAdded</code> replays each existing direct child of the parent ref on subscribe (one fire per existing key)</span></span></summary>
|
|
378
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-child-events.test.ts</code> ("replays existing direct children on subscribe — one fire per key"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-initial-replay.json</code> (seeded <code>{k1,k2,k3}</code>, observed <code>firedKeys: ['k1','k2','k3']</code>).</div></div>
|
|
379
|
+
</details>
|
|
380
|
+
<details class="compat-row" data-status="ok">
|
|
381
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">After subscribe, <code>onChildAdded</code> fires exactly once per new direct child write; snapshot carries <code>{key, val}</code> of the new child</span></span></summary>
|
|
382
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-child-events.test.ts</code> ("fires exactly once per NEW direct child after subscribe"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-post-subscribe.json</code> (<code>postSubscribeFires: 1</code>, <code>lastFire: {key:'k3', val:{v:3}}</code>).</div></div>
|
|
383
|
+
</details>
|
|
384
|
+
<details class="compat-row" data-status="ok">
|
|
385
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildChanged</code> has NO initial replay; fires once when an existing direct child's value transitions; snapshot carries the NEW value</span></span></summary>
|
|
386
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-child-events.test.ts</code> ("does NOT fire on subscribe (no initial replay)" + "fires once when an existing child transitions to a new value; snapshot carries NEW val"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildchanged-fires-on-update.json</code> (<code>firedOnInitial: 0, firedOnUpdate: 1, lastFire: {key:'k1', val:{v:2}}</code>).</div></div>
|
|
387
|
+
</details>
|
|
388
|
+
<details class="compat-row" data-status="ok">
|
|
389
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildChanged</code> does NOT fire for added or removed children — those go to the other event listeners</span></span></summary>
|
|
390
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-child-events.test.ts</code> ("does NOT fire when a child is added" + "does NOT fire when a child is removed").</div></div>
|
|
391
|
+
</details>
|
|
392
|
+
<details class="compat-row" data-status="ok">
|
|
393
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildRemoved</code> has NO initial replay; fires once when a direct child is deleted (via <code>remove(child)</code> or <code>set(child, null)</code>); snapshot carries the PRIOR (now-removed) value</span></span></summary>
|
|
394
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:upstream-rtdb-probes.test.ts</code> (parent wipe fan-out via remove(parent) / set(parent, scalar)) + <code>unit:modular/sandbox-child-events.test.ts</code> (single-child delete carries PRIOR val); matches oracle <code>rtdb-modular-onchildremoved-fires-on-delete.json</code></div></div>
|
|
395
|
+
</details>
|
|
396
|
+
<details class="compat-row" data-status="ok">
|
|
397
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildMoved</code> on a plain ref (no <code>query(_, orderBy*)</code>) NEVER fires — per RTDB docs, child_moved emits only under ordered queries</span></span></summary>
|
|
398
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-child-events.test.ts</code> ("does NOT fire on a plain ref (no ordering)"); matches the upstream contract observed under ordered-query in <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildmoved-with-orderby.json</code> (where ordered-query did fire — Tier 3 will wire that path; Tier 2 locks the plain-ref no-fire case).</div></div>
|
|
399
|
+
</details>
|
|
400
|
+
<details class="compat-row" data-status="ok">
|
|
401
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(ref)</code> (no event type) removes ALL listeners at that ref — value + every child event variety</span></span></summary>
|
|
402
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-child-events.test.ts</code> ("off(ref) removes ALL listeners at the ref" + "off(ref) also removes value listeners at the same path"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-off-stops-child-fires.json</code> (<code>postOffFires: 0</code>).</div></div>
|
|
403
|
+
</details>
|
|
404
|
+
<details class="compat-row" data-status="ok">
|
|
405
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(ref, eventType?, callback?)</code> variants: <code>off(ref, 'value')</code> / <code>off(ref, 'child_added')</code> / <code>off(ref, eventType, cb)</code> remove the targeted subset; returned-unsubscribe from <code>onChild*</code> is equivalent to <code>off(ref, eventType, cb)</code></span></span></summary>
|
|
406
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/sandbox-child-events.test.ts</code> ("off(ref, \"child_added\") removes only that event variety" + "off(ref, \"value\") removes only value listeners" + "off(ref, eventType, cb) removes only the matching callback" + "returned-unsubscribe from onChildAdded is functionally equivalent to off()").</div></div>
|
|
407
|
+
</details>
|
|
408
|
+
<details class="compat-row" data-status="ok">
|
|
409
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>connectDatabaseEmulator(db, host, port)</code> is a no-op on sandbox targets (the sandbox IS a local emulator)</span></span></summary>
|
|
410
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("is a no-op on sandbox handles")</div></div>
|
|
411
|
+
</details>
|
|
412
|
+
<details class="compat-row" data-status="ok">
|
|
413
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.setRules(db, rulesJson)</code> deploys rules to the in-process simulator; <code>setRules(db, null)</code> clears rules (default-allow)</span></span></summary>
|
|
414
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("sandbox.setRules(db, null) clears rules")</div></div>
|
|
415
|
+
</details>
|
|
416
|
+
<details class="compat-row" data-status="ok">
|
|
417
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.setData(db, { '/path': value })</code> bulk-loads data, bypassing rules</span></span></summary>
|
|
418
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("sandbox.setData seeds the tree (rule-bypass)")</div></div>
|
|
419
|
+
</details>
|
|
420
|
+
<details class="compat-row" data-status="ok">
|
|
421
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.snapshotState(db)</code> dumps the full tree as a plain JSON object</span></span></summary>
|
|
422
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("sandbox.snapshotState dumps the full tree")</div></div>
|
|
423
|
+
</details>
|
|
424
|
+
<details class="compat-row" data-status="ok">
|
|
425
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query(ref, ...constraints)</code> + ordering/range constraints</span></span></summary>
|
|
426
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:upstream-rtdb-probes.test.ts</code> ("orderByChild('a/b') + limitToFirst orders by the nested path") + <code>unit:modular/queries.test.ts</code> + oracle observations under <code>packages/conformance/observations/rtdb-modular/</code>; see M49–M64 for the per-claim breakdown.</div></div>
|
|
427
|
+
</details>
|
|
428
|
+
<details class="compat-row" data-status="ok">
|
|
429
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>runTransaction(ref, fn, options?)</code> resolves to <code>{ committed: boolean, snapshot: DataSnapshot }</code> for the happy path — the update fn return value is written, committed is <code>true</code>, and <code>snapshot.val()</code> reflects the committed value</span></span></summary>
|
|
430
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/transaction.test.ts</code> ("resolves to { committed: boolean, snapshot } with the committed value"); matches oracle observations <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json</code> + <code>rtdb-modular-runtransaction-returns-committed-snapshot.json</code> (against blockingfun, fb-js-sdk 12.13.0)</div></div>
|
|
431
|
+
</details>
|
|
432
|
+
<details class="compat-row" data-status="ok">
|
|
433
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Returning <code>undefined</code> from the update fn ABORTS the transaction — resolves <code>{ committed: false, snapshot }</code>; no write performed, no listener fan-out</span></span></summary>
|
|
434
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/transaction.test.ts</code> ("returning undefined aborts — committed: false, no write" + "aborted transaction does NOT fan out to listeners"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-abort-undefined.json</code> — known divergence: prod's <code>result.snapshot.val()</code> reflects the CLIENT's pre-fetch (often <code>null</code> even when the server has a value because the speculative invocation runs before the server snap arrives); the sandbox returns the actual pre-transaction value at the path (more useful in single-client harness). The agreed-upon contract callers should rely on is <code>committed === false</code> and unchanged server-side data, NOT the snapshot's <code>.val()</code> on the abort path.</div></div>
|
|
435
|
+
</details>
|
|
436
|
+
<details class="compat-row" data-status="ok">
|
|
437
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The update fn receives the CURRENT value at the ref's path; for an absent path the argument is <code>null</code> (NOT <code>undefined</code>)</span></span></summary>
|
|
438
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/transaction.test.ts</code> ("update fn receives null for an absent path" + "update fn receives the existing value for a seeded path"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-current-value-arg.json</code> (prod observation showed <code>missingArgs[0].isNull === true</code>) — note divergence: prod ALSO speculatively calls the fn with <code>null</code> for a seeded path before the server-snap arrives, the sandbox skips that speculative call (single invocation with the real current value)</div></div>
|
|
439
|
+
</details>
|
|
440
|
+
<details class="compat-row" data-status="ok">
|
|
441
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The update fn arg is a defensive deep clone — mutating it does NOT corrupt the stored tree (matters for code that does <code>current.count++; return undefined</code> and expects abort to preserve state)</span></span></summary>
|
|
442
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/transaction.test.ts</code> ("mutating the update-fn arg does NOT corrupt the stored tree") — no separate oracle row (defensive contract; prod behavior is identical because the SDK clones on the wire boundary)</div></div>
|
|
443
|
+
</details>
|
|
444
|
+
<details class="compat-row" data-status="ok">
|
|
445
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>options.applyLocally</code> controls whether the in-flight optimistic value fans out to <code>onValue</code> listeners — default <code>true</code> (apply locally before commit); <code>false</code> suppresses intermediate fires so listeners see only the committed value</span></span></summary>
|
|
446
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/transaction.test.ts</code> ("applyLocally: true (default) — listener sees initial + committed value" + "applyLocally: false — listener sees only the committed value"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-options-applylocally.json</code> (single-client harness: both branches produce 2 fires (initial + commit) — divergence vs prod's documented multi-client suppression would surface under contention, which the sandbox doesn't model)</div></div>
|
|
447
|
+
</details>
|
|
448
|
+
<details class="compat-row" data-status="ok">
|
|
449
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied transaction rejects with a plain <code>Error</code> whose <code>message === 'permission_denied'</code> (lowercase) and NO <code>.code</code> field — DIFFERENT from <code>set</code>/<code>get</code>'s <code>'PERMISSION_DENIED: Permission denied'</code> shape with uppercase <code>.code</code>.</span></span></summary>
|
|
450
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/transaction.test.ts</code> ("rejects with a plain Error whose message is \"permission_denied\""); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-on-rules-denied-path.json</code> (against blockingfun: <code>message: 'permission_denied', code: null, constructorName: 'Error'</code>).</div></div>
|
|
451
|
+
</details>
|
|
452
|
+
<details class="compat-row" data-status="ok">
|
|
453
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied transaction does NOT write — pre-transaction value at the path is preserved through the rejection</span></span></summary>
|
|
454
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/transaction.test.ts</code> ("does not write to the path when rules deny") — locked alongside the M37e shape claim</div></div>
|
|
455
|
+
</details>
|
|
456
|
+
<details class="compat-row" data-status="ok">
|
|
457
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Committed transaction fans out to <code>onValue</code> listeners on the watched path with the new value (default applyLocally behavior)</span></span></summary>
|
|
458
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/transaction.test.ts</code> ("committed write fans out to onValue listeners")</div></div>
|
|
459
|
+
</details>
|
|
460
|
+
<details class="compat-row" data-status="unsupported">
|
|
461
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior">Concurrent contention / retry-on-conflict — single-client sandbox doesn't model real concurrency; the documented "up to 25 retries" contract is degenerate (the fn is invoked once)</span></span></summary>
|
|
462
|
+
<div class="compat-evidence"><div class="compat-probe">matrix #161 documents the same gap on the spec side; oracle observation hard to obtain from a single client (oracle row stays <code>?</code>)</div></div>
|
|
463
|
+
</details>
|
|
464
|
+
<details class="compat-row" data-status="ok">
|
|
465
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Identity-aware sandbox-live op routing — sign-in/sign-out via <code>pyric/auth</code> is observed by the next RTDB op without re-binding</span></span></summary>
|
|
466
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> ("reads sandbox.currentUser at op time, not at getDatabase time")</div></div>
|
|
467
|
+
</details>
|
|
468
|
+
<details class="compat-row" data-status="ok">
|
|
469
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Backend identity is per-<code>Sandbox</code> — two <code>getDatabase(sandbox)</code> calls on the same sandbox share data, two on different sandboxes don't</span></span></summary>
|
|
470
|
+
<div class="compat-evidence"><div class="compat-probe">implicit via the WeakMap binding; tested transitively by <code>sandbox.setData</code> + <code>get</code> round-trips in the same test suite</div></div>
|
|
471
|
+
</details>
|
|
472
|
+
<details class="compat-row" data-status="ok">
|
|
473
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Sandbox refs carry a stable <code>key</code> (last path segment) and <code>toString()</code> returning <code>sandbox://rtdb/<path></code></span></span></summary>
|
|
474
|
+
<div class="compat-evidence"><div class="compat-probe">covered by the <code>ref</code> / <code>child</code> / <code>parent</code> tests</div></div>
|
|
475
|
+
</details>
|
|
476
|
+
<details class="compat-row" data-status="ok">
|
|
477
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query(ref, orderByChild(p), startAt(v), endAt(w))</code> window is BOTH-INCLUSIVE — children whose ordered field === <code>v</code> or === <code>w</code> are included</span></span></summary>
|
|
478
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:upstream-rtdb-probes.test.ts</code> (deep orderByChild nested path) + <code>unit:modular/queries.test.ts</code> ("returns children whose ordered child is within [startAt, endAt] inclusive"); matches oracle <code>rtdb-modular-orderbychild-window.json</code></div></div>
|
|
479
|
+
</details>
|
|
480
|
+
<details class="compat-row" data-status="ok">
|
|
481
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByKey()</code> orders children by RTDB <code>nameCompare</code> — integer-looking keys sort numerically FIRST (so <code>['1','2','10']</code>, not the lexicographic <code>['1','10','2']</code>), then non-integer keys lexicographically; <code>startAt</code>/<code>endAt</code> cursors + the optional <code>key</code> tie-breaker use the same order (DB-B4)</span></span></summary>
|
|
482
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:upstream-rtdb-probes.test.ts</code> (INT32 overflow/underflow cursors) + <code>unit:modular/queries.test.ts</code> + <code>unit:modular/name-compare.test.ts</code>; matches oracle <code>rtdb-modular-orderbykey-window.json</code> and upstream <code>core/util/util.ts:253-276</code></div></div>
|
|
483
|
+
</details>
|
|
484
|
+
<details class="compat-row" data-status="ok">
|
|
485
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByValue()</code> orders primitive children by their value; <code>limitToFirst(N)</code> returns the N smallest, ascending</span></span></summary>
|
|
486
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/queries.test.ts</code> ("returns the limitToFirst(N) smallest values, ascending"). Oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-orderbyvalue-numeric.json</code> shows prod threw <code>Index not defined</code> against blockingfun — the sandbox does NOT enforce <code>.indexOn</code> (rules-engine integration for query indexes is deferred); the semantic claim (ordering by value) is locked here.</div></div>
|
|
487
|
+
</details>
|
|
488
|
+
<details class="compat-row" data-status="ok">
|
|
489
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByChild(p) + equalTo(v)</code> returns ALL children whose field at <code>p</code> === <code>v</code> — no uniqueness enforced</span></span></summary>
|
|
490
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/queries.test.ts</code> ("returns ALL children whose ordered field === the supplied value"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-equalTo-filter.json</code> (both 'b'-grouped children returned).</div></div>
|
|
491
|
+
</details>
|
|
492
|
+
<details class="compat-row" data-status="ok">
|
|
493
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>equalTo</code> with no matches returns an empty snapshot (<code>exists() === false</code>, <code>numChildren() === 0</code>)</span></span></summary>
|
|
494
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("returns an empty snapshot when nothing matches")</div></div>
|
|
495
|
+
</details>
|
|
496
|
+
<details class="compat-row" data-status="ok">
|
|
497
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToFirst(N)</code> keeps the lowest-ranked N children (post-ordering, pre-filter)</span></span></summary>
|
|
498
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/queries.test.ts</code> ("limitToFirst takes the lowest-ranked window"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code> (firstPositions <code>[1,2]</code>).</div></div>
|
|
499
|
+
</details>
|
|
500
|
+
<details class="compat-row" data-status="ok">
|
|
501
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToLast(N)</code> keeps the highest-ranked N children</span></span></summary>
|
|
502
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/queries.test.ts</code> ("limitToLast takes the highest-ranked window"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code> (lastPositions <code>[4,5]</code>).</div></div>
|
|
503
|
+
</details>
|
|
504
|
+
<details class="compat-row" data-status="ok">
|
|
505
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToFirst(N)</code> larger than the result returns the full window (no padding, no throw)</span></span></summary>
|
|
506
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("limitToFirst(N) larger than the result returns the full window")</div></div>
|
|
507
|
+
</details>
|
|
508
|
+
<details class="compat-row" data-status="ok">
|
|
509
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>startAfter(v)</code> and <code>endBefore(v)</code> are EXCLUSIVE — the boundary value is dropped from the result</span></span></summary>
|
|
510
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/queries.test.ts</code> ("startAfter + endBefore drop the boundary values"); matches oracle observation <code>packages/conformance/observations/rtdb-modular/rtdb-modular-startafter-endbefore-exclusive.json</code> (positions <code>[3,4]</code>, cursors 2 + 5 dropped).</div></div>
|
|
511
|
+
</details>
|
|
512
|
+
<details class="compat-row" data-status="ok">
|
|
513
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue(query, cb)</code> only fires when the windowed result changes — writes OUTSIDE the window don't re-fire the listener; writes that displace a member DO</span></span></summary>
|
|
514
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:upstream-rtdb-probes.test.ts</code> ("one update nulls, mutates, and displaces within a limitToFirst window") + <code>unit:modular/queries.test.ts</code> ("fires only when the windowed result changes"); matches oracle <code>rtdb-modular-onvalue-with-query.json</code></div></div>
|
|
515
|
+
</details>
|
|
516
|
+
<details class="compat-row" data-status="ok">
|
|
517
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue(query)</code> initial fire delivers an empty window (<code>numChildren() === 0</code>) when the path is absent</span></span></summary>
|
|
518
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("initial fire on an empty path delivers an empty window")</div></div>
|
|
519
|
+
</details>
|
|
520
|
+
<details class="compat-row" data-status="ok">
|
|
521
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query(query(ref, c1), c2)</code> composes constraints — chaining folds both into one spec</span></span></summary>
|
|
522
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("query(query(ref, c1), c2) composes constraints")</div></div>
|
|
523
|
+
</details>
|
|
524
|
+
<details class="compat-row" data-status="ok">
|
|
525
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Snapshot from a query exposes children via <code>snap.forEach</code> in the executor-computed order — NOT necessarily the order <code>Object.entries(val)</code> would yield</span></span></summary>
|
|
526
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("forEach visits children in ascending order of the child key")</div></div>
|
|
527
|
+
</details>
|
|
528
|
+
<details class="compat-row" data-status="ok">
|
|
529
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>startAt(value, key)</code> uses <code>key</code> as the tie-breaker when multiple children share the same ordered value — children before <code>key</code> are dropped, the row at <code>key</code> is included (inclusive cursor)</span></span></summary>
|
|
530
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("startAt with key tie-breaker drops earlier same-value children")</div></div>
|
|
531
|
+
</details>
|
|
532
|
+
<details class="compat-row" data-status="ok">
|
|
533
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByChild('p')</code> on children missing the field treats their value as <code>null</code> (sorts FIRST per RTDB's type ordering)</span></span></summary>
|
|
534
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("orderByChild on a missing child path treats those children as null")</div></div>
|
|
535
|
+
</details>
|
|
536
|
+
<details class="compat-row" data-status="ok">
|
|
537
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query</code> on a path holding a primitive (or absent path) returns an empty snapshot — no rows to iterate</span></span></summary>
|
|
538
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/queries.test.ts</code> ("query on a path with primitive value returns no rows")</div></div>
|
|
539
|
+
</details>
|
|
540
|
+
<details class="compat-row" data-status="ok">
|
|
541
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Write-boundary normalization (<code>nodeFromJSON</code>-equivalent): a value written as an array is stored as an integer-keyed object — <code>child(ref, '1')</code> returns the element, <code>forEach</code> iterates <code>0,1,2…</code> (DB-B2)</span></span></summary>
|
|
542
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/normalization.test.ts</code> ("array write is addressable by integer-string child key" + "forEach over an array iterates its elements"); upstream <code>core/snap/nodeFromJSON.ts:118-128</code>, <code>core/snap/ChildrenNode.ts:194-230</code></div></div>
|
|
543
|
+
</details>
|
|
544
|
+
<details class="compat-row" data-status="ok">
|
|
545
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Read-side array coercion: a dense integer-keyed object renders back as an array on <code>snap.val()</code> (<code>allIntegerKeys && maxKey < 2 * numKeys</code>) (DB-B2)</span></span></summary>
|
|
546
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/normalization.test.ts</code> ("a dense integer-keyed object reads back as an array"); upstream <code>core/snap/ChildrenNode.ts:196-230</code></div></div>
|
|
547
|
+
</details>
|
|
548
|
+
<details class="compat-row" data-status="ok">
|
|
549
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>null</code> children and empty objects are pruned at the write boundary — <code>set(ref, {})</code> is equivalent to <code>remove(ref)</code>; nested <code>null</code> collapses empty ancestors ("empty nodes don't exist") (DB-B3)</span></span></summary>
|
|
550
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/normalization.test.ts</code> ("set(ref, {}) is equivalent to remove" + "null children are pruned"); upstream <code>core/snap/nodeFromJSON.ts:78-88,122-126</code></div></div>
|
|
551
|
+
</details>
|
|
552
|
+
<details class="compat-row" data-status="ok">
|
|
553
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Write validation: an <code>undefined</code> payload, a non-finite number (<code>NaN</code>/<code>±Infinity</code>), or a key containing a forbidden char (<code>.</code>, <code>#</code>, <code>$</code>, <code>/</code>, <code>[</code>, <code>]</code>, control chars) is rejected with a plain <code>Error</code> (DB-B1)</span></span></summary>
|
|
554
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/normalization.test.ts</code> ("rejects an undefined payload" + "rejects an invalid key" + "rejects a non-finite number"); upstream <code>core/util/validation.ts:45,58,112-199</code></div></div>
|
|
555
|
+
</details>
|
|
556
|
+
<details class="compat-row" data-status="ok">
|
|
557
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Conflicting query constraints throw synchronously at <code>query(...)</code> construction (NOT silent last-win): multiple <code>orderBy*</code>, a second <code>limitToFirst</code>/<code>limitToLast</code>, a second start (<code>startAt</code>/<code>startAfter</code>/<code>equalTo</code>) or end (<code>endAt</code>/<code>endBefore</code>/<code>equalTo</code>) (DB-B5)</span></span></summary>
|
|
558
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/constraint-conflicts.test.ts</code> (5 cases); upstream <code>api/Reference_impl.ts:160-165,1824-1841,1888-1905,1945-1951,2193-2206</code></div></div>
|
|
559
|
+
</details>
|
|
560
|
+
<details class="compat-row" data-status="ok">
|
|
561
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref, value?)</code> returns a <code>ThenableReference</code> (a <code>DatabaseReference</code> with <code>.then</code>/<code>.catch</code>). The key + ref are minted CLIENT-SIDE and available synchronously even when the optional value write is rules-denied; the write is deferred onto the promise, so a denial REJECTS the awaited push rather than throwing synchronously and discarding the key (DB-B7)</span></span></summary>
|
|
562
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/push-thenable.test.ts</code> (4 cases); matches oracle <code>packages/conformance/observations/rtdb/rtdb-push-autoid-format.json</code> ("available immediately even when the subsequent server write is denied by rules") + upstream <code>api/Reference_impl.ts:599-630</code></div></div>
|
|
563
|
+
</details>
|
|
564
|
+
<details class="compat-row" data-status="ok">
|
|
565
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>DataSnapshot</code> shape: <code>size</code> (getter), <code>priority</code> (always <code>null</code> — priority deny-listed), <code>exportVal()</code>, <code>key</code>, <code>ref</code>, <code>val()</code>, <code>exists()</code>, <code>child()</code>, <code>hasChild()</code>, <code>hasChildren()</code>, <code>forEach()</code>, <code>toJSON()</code>. It does NOT ship the legacy namespaced <code>numChildren()</code> method (DB-B10)</span></span></summary>
|
|
566
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/snapshot-shape.test.ts</code> ("exposes size/priority/exportVal; NOT numChildren()"); matches oracle <code>packages/conformance/observations/rtdb-modular/rtdb-modular-get-snapshot-shape.json</code> (<code>hasSize: true, hasNumChildren: false</code>) + upstream <code>api/Reference_impl.ts:288-447</code>. <strong>Flipped masking tests</strong>: <code>modular/queries.test.ts</code> + <code>modular/sandbox-target.test.ts</code> asserted <code>snap.numChildren()</code> — updated to <code>snap.size</code>.</div></div>
|
|
567
|
+
</details>
|
|
568
|
+
<details class="compat-row" data-status="ok">
|
|
569
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Object-valued children are ORDER-EQUAL — the sort/range tie is broken by key (<code>nameCompare</code>), NOT by an invented <code>JSON.stringify</code> ordering; a query re-write that only reorders object keys is "no change" and doesn't re-fire (DB-B11)</span></span></summary>
|
|
570
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/object-order-equality.test.ts</code>; upstream <code>core/snap/ChildrenNode.ts:386-400</code></div></div>
|
|
571
|
+
</details>
|
|
572
|
+
<details class="compat-row" data-status="ok">
|
|
573
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">A primitive at the ROOT is legal (<code>set(ref(db), 'hello')</code>); a subsequent child write replaces the primitive root ("writes win") (DB-B13)</span></span></summary>
|
|
574
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/root-primitive.test.ts</code> (2 cases)</div></div>
|
|
575
|
+
</details>
|
|
576
|
+
<details class="compat-row" data-status="ok">
|
|
577
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue(ref, cb, { onlyOnce: true })</code> fires once then auto-unsubscribes (DB-B12)</span></span></summary>
|
|
578
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/onvalue-onlyonce.test.ts</code>; upstream <code>api/Reference_impl.ts:975-980</code></div></div>
|
|
579
|
+
</details>
|
|
580
|
+
<details class="compat-row" data-status="diverged">
|
|
581
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><strong>Divergence (DB-B12, honest doc):</strong> the onChild<em> callbacks do NOT receive the <code>previousChildName</code> second argument; <code>onValue</code>/<code>onChild</em></code> do NOT accept a <code>cancelCallback</code>; <code>onChildAdded</code>/<code>Changed</code>/<code>Removed</code>/<code>Moved</code> accept only plain refs (not <code>Query</code>); <code>child_moved</code> never fires (ordered-query move detection unmodeled). These listener-surface holes are out of scope for the current phase — consumers needing them use <code>firebase/database</code> directly.</span></span></summary>
|
|
582
|
+
<div class="compat-evidence"><div class="compat-probe">divergence documented; partial coverage: <code>{ onlyOnce }</code> IS implemented (M74).</div></div>
|
|
583
|
+
</details>
|
|
584
|
+
<details class="compat-row" data-status="ok">
|
|
585
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>.validate</code> rules are enforced on modular sandbox writes through <code>set</code>, atomic <code>update</code>, and <code>runTransaction</code>; a descendant validation failure rejects the operation without changing state.</span></span></summary>
|
|
586
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/sandbox-target.test.ts</code> executes all three write paths against a required-child <code>.validate</code> rule and proves each rejects without committing state. The shared <code>SimulateHandler</code> behavior is production-locked by RTDB rules corpus rows #4 and #15.</div></div>
|
|
587
|
+
</details>
|
|
588
|
+
</div>
|
|
589
|
+
|
|
590
|
+
### Deferred mirror behaviors
|
|
591
|
+
|
|
592
|
+
- Ordered-query `onChildMoved` is accepted but does not yet fire on reorder.
|
|
593
|
+
- `onDisconnect` has no in-process socket lifecycle to model yet.
|
|
594
|
+
- Priority ordering is not modeled.
|
|
595
|
+
|
|
596
|
+
The playground and `pyric dev` map canonical `firebase/database` imports to `pyric/database` before the mirror loads. A bare preview `getDatabase()` call is wrapped to receive the active sandbox. Production bundling leaves `firebase/database` unchanged.
|
|
597
|
+
|
|
598
|
+
Simulation and structure crawling are sandbox/CLI operations; rules authoring and analysis remain on the internal RTDB rules-engine seam until their later package relocation.
|
|
599
|
+
|
|
600
|
+
---
|
|
601
|
+
|
|
602
|
+
### `getDatabase(target)` — initializer
|
|
603
|
+
|
|
604
|
+
<div class="compat-list">
|
|
605
|
+
<details class="compat-row" data-status="unsupported">
|
|
606
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase(ctx)</code> returns a tagged sandbox-target handle (frozen identity)</span></span></summary>
|
|
607
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3</div></div>
|
|
608
|
+
</details>
|
|
609
|
+
<details class="compat-row" data-status="unsupported">
|
|
610
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase(sandbox)</code> returns a tagged sandbox-live handle (per-op identity)</span></span></summary>
|
|
611
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3</div></div>
|
|
612
|
+
</details>
|
|
613
|
+
<details class="compat-row" data-status="unverified">
|
|
614
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior">Inactive canonical <code>firebase/database</code> imports remain the upstream package; the mirror does not create tagged production targets</span></span></summary>
|
|
615
|
+
<div class="compat-evidence"><div class="compat-probe">package-resolution boundary; inactive RTDB canonical-import isolation is not yet claimed by this row</div></div>
|
|
616
|
+
</details>
|
|
617
|
+
<details class="compat-row" data-status="ok">
|
|
618
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase()</code> (no argument) — wrapped in the playground preview to supply the sandbox; a raw mirror call rejects with package-resolution guidance</span></span></summary>
|
|
619
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3 Tier 5: virtualized in the playground preview scope. Wired at <code>packages/playground/src/components/AppPreview.tsx</code> (slot install with bare-call wrap), <code>packages/playground/src/lib/preview/virtual-imports-plugin.ts</code> (alias map), and <code>packages/playground/src/lib/preview/preview-scope.ts</code> (type-level slot). Mirrors the <code>getAuth</code> / <code>getFirestore</code> wrap pattern. Demo fixture: <code>packages/playground/scripts/fixtures/rtdb-set-get-roundtrip.tsx</code> (bare <code>getDatabase()</code> + <code>set</code>/<code>get</code>/<code>remove</code> round-trip with anonymous sign-in) passes end-to-end through the <code>bun run debug:fixtures</code> Playwright suite.</div>
|
|
620
|
+
<div class="compat-note">(wrap, fixture passing)</div></div>
|
|
621
|
+
</details>
|
|
622
|
+
<details class="compat-row" data-status="unsupported">
|
|
623
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior">Two <code>getDatabase(sandbox)</code> calls share state (same underlying <code>LocalEnvironment</code>)</span></span></summary>
|
|
624
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3</div></div>
|
|
625
|
+
</details>
|
|
626
|
+
<details class="compat-row" data-status="unsupported">
|
|
627
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior">Handle dispatch by <code>TARGET_SYMBOL</code> brand — refs route to their owning target via a <code>refToTarget</code> WeakMap (mirror of firestore's pattern)</span></span></summary>
|
|
628
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3</div></div>
|
|
629
|
+
</details>
|
|
630
|
+
</div>
|
|
631
|
+
|
|
632
|
+
### `ref(db, path)` / `child` / `parent` / `root`
|
|
633
|
+
|
|
634
|
+
<div class="compat-list">
|
|
635
|
+
<details class="compat-row" data-status="unverified">
|
|
636
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior"><code>ref(db, path)</code> returns a tagged <code>DatabaseReference</code> carrying <code>key</code>, <code>parent</code>, <code>root</code>, <code>toString()</code></span></span></summary>
|
|
637
|
+
<div class="compat-evidence"><div class="compat-probe">upstream <code>firebase/database</code> contract</div></div>
|
|
638
|
+
</details>
|
|
639
|
+
<details class="compat-row" data-status="unverified">
|
|
640
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior"><code>ref(db)</code> with no path returns the root ref (<code>key === null</code>, <code>parent === null</code>)</span></span></summary>
|
|
641
|
+
<div class="compat-evidence"><div class="compat-probe">upstream contract</div></div>
|
|
642
|
+
</details>
|
|
643
|
+
<details class="compat-row" data-status="unverified">
|
|
644
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior"><code>child(ref, 'a/b')</code> joins a relative path, including embedded slashes</span></span></summary>
|
|
645
|
+
<div class="compat-evidence"><div class="compat-probe">upstream contract</div></div>
|
|
646
|
+
</details>
|
|
647
|
+
<details class="compat-row" data-status="unverified">
|
|
648
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior"><code>ref.parent</code> is <code>null</code> at root, otherwise the parent ref</span></span></summary>
|
|
649
|
+
<div class="compat-evidence"><div class="compat-probe">upstream contract</div></div>
|
|
650
|
+
</details>
|
|
651
|
+
<details class="compat-row" data-status="unverified">
|
|
652
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior"><code>ref.key</code> is the final path segment, <code>null</code> for root</span></span></summary>
|
|
653
|
+
<div class="compat-evidence"><div class="compat-probe">upstream contract</div></div>
|
|
654
|
+
</details>
|
|
655
|
+
<details class="compat-row" data-status="unsupported">
|
|
656
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior">Unknown ref (not produced by this package) → <code>TypeError</code> in shim ops</span></span></summary>
|
|
657
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3</div></div>
|
|
658
|
+
</details>
|
|
659
|
+
</div>
|
|
660
|
+
|
|
661
|
+
### `get(ref)` — single read
|
|
662
|
+
|
|
663
|
+
<div class="compat-list">
|
|
664
|
+
<details class="compat-row" data-status="ok">
|
|
665
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Returns a <code>DataSnapshot</code> carrying <code>.val()</code>, <code>.exists()</code>, <code>.key</code>, <code>.ref</code>, <code>.size</code> (getter, returns child count), <code>.hasChildren()</code>, <code>.hasChild(path)</code>, <code>.forEach(cb)</code>. The legacy namespaced-SDK method <code>.numChildren()</code> is <strong>NOT</strong> on the modular DataSnapshot — use <code>.size</code> instead. Observed: <code>hasNumChildren: false</code>, <code>size: 3</code> for a <code>{a,b,c}</code> object, <code>forEachKeys: ['a','b','c']</code> against blockingfun, fb-js-sdk 12.13.0.</span></span></summary>
|
|
666
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-get-snapshot-shape.json</code></div></div>
|
|
667
|
+
</details>
|
|
668
|
+
<details class="compat-row" data-status="ok">
|
|
669
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>snap.val()</code> returns <code>null</code> for a missing path (NOT a thrown error — RTDB diverges from Firestore here; <code>getDoc</code> returns <code>exists()===false</code> but <code>get</code> on RTDB just returns a <code>null</code>-val snapshot)</span></span></summary>
|
|
670
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-get-missing-path.json</code> — observed <code>threw: false, val: null, exists: false</code> on a never-written path against blockingfun.</div></div>
|
|
671
|
+
</details>
|
|
672
|
+
<details class="compat-row" data-status="ok">
|
|
673
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>snap.exists()</code> is <code>false</code> when <code>val() === null</code>, <code>true</code> otherwise</span></span></summary>
|
|
674
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-get-missing-path.json</code> — observed <code>exists: false</code> for <code>val: null</code>.</div></div>
|
|
675
|
+
</details>
|
|
676
|
+
<details class="compat-row" data-status="ok">
|
|
677
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Round-trip: <code>set(ref, payload)</code> then <code>get(ref)</code> returns the payload (lock the basic write→read invariant)</span></span></summary>
|
|
678
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code> — the payload round-trips structurally on both sides (this row's claim holds). NOTE — adjacent divergence pinned in <code>oracle-conformance.test.ts</code>: prod returns object children in LEXICOGRAPHIC key order (the capture's <code>roundTripEqual: false</code> — a <code>JSON.stringify</code> round-trip against a non-sorted payload fails), while the sandbox preserves insertion order (stringify round-trip succeeds). Key-order-sensitive consumers behave differently.</div></div>
|
|
679
|
+
</details>
|
|
680
|
+
<details class="compat-row" data-status="ok">
|
|
681
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied read throws a plain <code>Error</code> (NOT a <code>FirebaseError</code>) with <code>code: 'PERMISSION_DENIED'</code> (uppercase snake-case) — matches the agent-tool rows #15/#20</span></span></summary>
|
|
682
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></div></div>
|
|
683
|
+
</details>
|
|
684
|
+
</div>
|
|
685
|
+
|
|
686
|
+
### `set(ref, value)` — full write
|
|
687
|
+
|
|
688
|
+
<div class="compat-list">
|
|
689
|
+
<details class="compat-row" data-status="unverified">
|
|
690
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior">Replaces the value at the path entirely; resolves to <code>undefined</code> (unlike <code>setDoc</code> which resolves to <code>void</code>, RTDB's <code>set</code> is documented as <code>Promise<void></code>)</span></span></summary>
|
|
691
|
+
<div class="compat-evidence"><div class="compat-probe">upstream contract</div></div>
|
|
692
|
+
</details>
|
|
693
|
+
<details class="compat-row" data-status="ok">
|
|
694
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>set(ref, null)</code> removes the path entirely — equivalent to <code>remove(ref)</code>, subsequent <code>get</code> returns <code>null</code>-val snapshot</span></span></summary>
|
|
695
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-set-null-equals-remove.json</code> — observed <code>beforeExists: true → afterExists: false, afterVal: null</code> after <code>set(ref, null)</code>.</div></div>
|
|
696
|
+
</details>
|
|
697
|
+
<details class="compat-row" data-status="ok">
|
|
698
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Nested objects overwrite — <code>set(ref, {a: 1})</code> after <code>set(ref, {a: 1, b: 2})</code> leaves <code>{a: 1}</code> only, NOT a merge (RTDB <code>set</code> is replacement, not merge)</span></span></summary>
|
|
699
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-set-replaces-not-merges.json</code> — observed <code>final: {a: 1}</code> with <code>b</code> absent after the second set.</div></div>
|
|
700
|
+
</details>
|
|
701
|
+
<details class="compat-row" data-status="ok">
|
|
702
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Primitive round-trip — numbers, strings, booleans, arrays all survive a set→get cycle</span></span></summary>
|
|
703
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code> — the payload round-trips structurally on both sides (this row's claim holds). NOTE — adjacent divergence pinned in <code>oracle-conformance.test.ts</code>: prod returns object children in LEXICOGRAPHIC key order (the capture's <code>roundTripEqual: false</code> — a <code>JSON.stringify</code> round-trip against a non-sorted payload fails), while the sandbox preserves insertion order (stringify round-trip succeeds). Key-order-sensitive consumers behave differently.</div></div>
|
|
704
|
+
</details>
|
|
705
|
+
<details class="compat-row" data-status="ok">
|
|
706
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied write throws plain <code>Error</code> with <code>code: 'PERMISSION_DENIED'</code> (same shape as #110)</span></span></summary>
|
|
707
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></div></div>
|
|
708
|
+
</details>
|
|
709
|
+
</div>
|
|
710
|
+
|
|
711
|
+
### `update(ref, values)` — partial / multi-path update
|
|
712
|
+
|
|
713
|
+
<div class="compat-list">
|
|
714
|
+
<details class="compat-row" data-status="ok">
|
|
715
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>update(ref, {a: 1, b: 2})</code> merges top-level keys at the ref; unspecified keys preserved (in contrast to <code>set</code>'s replacement)</span></span></summary>
|
|
716
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-update-merges-keys.json</code> — after <code>set({a:1,b:2})</code> then <code>update({a:10})</code>, observed <code>final: {a:10, b:2}</code>.</div></div>
|
|
717
|
+
</details>
|
|
718
|
+
<details class="compat-row" data-status="ok">
|
|
719
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Multi-path update — <code>update(parentRef, { 'a/x': 1, 'b/y': 2 })</code> lands BOTH writes atomically at distinct subtrees (RTDB's most distinctive feature; this is the "fan-out" pattern)</span></span></summary>
|
|
720
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-update-multipath-atomic.json</code> — observed <code>aX: 1, bY: 2</code> both readable after a single update call.</div></div>
|
|
721
|
+
</details>
|
|
722
|
+
<details class="compat-row" data-status="ok">
|
|
723
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Multi-path update is atomic: if any path is denied by rules, the entire update rejects and no path is written</span></span></summary>
|
|
724
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-update-multipath-rules-denial.json</code> — observed <code>threw: true, code: 'PERMISSION_DENIED'</code> AND <code>okPathWrittenDespiteDenial: false</code> (the otherwise-permitted path also rolled back).</div></div>
|
|
725
|
+
</details>
|
|
726
|
+
<details class="compat-row" data-status="ok">
|
|
727
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Setting a key to <code>null</code> inside <code>update</code> removes that key — same equivalence as <code>set(ref, null)</code></span></span></summary>
|
|
728
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-update-null-removes-key.json</code> — after <code>set({a:1,b:2})</code> then <code>update({a:null})</code>, observed <code>final: {b:2}</code> with <code>a</code> absent.</div></div>
|
|
729
|
+
</details>
|
|
730
|
+
<details class="compat-row" data-status="unverified">
|
|
731
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior">Update path validation — overlapping paths (e.g. <code>'/a'</code> and <code>'/a/x'</code> in the same call) throws synchronously before any write</span></span></summary>
|
|
732
|
+
<div class="compat-evidence"><div class="compat-probe">upstream contract — needs targeted probe</div></div>
|
|
733
|
+
</details>
|
|
734
|
+
</div>
|
|
735
|
+
|
|
736
|
+
### `remove(ref)` — delete
|
|
737
|
+
|
|
738
|
+
<div class="compat-list">
|
|
739
|
+
<details class="compat-row" data-status="ok">
|
|
740
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Removes the value AND all children; subsequent <code>get</code> returns <code>null</code>-val snapshot</span></span></summary>
|
|
741
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></div></div>
|
|
742
|
+
</details>
|
|
743
|
+
<details class="compat-row" data-status="ok">
|
|
744
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Idempotent — <code>remove</code> on a path that's already absent resolves successfully (no-throw)</span></span></summary>
|
|
745
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-remove-idempotent.json</code> — <code>remove</code> on a never-written path observed <code>threw: false, afterExists: false</code>.</div></div>
|
|
746
|
+
</details>
|
|
747
|
+
<details class="compat-row" data-status="ok">
|
|
748
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>remove(ref)</code> and <code>set(ref, null)</code> produce the same end state — locks the documented RTDB invariant</span></span></summary>
|
|
749
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></div></div>
|
|
750
|
+
</details>
|
|
751
|
+
</div>
|
|
752
|
+
|
|
753
|
+
### `push(ref, value?)` — auto-id append
|
|
754
|
+
|
|
755
|
+
<div class="compat-list">
|
|
756
|
+
<details class="compat-row" data-status="ok">
|
|
757
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref).key</code> is a 20-char string starting with <code>-</code>, available <strong>synchronously</strong> (client-side mint, no server round-trip required)</span></span></summary>
|
|
758
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-push-autoid-format.json</code></div></div>
|
|
759
|
+
</details>
|
|
760
|
+
<details class="compat-row" data-status="ok">
|
|
761
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Sequential <code>push</code> calls produce monotonically-sortable keys (timestamp-prefixed for chronological ordering via <code>orderByKey</code>)</span></span></summary>
|
|
762
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-push-autoid-format.json</code></div></div>
|
|
763
|
+
</details>
|
|
764
|
+
<details class="compat-row" data-status="ok">
|
|
765
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref, value)</code> writes the value AND returns the new child ref (both behaviors in one call); <code>push(ref)</code> mints the ref without writing</span></span></summary>
|
|
766
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-push-with-value.json</code> — <code>await push(parent, {hello:'world'})</code> returned a ref with a 20-char key; subsequent <code>get(r)</code> returned <code>{hello:'world'}</code>.</div></div>
|
|
767
|
+
</details>
|
|
768
|
+
<details class="compat-row" data-status="ok">
|
|
769
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The returned ref <code>r = push(parent, value)</code> is usable in follow-up ops: <code>get(r)</code>, <code>set(r, …)</code>, <code>remove(r)</code></span></span></summary>
|
|
770
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-push-with-value.json</code> — observed all 4 follow-up ops succeed through the returned ref (<code>refIsUsableForFollowupOps: true</code>).</div></div>
|
|
771
|
+
</details>
|
|
772
|
+
</div>
|
|
773
|
+
|
|
774
|
+
### `onValue(ref, cb)` — value-level listener
|
|
775
|
+
|
|
776
|
+
<div class="compat-list">
|
|
777
|
+
<details class="compat-row" data-status="ok">
|
|
778
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Subscribing to a path with <strong>existing data</strong> fires the listener once with the current snapshot (the "initial fire")</span></span></summary>
|
|
779
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onvalue-initial-with-data.json</code> — observed exactly 1 initial fire within ~46ms of subscribe, snapshot.val() === the seeded payload.</div></div>
|
|
780
|
+
</details>
|
|
781
|
+
<details class="compat-row" data-status="ok">
|
|
782
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Subscribing to a <strong>nonexistent path</strong> still fires the listener once — with a <code>null</code>-val snapshot AND <code>exists() === false</code>. Matches Firestore's <code>onSnapshot</code>-on-missing-doc semantics: prod RTDB does NOT silently skip the initial fire for empty paths.</span></span></summary>
|
|
783
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onvalue-initial-no-data.json</code> — observed 1 initial fire on a never-written path with <code>firstFire.val: null, firstFire.exists: false</code> (~55ms after subscribe).</div></div>
|
|
784
|
+
</details>
|
|
785
|
+
<details class="compat-row" data-status="ok">
|
|
786
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Subsequent <code>set(ref, …)</code> fires the listener with the new value</span></span></summary>
|
|
787
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-onvalue-fires-on-set.json</code> — observed 1 fire per <code>set()</code> (1+1+1 = 3 total: initial-null, after-first-set, after-second-set).</div></div>
|
|
788
|
+
</details>
|
|
789
|
+
<details class="compat-row" data-status="ok">
|
|
790
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Unsubscribe — the returned unsubscribe function stops further fires; subsequent writes produce 0 additional fires after <code>unsub()</code></span></span></summary>
|
|
791
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onvalue-unsubscribe.json</code> — observed <code>preUnsubFires: 2, postUnsubFires: 2</code> (a write performed after <code>unsub()</code> produced 0 additional fires within a 500ms settle window).</div></div>
|
|
792
|
+
</details>
|
|
793
|
+
<details class="compat-row" data-status="unverified">
|
|
794
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior">The returned value from <code>onValue(ref, cb)</code> is the unsubscribe function (NOT an object); calling it removes the listener</span></span></summary>
|
|
795
|
+
<div class="compat-evidence"><div class="compat-probe">upstream contract — locked indirectly by #131</div></div>
|
|
796
|
+
</details>
|
|
797
|
+
</div>
|
|
798
|
+
|
|
799
|
+
### `onChildAdded` / `onChildChanged` / `onChildRemoved` / `onChildMoved`
|
|
800
|
+
|
|
801
|
+
<div class="compat-list">
|
|
802
|
+
<details class="compat-row" data-status="ok">
|
|
803
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildAdded</code> replays the existing children on subscribe — one fire per existing child key, in <code>orderByKey</code> order by default (unlike <code>onValue</code> which fires once with the parent snapshot)</span></span></summary>
|
|
804
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-initial-replay.json</code> — seeded <code>{k1, k2, k3}</code>, observed 3 initial fires with <code>firedKeys: ['k1', 'k2', 'k3']</code> in insertion order against blockingfun.</div></div>
|
|
805
|
+
</details>
|
|
806
|
+
<details class="compat-row" data-status="ok">
|
|
807
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">After subscribe, adding a child via <code>push</code> or <code>set(child, …)</code> fires <code>onChildAdded</code> exactly once for that key</span></span></summary>
|
|
808
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-post-subscribe.json</code> — seeded <code>{k1,k2}</code>, observed <code>postSubscribeFires: 1, lastFire: {key:'k3', val:{v:3}}</code> after writing the new child.</div></div>
|
|
809
|
+
</details>
|
|
810
|
+
<details class="compat-row" data-status="ok">
|
|
811
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildChanged</code> fires when an existing child's value changes; does NOT fire for added or removed children</span></span></summary>
|
|
812
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildchanged-fires-on-update.json</code> — observed <code>firedOnInitial: 0, firedOnUpdate: 1, lastFire: {key:'k1', val:{v:2}}</code> (the NEW value, not the prior).</div></div>
|
|
813
|
+
</details>
|
|
814
|
+
<details class="compat-row" data-status="ok">
|
|
815
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildRemoved</code> fires when a child is deleted (via <code>remove(child)</code> or <code>set(child, null)</code>); snapshot carries the PRIOR value</span></span></summary>
|
|
816
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildremoved-fires-on-delete.json</code> — observed <code>firedOnDelete: 1, removedSnapCarriesPriorValue: true</code> (snapshot.val() was the pre-delete value).</div></div>
|
|
817
|
+
</details>
|
|
818
|
+
<details class="compat-row" data-status="diverged">
|
|
819
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><code>onChildMoved</code> under an ordered query. Prod: fires when a child's <code>orderByChild</code>/<code>orderByValue</code> priority changes — emitted only on ordered queries. Sandbox: <strong>never fires on reorder</strong> — <code>onChildMoved</code> supports the plain-ref (no-fire) case only; the ordered-query overload is unimplemented</span></span></summary>
|
|
820
|
+
<div class="compat-evidence"><div class="compat-probe">divergence, oracle-locked by <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildmoved-with-orderby.json</code>: prod observed <code>firedOnMove: 1</code> under <code>query(ref, orderByChild('priority'))</code> after bumping a child's priority to a new sort position; the sandbox fires 0 on reorder. Partial alignment landed: all <code>onChild*</code> now ACCEPT a <code>Query</code> (previously threw a misleading <code>unrecognized reference</code> TypeError) with window-aware <code>child_added</code>/<code>child_changed</code>/<code>child_removed</code> diffs (<code>src/database/sandbox/backend.ts</code>); the two hold-lifting captures now exist: <code>rtdb-modular-onchildmoved-previouschildname-sequencing</code> pins prev-name sequencing (end/middle/front reorders yield prev k3/k2/null, no initial replay) and <code>rtdb-modular-childchanged-cofire-with-childmoved</code> pins co-fire semantics (a reorder fires BOTH <code>child_changed</code> and <code>child_moved</code>; a non-ordered-field change fires neither moved; prod fires <code>child_moved</code> on an ordered-field value change EVEN WHEN RANK IS UNCHANGED). Implementation of ordered <code>child_moved</code> is unblocked. Both sides pinned in <code>modular/oracle-conformance.test.ts</code> and <code>modular/sandbox-child-events.test.ts</code>. Sandbox Tier 2 locks the plain-ref no-fire case (M46).</div></div>
|
|
821
|
+
</details>
|
|
822
|
+
</div>
|
|
823
|
+
|
|
824
|
+
### `off(ref, eventType?, callback?)` — unsubscribe variants
|
|
825
|
+
|
|
826
|
+
<div class="compat-list">
|
|
827
|
+
<details class="compat-row" data-status="ok">
|
|
828
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(ref)</code> removes ALL listeners at that ref (any event type, any callback)</span></span></summary>
|
|
829
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-off-stops-child-fires.json</code> — after <code>off(ref)</code> with no eventType, a subsequent write produced <code>postOffFires: 0</code> against an <code>onChildAdded</code> registration.</div></div>
|
|
830
|
+
</details>
|
|
831
|
+
<details class="compat-row" data-status="ok">
|
|
832
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(ref, 'value')</code> removes only <code>value</code> listeners at that ref</span></span></summary>
|
|
833
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned (M48); oracle: <code>packages/conformance/observations/rtdb/rtdb-off-eventtype-precision.json</code> — registered TWO <code>value</code> listeners + one <code>child_added</code> at the same ref; after <code>off(ref, 'value')</code> (no callback), <code>valueListenersStopped: true</code> (neither value cb fired on subsequent writes) AND <code>childListenerStillFiringAfterOffValue: true</code> (the child listener kept firing). <code>offValueClearsAllValueListeners: true</code> confirms the no-callback variant removes ALL value listeners at the ref.</div></div>
|
|
834
|
+
</details>
|
|
835
|
+
<details class="compat-row" data-status="ok">
|
|
836
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(ref, 'value', cb)</code> removes only the specific callback</span></span></summary>
|
|
837
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned (M48); adjacent to #141 — the upstream <code>off</code> with the cb argument removes only the matching callback. Same probe (<code>rtdb-onvalue-unsub-equivalence.json</code> Case 2) confirms <code>off(ref, 'value', cb)</code> stops only that callback.</div></div>
|
|
838
|
+
</details>
|
|
839
|
+
<details class="compat-row" data-status="ok">
|
|
840
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The returned unsubscribe function from <code>onValue(ref, cb)</code> is equivalent to <code>off(ref, 'value', cb)</code></span></span></summary>
|
|
841
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned (M48); oracle: <code>packages/conformance/observations/rtdb/rtdb-onvalue-unsub-equivalence.json</code> — <code>unsubReturnType: 'function'</code>, <code>unsubReturnedFnStopsListener: true</code> (the captured return value halted fires on write), <code>offRefValueCbStopsListener: true</code> (the same effect via <code>off(ref, 'value', cb)</code>), <code>bothFormsEquivalent: true</code>.</div></div>
|
|
842
|
+
</details>
|
|
843
|
+
<details class="compat-row" data-status="unverified">
|
|
844
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><code class="compat-api">off(ref, eventType, callback)</code><span class="compat-sub"><span class="compat-behavior">When the same callback is registered more than once, each <code>off(ref, eventType, callback)</code> removes one registration without orphaning the others</span></span></span></summary>
|
|
845
|
+
<div class="compat-evidence"><div class="compat-probe">Pyric behavior is locked by <code>packages/pyric/test/app/multi-app-listener-auth.test.ts</code>; a production duplicate-registration oracle capture is still needed</div></div>
|
|
846
|
+
</details>
|
|
847
|
+
</div>
|
|
848
|
+
|
|
849
|
+
### `query(ref, ...constraints)` + ordering / bounds / limits
|
|
850
|
+
|
|
851
|
+
<div class="compat-list">
|
|
852
|
+
<details class="compat-row" data-status="ok">
|
|
853
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query(ref, orderByChild('field'), limitToFirst(N))</code> returns a <code>Query</code> whose <code>get()</code> resolves a snapshot containing N children ordered by <code>field</code></span></span></summary>
|
|
854
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-query-orderbychild-limit.json</code> — seeded 4 children with positions <code>[3,1,4,2]</code>, observed <code>orderedKeys: [{key:'a',pos:1}, {key:'b',pos:2}]</code> (first 2 in ascending order). Requires <code>.indexOn</code> declared in rules.</div></div>
|
|
855
|
+
</details>
|
|
856
|
+
<details class="compat-row" data-status="ok">
|
|
857
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByKey()</code> orders by the auto-id / numeric key</span></span></summary>
|
|
858
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-orderbykey-window.json</code> — seeded <code>{a,b,c,d,e}</code> in shuffled insertion order, observed <code>matchedKeys: ['b','c','d']</code> for <code>orderByKey() + startAt('b') + endAt('d')</code> (in key order).</div></div>
|
|
859
|
+
</details>
|
|
860
|
+
<details class="compat-row" data-status="ok">
|
|
861
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByValue()</code> orders by the primitive value of each child (for collections of primitives)</span></span></summary>
|
|
862
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-orderbyvalue-numeric.json</code> — seeded <code>{alice:30, bob:10, carol:50, dave:20, eve:40}</code>, the prod call threw <code>Index not defined, add ".indexOn": ".value"</code> (so prod enforces an index requirement on <code>orderByValue()</code>); semantic ordering claim still holds, sandbox does not enforce indexes.</div></div>
|
|
863
|
+
</details>
|
|
864
|
+
<details class="compat-row" data-status="ok">
|
|
865
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>equalTo(v)</code> filters children whose ordered field === v (returns 0, 1, or multiple matches — RTDB does NOT enforce uniqueness)</span></span></summary>
|
|
866
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-query-equalto.json</code> — seeded <code>{red, blue, blue, green}</code>, observed <code>matchedKeys: ['k2', 'k3']</code> for <code>equalTo('blue')</code> (both blue children, none of the others). Additional probe: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-equalTo-filter.json</code> (a..b..c groups) confirms <code>equalTo('b')</code> returns the two <code>b</code> children.</div></div>
|
|
867
|
+
</details>
|
|
868
|
+
<details class="compat-row" data-status="ok">
|
|
869
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>startAt(v)</code> is <strong>inclusive</strong> (the child whose ordered value === v is included)</span></span></summary>
|
|
870
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-query-startat-inclusive.json</code> — seeded positions <code>[1,2,3,4]</code>, observed <code>matched: [2,3,4]</code> for <code>startAt(2)</code> (cursor doc included).</div></div>
|
|
871
|
+
</details>
|
|
872
|
+
<details class="compat-row" data-status="ok">
|
|
873
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>endAt(v)</code> is <strong>inclusive</strong></span></span></summary>
|
|
874
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-orderbychild-window.json</code> — <code>startAt(2) + endAt(4)</code> matched positions <code>[2,3,4]</code> (endAt(4) included its boundary value).</div></div>
|
|
875
|
+
</details>
|
|
876
|
+
<details class="compat-row" data-status="ok">
|
|
877
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>startAfter(v)</code> is <strong>exclusive</strong></span></span></summary>
|
|
878
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-startafter-endbefore-exclusive.json</code> — <code>startAfter(2) + endBefore(5)</code> matched positions <code>[3,4]</code> (cursor <code>2</code> dropped).</div></div>
|
|
879
|
+
</details>
|
|
880
|
+
<details class="compat-row" data-status="ok">
|
|
881
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>endBefore(v)</code> is <strong>exclusive</strong></span></span></summary>
|
|
882
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-startafter-endbefore-exclusive.json</code> — same probe; cursor <code>5</code> dropped.</div></div>
|
|
883
|
+
</details>
|
|
884
|
+
<details class="compat-row" data-status="ok">
|
|
885
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToFirst(N)</code> caps the result count from the start of the ordered range</span></span></summary>
|
|
886
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-query-orderbychild-limit.json</code> plus <code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code> (firstPositions <code>[1,2]</code>).</div></div>
|
|
887
|
+
</details>
|
|
888
|
+
<details class="compat-row" data-status="ok">
|
|
889
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToLast(N)</code> caps from the end</span></span></summary>
|
|
890
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code> — observed <code>lastKeys: ['d','e'], lastPositions: [4,5]</code> for <code>limitToLast(2)</code> on a 5-child collection ordered by <code>pos</code>.</div></div>
|
|
891
|
+
</details>
|
|
892
|
+
<details class="compat-row" data-status="ok">
|
|
893
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Listeners on a <code>Query</code> (<code>onValue(q, …)</code>) emit only the windowed snapshot — NOT the parent ref's full data</span></span></summary>
|
|
894
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-onvalue-with-query.json</code> — seeded 3 children, watched first 2 by <code>pos</code>; observed 3 fires total: (1) initial <code>[a,b]</code>, (2) OUTSIDE-window write to <code>c/extra</code> did NOT fire, (3) INSIDE-window mutation of <code>a</code> re-fired, (4) new child <code>z</code> displaced <code>b</code> and re-fired. Outside-window writes are silent.</div></div>
|
|
895
|
+
</details>
|
|
896
|
+
</div>
|
|
897
|
+
|
|
898
|
+
### Sentinels — `serverTimestamp()` / `increment(n)`
|
|
899
|
+
|
|
900
|
+
<div class="compat-list">
|
|
901
|
+
<details class="compat-row" data-status="ok">
|
|
902
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> resolves server-side to a <strong>number</strong> (epoch milliseconds) — diverges from Firestore's <code>Timestamp</code> instance</span></span></summary>
|
|
903
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json</code> — observed <code>createdAtType: 'number', createdAt: 1779075391118</code> (i.e. a plain JS number, NOT a <code>Timestamp</code> object).</div></div>
|
|
904
|
+
</details>
|
|
905
|
+
<details class="compat-row" data-status="ok">
|
|
906
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> as a field value in <code>set</code> or <code>update</code> writes the <code>{".sv": "timestamp"}</code> sentinel; the read-back value is the resolved number</span></span></summary>
|
|
907
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json</code> — read-back showed <code>createdAtSentinelShape: false</code> (sentinel resolved server-side; client sees the number, not the <code>.sv</code> placeholder).</div></div>
|
|
908
|
+
</details>
|
|
909
|
+
<details class="compat-row" data-status="ok">
|
|
910
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>increment(n)</code> against a <strong>missing</strong> field starts at 0 (so <code>increment(5)</code> lands as <code>5</code>)</span></span></summary>
|
|
911
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned (modular <code>increment</code> export now present): <code>unit:modular/increment.test.ts</code> ("increment against a missing field starts from 0"); matches oracle <code>packages/conformance/observations/rtdb-modular/rtdb-modular-increment-from-missing.json</code> — observed <code>afterFirst: 5</code> from <code>increment(5)</code> against an absent <code>count</code> field.</div></div>
|
|
912
|
+
</details>
|
|
913
|
+
<details class="compat-row" data-status="ok">
|
|
914
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>increment(n)</code> against an existing numeric field adds atomically; negative deltas subtract</span></span></summary>
|
|
915
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <code>unit:modular/increment.test.ts</code> ("subsequent increments accumulate (positive then negative)" + "nested inside an update patch resolves per-field"); matches oracle <code>packages/conformance/observations/rtdb-modular/rtdb-modular-increment-from-missing.json</code> — observed <code>afterSecond: 8</code> (5+3) then <code>afterNegative: 6</code> (8-2).</div></div>
|
|
916
|
+
</details>
|
|
917
|
+
<details class="compat-row" data-status="unverified">
|
|
918
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior">Two concurrent <code>increment</code> calls interleave correctly (last-write-wins is NOT the contract — both deltas accumulate)</span></span></summary>
|
|
919
|
+
<div class="compat-evidence"><div class="compat-probe">hard to observe deterministically from a single client; documented contract</div></div>
|
|
920
|
+
</details>
|
|
921
|
+
</div>
|
|
922
|
+
|
|
923
|
+
### `runTransaction(ref, transactionUpdate, options?)` — optimistic concurrency
|
|
924
|
+
|
|
925
|
+
<div class="compat-list">
|
|
926
|
+
<details class="compat-row" data-status="ok">
|
|
927
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Basic success — <code>runTransaction(ref, current => (current ?? 0) + 1)</code> resolves <code>{ committed: true, snapshot }</code> where <code>snapshot.val()</code> is the new value</span></span></summary>
|
|
928
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json</code> — observed <code>committed: true, snapVal: 1</code> after running <code>current => (current ?? 0) + 1</code> against an empty ref.</div></div>
|
|
929
|
+
</details>
|
|
930
|
+
<details class="compat-row" data-status="ok">
|
|
931
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Returning <code>undefined</code> from the update fn <strong>aborts</strong> the transaction — resolves <code>{ committed: false }</code>, no write performed (RTDB-specific; distinct from Firestore where the only abort path is throwing)</span></span></summary>
|
|
932
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-abort-undefined.json</code> — seeded <code>100</code> then transaction returned <code>undefined</code>; observed <code>committed: false, snapVal: null, afterValOnServer: 100</code> (existing value preserved).</div></div>
|
|
933
|
+
</details>
|
|
934
|
+
<details class="compat-row" data-status="ok">
|
|
935
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The update fn is called with the CURRENT server value (may be <code>null</code> if the ref is empty); the fn's return value is the proposed new value</span></span></summary>
|
|
936
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json</code> — observed <code>seenCurrentValues: [null]</code> on first invocation against an empty ref (a single call, no speculative re-runs against <code>undefined</code>). NOTE — adjacent divergence pinned in <code>modular/oracle-conformance.test.ts</code>: for a SEEDED path, prod speculatively invokes the update fn twice (first with <code>null</code>, then the real value; <code>rtdb-modular-runtransaction-current-value-arg.json</code> <code>seededArgs.length: 2</code>) while the sandbox invokes once with the actual value. The argument-semantics claim of this row holds for the effective invocation on both sides. WARNING for update-fn authors: prod may invoke your fn first with <code>null</code> even when data exists — the pattern <code>if (current === null) return;</code> (abort-on-empty) silently loses writes on prod while working on the sandbox, and side effects inside the fn can run twice on prod. RESOLVED by the warm-client capture <code>rtdb-modular-runtransaction-warm-client-speculation</code>: a warm prod client (active listener + prior get) receives a SINGLE invocation with the cached value, exactly matching the sandbox. The cold-cache speculative double-call is an artifact of an empty client cache, which the always-warm in-process sandbox structurally never has; the sandbox behavior IS the warm-client contract.</div></div>
|
|
937
|
+
</details>
|
|
938
|
+
<details class="compat-row" data-status="unverified">
|
|
939
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unverified" role="img" aria-label="Unverified" title="Unverified"></span><span class="compat-main"><span class="compat-behavior">Concurrent contention — if another client writes between the read and write, the update fn is retried with the new current value (typically up to 25 retries by default)</span></span></summary>
|
|
940
|
+
<div class="compat-evidence"><div class="compat-probe">hard to observe deterministically from a single client</div></div>
|
|
941
|
+
</details>
|
|
942
|
+
<details class="compat-row" data-status="ok">
|
|
943
|
+
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Result snapshot's <code>.val()</code> reflects the committed value (or the existing value if aborted)</span></span></summary>
|
|
944
|
+
<div class="compat-evidence"><div class="compat-probe">oracle: <code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json</code> — observed <code>snapVal: 1</code> matching the committed value.</div></div>
|
|
945
|
+
</details>
|
|
946
|
+
</div>
|
|
947
|
+
|
|
948
|
+
### `goOnline` / `goOffline` — connection control
|
|
949
|
+
|
|
950
|
+
<div class="compat-list">
|
|
951
|
+
<details class="compat-row" data-status="diverged">
|
|
952
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><code>goOffline(db)</code> — accepted no-op: there is no network connection in the local sandbox to toggle, so nothing is disconnected (we deliberately do NOT simulate a disconnect — pending writes, listeners, and <code>get()</code> keep working)</span></span></summary>
|
|
953
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/fruit-aliases.test.ts</code></div>
|
|
954
|
+
<div class="compat-note">no network connection in the local sandbox to toggle</div></div>
|
|
955
|
+
</details>
|
|
956
|
+
<details class="compat-row" data-status="diverged">
|
|
957
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><code>goOnline(db)</code> — accepted no-op: there is no connection to reopen (see <code>goOffline</code>)</span></span></summary>
|
|
958
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/fruit-aliases.test.ts</code></div>
|
|
959
|
+
<div class="compat-note">no network connection in the local sandbox to toggle</div></div>
|
|
960
|
+
</details>
|
|
961
|
+
</div>
|
|
962
|
+
|
|
963
|
+
### `connectDatabaseEmulator` — emulator hook
|
|
964
|
+
|
|
965
|
+
<div class="compat-list">
|
|
966
|
+
<details class="compat-row" data-status="unsupported">
|
|
967
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior">No-op on sandbox-target handles (the sandbox IS the local emulator)</span></span></summary>
|
|
968
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3</div></div>
|
|
969
|
+
</details>
|
|
970
|
+
<details class="compat-row" data-status="unsupported">
|
|
971
|
+
<summary class="compat-line"><span class="compat-dot" data-status="unsupported" role="img" aria-label="Unsupported" title="Unsupported"></span><span class="compat-main"><span class="compat-behavior">A production target is intentionally absent; production code continues to use <code>connectDatabaseEmulator</code> from the unchanged <code>firebase/database</code> package</span></span></summary>
|
|
972
|
+
<div class="compat-evidence"><div class="compat-probe">Phase 3</div></div>
|
|
973
|
+
</details>
|
|
974
|
+
</div>
|
|
975
|
+
|
|
976
|
+
### Transport, logging, and URL-reference exports
|
|
977
|
+
|
|
978
|
+
<div class="compat-list">
|
|
979
|
+
<details class="compat-row" data-status="diverged">
|
|
980
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><code>forceLongPolling()</code> — accepted no-op: transport selection is not applicable to the in-process/worker sandbox (it never opens a real socket). Accepted so init code that calls it compiles + runs</span></span></summary>
|
|
981
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/fruit-aliases.test.ts</code></div>
|
|
982
|
+
<div class="compat-note">transport selection not applicable to the in-process/worker sandbox</div></div>
|
|
983
|
+
</details>
|
|
984
|
+
<details class="compat-row" data-status="diverged">
|
|
985
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><code>forceWebSockets()</code> — accepted no-op: transport selection is not applicable to the in-process/worker sandbox (see <code>forceLongPolling</code>)</span></span></summary>
|
|
986
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/fruit-aliases.test.ts</code></div>
|
|
987
|
+
<div class="compat-note">transport selection not applicable to the in-process/worker sandbox</div></div>
|
|
988
|
+
</details>
|
|
989
|
+
<details class="compat-row" data-status="diverged">
|
|
990
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><code>enableLogging(logger?, persistent?)</code> — accepted no-op: the sandbox has no modular-SDK-style logger to wire a level/sink into (it uses host-level <code>console</code> logging directly, matching <code>pyric/firestore</code>'s <code>setLogLevel</code>). Accepted so init code that calls it compiles + runs</span></span></summary>
|
|
991
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/fruit-aliases.test.ts</code></div>
|
|
992
|
+
<div class="compat-note">accepted no-op; no sandbox logger to wire into</div></div>
|
|
993
|
+
</details>
|
|
994
|
+
<details class="compat-row" data-status="diverged">
|
|
995
|
+
<summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><code>refFromURL(db, url)</code> — real alias: parses the path out of the absolute database URL and delegates to <code>ref(db, path)</code>, so the returned ref resolves + reads exactly like <code>ref(db, path)</code>. Divergence: the sandbox is single-database with no host/namespace, so the URL's HOST is NOT validated against the handle (the real SDK throws if the host doesn't match the db's namespace); only the path is honored</span></span></summary>
|
|
996
|
+
<div class="compat-evidence"><div class="compat-probe"><code>unit:modular/fruit-aliases.test.ts</code></div>
|
|
997
|
+
<div class="compat-note">path resolves like <code>ref</code>; URL host/namespace not validated (single-database sandbox)</div></div>
|
|
998
|
+
</details>
|
|
999
|
+
</div>
|
|
1000
|
+
|
|
1001
|
+
### Modular SDK surface — deny-list (intentionally NOT shimmed)
|
|
1002
|
+
|
|
1003
|
+
> `goOffline` / `goOnline` / `forceLongPolling` / `forceWebSockets` / `enableLogging` (honest no-ops) and `refFromURL` (a real alias to `ref`) were moved OUT of this deny-list and mirrored — see the tables above.
|
|
1004
|
+
|
|
1005
|
+
| Name | Reason |
|
|
1006
|
+
|---|---|
|
|
1007
|
+
| IndexedDB persistence APIs (the Web SDK's RTDB caches in-memory; there's no `enableIndexedDbPersistence` for RTDB, but if upstream adds one, we deny-list it for sandbox parity with firestore's persistence deny-list) | Persistence is owned by `pyric/sandbox`; the modular SDK's cache APIs would conflict. |
|
|
1008
|
+
| `.info/connected` reads (`onValue(ref(db, '.info/connected'), …)`) | The sandbox has no real connection state to model; firing `true` constantly or never would be a divergence either way. Phase 3 may model this as always-`true` on the sandbox-target. |
|
|
1009
|
+
| `onDisconnect(ref).set(...)` / `.update(...)` / `.remove(...)` / `.cancel()` | Disconnect handlers require a real network channel; the sandbox has no equivalent. Considered for Phase 3 with explicit divergence documentation. NOT exported (no build break — nothing in the shim references it). |
|
|
1010
|
+
| `orderByPriority()` / `setPriority(ref, p)` / `setWithPriority(ref, v, p)` and the whole `.priority` model (DB-B6, DB-GAP) | RTDB's priority model — a per-node `.priority` plus a `PriorityIndex` default ordering — is a cross-cutting data-model concern (every node carries an optional priority; the default child ordering is by priority, not key). Modeling it faithfully touches the tree, the snapshot surface, and every query path; it is not cheap and there is no agent/playground demand. Deny-listed with this note. **Divergence:** the sandbox's default child ordering is `orderByKey` (not priority); `setPriority`/`setWithPriority`/`orderByPriority` are not exported. Consumers needing priority use `firebase/database` directly. |
|
|
1011
|
+
|
|
1012
|
+
---
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
### Modular SDK surface — rows still marked **?** (need explicit probes)
|
|
1017
|
+
|
|
1018
|
+
Rows **locked by the empirical oracle harness** (committed observations under `packages/conformance/observations/`, captured against the `blockingfun` project):
|
|
1019
|
+
|
|
1020
|
+
- #96–#105 — most of the `getDatabase` + `ref` rows are still **?**. These are upstream `firebase/database` shape claims that hold by definition; they'll lift to **✓** when the Phase 3 shim's unit tests cover them.
|
|
1021
|
+
- #111 `set()` return shape (`Promise<void>`) — trivial; first sandbox unit test will lock.
|
|
1022
|
+
- #120 `update()` path-validation errors — same as agent-tool #24.
|
|
1023
|
+
- #132 the unsubscribe return-value shape — locked indirectly by #131 (`unsubStopsFires: true`); a stronger one-claim probe would assert `typeof returnedValue === 'function'`.
|
|
1024
|
+
- #134–#137 `onChildAdded` post-subscribe / `onChildChanged` / `onChildRemoved` / `onChildMoved` — fire-count claims; each needs a probe that mutates the parent after subscribe.
|
|
1025
|
+
- #138–#141 `off(ref, ...)` variants — needs probes that register multiple listeners and verify the correct subset gets removed.
|
|
1026
|
+
- ~~#143 `orderByKey()`, #144 `orderByValue()`, #147 `endAt`, #148 `startAfter`, #149 `endBefore`, #151 `limitToLast`, #152 query-listener windowing~~ — all locked in Phase 3 Tier 3 by 7 new oracle probes (see "Modular SDK surface — Phase 3 Tier 3" below).
|
|
1027
|
+
- #157 concurrent `increment` interleaving — hard to observe from a single client; punt to a 2-client harness if it ever becomes load-bearing.
|
|
1028
|
+
- #161 transaction conflict-retry — same problem; documented contract.
|
|
1029
|
+
|
|
1030
|
+
### Modular SDK surface — rows locked by the empirical oracle harness (Phase 1 output)
|
|
1031
|
+
|
|
1032
|
+
36 oracle observations under `packages/conformance/observations/rtdb-modular/rtdb-modular-*.json` lock the following modular-SDK rows against `blockingfun`, fb-js-sdk 12.13.0 (20 from Phase 1 + 4 transaction probes from Tier 4 + 5 child-event probes from Tier 2 + 7 query probes from Tier 3):
|
|
1033
|
+
|
|
1034
|
+
- #106 `DataSnapshot` shape — `size` is a getter, `numChildren()` is NOT on the modular SDK (was the legacy namespaced API).
|
|
1035
|
+
- #107/#108 `get()` on missing path → `{ val: null, exists: false }`, no throw.
|
|
1036
|
+
- #112 `set(ref, null)` removes the path (subsequent `get` returns `null`).
|
|
1037
|
+
- #113 `set` replaces (NOT merges) at the parent ref.
|
|
1038
|
+
- #116 `update` merges top-level keys; unspecified keys preserved.
|
|
1039
|
+
- #117 multi-path update — `update(parentRef, { 'a/x': 1, 'b/y': 2 })` lands both writes.
|
|
1040
|
+
- #118 multi-path update atomicity — one path denied → entire update rejects, no partial application.
|
|
1041
|
+
- #119 `update` with `null` value removes a key.
|
|
1042
|
+
- #122 `remove` on absent path is idempotent (no-throw).
|
|
1043
|
+
- #126/#127 `push(ref, value)` writes the value AND returns a ref usable for follow-up ops.
|
|
1044
|
+
- #128 `onValue` initial fire with existing data — exactly 1 fire.
|
|
1045
|
+
- #129 `onValue` initial fire on a nonexistent path — fires once with `val: null, exists: false` (matches Firestore semantics; RTDB does NOT silently skip the empty-path initial fire).
|
|
1046
|
+
- #130 `onValue` fires on subsequent `set`.
|
|
1047
|
+
- #131 unsubscribe stops further fires (`postUnsubFires === preUnsubFires`).
|
|
1048
|
+
- #133 `onChildAdded` replays existing children on subscribe — one fire per existing key.
|
|
1049
|
+
- #134 `onChildAdded` post-subscribe — exactly one fire per new direct child write.
|
|
1050
|
+
- #135 `onChildChanged` — no initial replay, fires once when an existing child transitions, snapshot carries the NEW value.
|
|
1051
|
+
- #136 `onChildRemoved` — no initial replay, fires once on delete, snapshot carries the PRIOR (now-removed) value.
|
|
1052
|
+
- #137 `onChildMoved` — fires under ordered queries (`query(ref, orderByChild(...))`) when a child's ordering value moves it to a new sort position; the Tier 2 sandbox locks the plain-ref no-fire case, Tier 3 wires the ordered-query path.
|
|
1053
|
+
- #138/#139 `off(ref)` (no event type) stops further fires — locked against an `onChildAdded` registration; covers the off() variants by extension.
|
|
1054
|
+
- #142/#150 `query(ref, orderByChild('pos'), limitToFirst(2))` returns the first 2 ordered children.
|
|
1055
|
+
- #145 `equalTo(v)` filters to exactly the matching children.
|
|
1056
|
+
- #146 `startAt(v)` is inclusive.
|
|
1057
|
+
- #153/#154 `serverTimestamp()` resolves to a JS `number` (epoch ms), NOT a `Timestamp` instance.
|
|
1058
|
+
- #155/#156 `increment(n)` starts at 0 on missing fields and accumulates (incl. negative deltas).
|
|
1059
|
+
- #158/#160/#162 `runTransaction` happy path — committed: true, snapshot.val() is the new value, update fn sees `null` for empty refs.
|
|
1060
|
+
- #159 `runTransaction` abort by returning `undefined` — committed: false, existing server value preserved.
|
|
1061
|
+
- #160 (extended) `runTransaction` current-value arg shape — `null` for absent paths (`isNull: true`); prod speculatively invokes the fn once with `null` for a seeded path before the server-snap arrives (sandbox skips that speculative call — single invocation with the real current value).
|
|
1062
|
+
- #162 (extended) `runTransaction` result shape — `{ committed: boolean, snapshot: DataSnapshot }`; snapshot responds to `.val()`, `.exists()`, `.key`.
|
|
1063
|
+
- M37d `runTransaction` `options.applyLocally` — both branches commit; single-client harness produces 2 fires (initial + commit) on both, confirming the option doesn't break the contract (the suppression difference would only surface under contention).
|
|
1064
|
+
- M37e `runTransaction` rules-denied error shape — plain `Error`, `message: 'permission_denied'` (lowercase), NO `.code` field — **distinct from `set`/`get`'s `'PERMISSION_DENIED: Permission denied'` shape with uppercase `.code`**.
|
|
1065
|
+
|
|
1066
|
+
### Modular SDK surface — Phase 3 Tier 3 (query semantics) oracle observations
|
|
1067
|
+
|
|
1068
|
+
7 new oracle probes locked the full query-pipeline behavior against `blockingfun`, fb-js-sdk 12.13.0:
|
|
1069
|
+
|
|
1070
|
+
- #142/#146/#147 `rtdb-modular-orderbychild-window.json` — `orderByChild('pos') + startAt(2) + endAt(4)` matched positions `[2,3,4]` (both-inclusive window).
|
|
1071
|
+
- #143/#146/#147 `rtdb-modular-orderbykey-window.json` — `orderByKey() + startAt('b') + endAt('d')` matched keys `[b,c,d]` in key order.
|
|
1072
|
+
- #144/#150 `rtdb-modular-orderbyvalue-numeric.json` — `orderByValue() + limitToFirst(3)` threw `Index not defined, add ".indexOn": ".value"` against blockingfun — prod enforces a value-index requirement. (Sandbox does not enforce indexes; the semantic ordering claim is locked by unit test in `unit:modular/queries.test.ts`.)
|
|
1073
|
+
- #145 `rtdb-modular-equalTo-filter.json` — `orderByChild('group') + equalTo('b')` returned `[k2,k4]` (both 'b'-grouped children); no uniqueness enforced.
|
|
1074
|
+
- #150/#151 `rtdb-modular-limittofirst-vs-limittolast.json` — `limitToFirst(2)` returned `[a,b]` (positions `[1,2]`); `limitToLast(2)` returned `[d,e]` (positions `[4,5]`) on the same 5-child ordered query.
|
|
1075
|
+
- #148/#149 `rtdb-modular-startafter-endbefore-exclusive.json` — `startAfter(2) + endBefore(5)` returned positions `[3,4]` (cursors `2` and `5` dropped — both bounds are EXCLUSIVE).
|
|
1076
|
+
- #152 `rtdb-modular-onvalue-with-query.json` — listener on `query(ref, orderByChild('pos'), limitToFirst(2))` fired 3 times: initial `[a,b]`, then on an INSIDE-window mutation (`a` value change), then when a new child `z` displaced `b`. The OUTSIDE-window write to `c/extra` did NOT fire the listener.
|
|
1077
|
+
|
|
1078
|
+
### Modular SDK surface — implementation status
|
|
1079
|
+
|
|
1080
|
+
The sandbox implementation has landed (`packages/pyric/src/database/modular.ts` + `sandbox/`); rows locked by sandbox unit tests or oracle observations sit at `✓`, and rows still pending implementation sit at `—` (see the per-row tables above for the current status of each). The oracle observations are the spec the sandbox conforms to.
|
|
1081
|
+
|
|
1082
|
+
## Probe coverage summary
|
|
1083
|
+
|
|
1084
|
+
- **Pure rules engine:** compiler, simulator, grammar, and constraints tests under `packages/pyric/test/rules/rtdb/`.
|
|
1085
|
+
- **Modular mirror:** focused tests under `packages/pyric/test/database/modular/` plus frozen `rtdb-modular-*` production observations.
|
|
1086
|
+
- **Archived observations:** legacy `rtdb-*` captures remain immutable historical evidence but no longer contribute rows for the removed production toolkit.
|
|
1087
|
+
|
|
1088
|
+
### Harness extension: `ensureOracleRtdbRules`
|
|
1089
|
+
|
|
1090
|
+
`packages/conformance/src/run.ts` now deploys an RTDB rules namespace
|
|
1091
|
+
analogous to `ensureOracleRules` / `ensureOracleStorageRules`. The
|
|
1092
|
+
JSON shape:
|
|
1093
|
+
|
|
1094
|
+
```json
|
|
1095
|
+
{
|
|
1096
|
+
"rules": {
|
|
1097
|
+
".read": false,
|
|
1098
|
+
".write": false,
|
|
1099
|
+
"pyric_oracle": {
|
|
1100
|
+
".read": "auth != null",
|
|
1101
|
+
".write": "auth != null",
|
|
1102
|
+
"$run": { "$probe": { "list": { ".indexOn": ["pos", "group"] } } }
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
```
|
|
1107
|
+
|
|
1108
|
+
The harness mints a separate OAuth token scoped to
|
|
1109
|
+
`https://www.googleapis.com/auth/firebase.database` (the broader
|
|
1110
|
+
`firebase` scope used by Firestore + Storage + Management APIs is
|
|
1111
|
+
NOT accepted by the per-database rules endpoint) and `PUT`s to
|
|
1112
|
+
`<databaseUrl>/.settings/rules.json?print=silent` with marker-based
|
|
1113
|
+
idempotency: if `pyric_oracle` is already a top-level key AND the
|
|
1114
|
+
shape matches `ORACLE_RTDB_RULES_BODY`, the deploy is a no-op;
|
|
1115
|
+
otherwise the namespace is merged (preserving any other top-level
|
|
1116
|
+
keys) and a 5s propagation wait runs before the probes start. The
|
|
1117
|
+
`.indexOn` inside `$run/$probe/list` is what lets the
|
|
1118
|
+
`orderByChild`/`equalTo`/`startAt` probes run without per-probe
|
|
1119
|
+
rule modifications.
|
|
1120
|
+
|
|
1121
|
+
## Historical simulator-vs-production capture
|
|
1122
|
+
|
|
1123
|
+
The frozen `rtdb-simulator-vs-prod-agreement.json` observation recorded 28 agreements and one historical `.validate` disagreement. The current in-process RTDB rules engine evaluates descendant validation rules on writes; row #71 and the simulator tests cover the repaired behavior without editing the frozen observation.
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
## Current gaps
|
|
1128
|
+
|
|
1129
|
+
### Documented divergences
|
|
1130
|
+
|
|
1131
|
+
Known differences between Pyric and production Firebase. Each remains tracked as a non-conforming row.
|
|
1132
|
+
|
|
1133
|
+
<div class="compat-list compat-list--plain">
|
|
1134
|
+
<div class="compat-row">
|
|
1135
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub">Cross-path <code>root.child(…).val()</code> reads return <code>null</code> for paths NOT present in <code>mockData</code> — divergence from real prod rules where the engine reads the live database</span></span></div>
|
|
1136
|
+
</div>
|
|
1137
|
+
<div class="compat-row">
|
|
1138
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><strong>Divergence (DB-B12, honest doc):</strong> the onChild<em> callbacks do NOT receive the <code>previousChildName</code> second argument; <code>onValue</code>/<code>onChild</em></code> do NOT accept a <code>cancelCallback</code>; <code>onChildAdded</code>/<code>Changed</code>/<code>Removed</code>/<code>Moved</code> accept only plain refs (not <code>Query</code>); <code>child_moved</code> never fires (ordered-query move detection unmodeled). These listener-surface holes are out of scope for the current phase — consumers needing them use <code>firebase/database</code> directly.</span></span></div>
|
|
1139
|
+
</div>
|
|
1140
|
+
<div class="compat-row">
|
|
1141
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>onChildMoved</code> under an ordered query. Prod: fires when a child's <code>orderByChild</code>/<code>orderByValue</code> priority changes — emitted only on ordered queries. Sandbox: <strong>never fires on reorder</strong> — <code>onChildMoved</code> supports the plain-ref (no-fire) case only; the ordered-query overload is unimplemented</span></span></div>
|
|
1142
|
+
</div>
|
|
1143
|
+
<div class="compat-row">
|
|
1144
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>goOffline(db)</code> — accepted no-op: there is no network connection in the local sandbox to toggle, so nothing is disconnected (we deliberately do NOT simulate a disconnect — pending writes, listeners, and <code>get()</code> keep working)</span></span></div>
|
|
1145
|
+
</div>
|
|
1146
|
+
<div class="compat-row">
|
|
1147
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>goOnline(db)</code> — accepted no-op: there is no connection to reopen (see <code>goOffline</code>)</span></span></div>
|
|
1148
|
+
</div>
|
|
1149
|
+
<div class="compat-row">
|
|
1150
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>forceLongPolling()</code> — accepted no-op: transport selection is not applicable to the in-process/worker sandbox (it never opens a real socket). Accepted so init code that calls it compiles + runs</span></span></div>
|
|
1151
|
+
</div>
|
|
1152
|
+
<div class="compat-row">
|
|
1153
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>forceWebSockets()</code> — accepted no-op: transport selection is not applicable to the in-process/worker sandbox (see <code>forceLongPolling</code>)</span></span></div>
|
|
1154
|
+
</div>
|
|
1155
|
+
<div class="compat-row">
|
|
1156
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>enableLogging(logger?, persistent?)</code> — accepted no-op: the sandbox has no modular-SDK-style logger to wire a level/sink into (it uses host-level <code>console</code> logging directly, matching <code>pyric/firestore</code>'s <code>setLogLevel</code>). Accepted so init code that calls it compiles + runs</span></span></div>
|
|
1157
|
+
</div>
|
|
1158
|
+
<div class="compat-row">
|
|
1159
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>refFromURL(db, url)</code> — real alias: parses the path out of the absolute database URL and delegates to <code>ref(db, path)</code>, so the returned ref resolves + reads exactly like <code>ref(db, path)</code>. Divergence: the sandbox is single-database with no host/namespace, so the URL's HOST is NOT validated against the handle (the real SDK throws if the host doesn't match the db's namespace); only the path is honored</span></span></div>
|
|
1160
|
+
</div>
|
|
1161
|
+
</div>
|
|
1162
|
+
|
|
1163
|
+
### Unsupported
|
|
1164
|
+
|
|
1165
|
+
Tracked behavior that is not implemented in the current contract.
|
|
1166
|
+
|
|
1167
|
+
<div class="compat-list compat-list--plain">
|
|
1168
|
+
<div class="compat-row">
|
|
1169
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed REST host</code><span class="compat-sub">Historical <code>.json</code> REST transport contract for the removed production host.</span></span></div>
|
|
1170
|
+
</div>
|
|
1171
|
+
<div class="compat-row">
|
|
1172
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical admin read and set/get behavior for the removed production data handler.</span></span></div>
|
|
1173
|
+
</div>
|
|
1174
|
+
<div class="compat-row">
|
|
1175
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical user read return shape for the removed production data handler.</span></span></div>
|
|
1176
|
+
</div>
|
|
1177
|
+
<div class="compat-row">
|
|
1178
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical rules-denial normalization for the removed production data handler.</span></span></div>
|
|
1179
|
+
</div>
|
|
1180
|
+
<div class="compat-row">
|
|
1181
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical rules-denied read behavior for the removed production data handler.</span></span></div>
|
|
1182
|
+
</div>
|
|
1183
|
+
<div class="compat-row">
|
|
1184
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical set/get round trip for the removed production data handler.</span></span></div>
|
|
1185
|
+
</div>
|
|
1186
|
+
<div class="compat-row">
|
|
1187
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical set-null removal behavior for the removed production data handler.</span></span></div>
|
|
1188
|
+
</div>
|
|
1189
|
+
<div class="compat-row">
|
|
1190
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical rules-denied write behavior for the removed production data handler.</span></span></div>
|
|
1191
|
+
</div>
|
|
1192
|
+
<div class="compat-row">
|
|
1193
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical multi-path update behavior for the removed production data handler.</span></span></div>
|
|
1194
|
+
</div>
|
|
1195
|
+
<div class="compat-row">
|
|
1196
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical push key behavior for the removed production data handler.</span></span></div>
|
|
1197
|
+
</div>
|
|
1198
|
+
<div class="compat-row">
|
|
1199
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical push auto-ID format for the removed production data handler.</span></span></div>
|
|
1200
|
+
</div>
|
|
1201
|
+
<div class="compat-row">
|
|
1202
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical remove-versus-set-null behavior for the removed production data handler.</span></span></div>
|
|
1203
|
+
</div>
|
|
1204
|
+
<div class="compat-row">
|
|
1205
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed data handler</code><span class="compat-sub">Historical idempotent removal behavior for the removed production data handler.</span></span></div>
|
|
1206
|
+
</div>
|
|
1207
|
+
<div class="compat-row">
|
|
1208
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed rules fetch handler</code><span class="compat-sub">Historical deployed-rules JSON round trip for the removed production fetch handler.</span></span></div>
|
|
1209
|
+
</div>
|
|
1210
|
+
<div class="compat-row">
|
|
1211
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed rules deployment handler</code><span class="compat-sub">Historical rules deployment propagation timing for the removed production deploy handler.</span></span></div>
|
|
1212
|
+
</div>
|
|
1213
|
+
<div class="compat-row">
|
|
1214
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">Removed REST crawler</code><span class="compat-sub">Historical shallow REST response shape for the removed production crawler.</span></span></div>
|
|
1215
|
+
</div>
|
|
1216
|
+
<div class="compat-row">
|
|
1217
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">simulateRtdbRules(compiled, input)</code><span class="compat-sub">The removed stateful simulator returned a generate-before-simulate error when no IR had been generated</span></span></div>
|
|
1218
|
+
</div>
|
|
1219
|
+
<div class="compat-row">
|
|
1220
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">An in-module production target is intentionally absent; direct calls with a real <code>FirebaseApp</code> reject with package-resolution guidance</span></span></div>
|
|
1221
|
+
</div>
|
|
1222
|
+
<div class="compat-row">
|
|
1223
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Concurrent contention / retry-on-conflict — single-client sandbox doesn't model real concurrency; the documented "up to 25 retries" contract is degenerate (the fn is invoked once)</span></span></div>
|
|
1224
|
+
</div>
|
|
1225
|
+
<div class="compat-row">
|
|
1226
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>getDatabase(ctx)</code> returns a tagged sandbox-target handle (frozen identity)</span></span></div>
|
|
1227
|
+
</div>
|
|
1228
|
+
<div class="compat-row">
|
|
1229
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>getDatabase(sandbox)</code> returns a tagged sandbox-live handle (per-op identity)</span></span></div>
|
|
1230
|
+
</div>
|
|
1231
|
+
<div class="compat-row">
|
|
1232
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Two <code>getDatabase(sandbox)</code> calls share state (same underlying <code>LocalEnvironment</code>)</span></span></div>
|
|
1233
|
+
</div>
|
|
1234
|
+
<div class="compat-row">
|
|
1235
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Handle dispatch by <code>TARGET_SYMBOL</code> brand — refs route to their owning target via a <code>refToTarget</code> WeakMap (mirror of firestore's pattern)</span></span></div>
|
|
1236
|
+
</div>
|
|
1237
|
+
<div class="compat-row">
|
|
1238
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Unknown ref (not produced by this package) → <code>TypeError</code> in shim ops</span></span></div>
|
|
1239
|
+
</div>
|
|
1240
|
+
<div class="compat-row">
|
|
1241
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">No-op on sandbox-target handles (the sandbox IS the local emulator)</span></span></div>
|
|
1242
|
+
</div>
|
|
1243
|
+
<div class="compat-row">
|
|
1244
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">A production target is intentionally absent; production code continues to use <code>connectDatabaseEmulator</code> from the unchanged <code>firebase/database</code> package</span></span></div>
|
|
1245
|
+
</div>
|
|
1246
|
+
</div>
|
|
1247
|
+
|
|
1248
|
+
### Unverified
|
|
1249
|
+
|
|
1250
|
+
Tracked behavior whose available evidence does not yet establish the production result.
|
|
1251
|
+
|
|
1252
|
+
<div class="compat-list compat-list--plain">
|
|
1253
|
+
<div class="compat-row">
|
|
1254
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Inactive canonical <code>firebase/database</code> imports remain the upstream package; the mirror does not create tagged production targets</span></span></div>
|
|
1255
|
+
</div>
|
|
1256
|
+
<div class="compat-row">
|
|
1257
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>ref(db, path)</code> returns a tagged <code>DatabaseReference</code> carrying <code>key</code>, <code>parent</code>, <code>root</code>, <code>toString()</code></span></span></div>
|
|
1258
|
+
</div>
|
|
1259
|
+
<div class="compat-row">
|
|
1260
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>ref(db)</code> with no path returns the root ref (<code>key === null</code>, <code>parent === null</code>)</span></span></div>
|
|
1261
|
+
</div>
|
|
1262
|
+
<div class="compat-row">
|
|
1263
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>child(ref, 'a/b')</code> joins a relative path, including embedded slashes</span></span></div>
|
|
1264
|
+
</div>
|
|
1265
|
+
<div class="compat-row">
|
|
1266
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>ref.parent</code> is <code>null</code> at root, otherwise the parent ref</span></span></div>
|
|
1267
|
+
</div>
|
|
1268
|
+
<div class="compat-row">
|
|
1269
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior"><code>ref.key</code> is the final path segment, <code>null</code> for root</span></span></div>
|
|
1270
|
+
</div>
|
|
1271
|
+
<div class="compat-row">
|
|
1272
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Replaces the value at the path entirely; resolves to <code>undefined</code> (unlike <code>setDoc</code> which resolves to <code>void</code>, RTDB's <code>set</code> is documented as <code>Promise<void></code>)</span></span></div>
|
|
1273
|
+
</div>
|
|
1274
|
+
<div class="compat-row">
|
|
1275
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Update path validation — overlapping paths (e.g. <code>'/a'</code> and <code>'/a/x'</code> in the same call) throws synchronously before any write</span></span></div>
|
|
1276
|
+
</div>
|
|
1277
|
+
<div class="compat-row">
|
|
1278
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">The returned value from <code>onValue(ref, cb)</code> is the unsubscribe function (NOT an object); calling it removes the listener</span></span></div>
|
|
1279
|
+
</div>
|
|
1280
|
+
<div class="compat-row">
|
|
1281
|
+
<div class="compat-line"><span class="compat-main"><code class="compat-api">off(ref, eventType, callback)</code><span class="compat-sub">When the same callback is registered more than once, each <code>off(ref, eventType, callback)</code> removes one registration without orphaning the others</span></span></div>
|
|
1282
|
+
</div>
|
|
1283
|
+
<div class="compat-row">
|
|
1284
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Two concurrent <code>increment</code> calls interleave correctly (last-write-wins is NOT the contract — both deltas accumulate)</span></span></div>
|
|
1285
|
+
</div>
|
|
1286
|
+
<div class="compat-row">
|
|
1287
|
+
<div class="compat-line"><span class="compat-main"><span class="compat-behavior">Concurrent contention — if another client writes between the read and write, the update fn is retried with the new current value (typically up to 25 retries by default)</span></span></div>
|
|
1288
|
+
</div>
|
|
1289
|
+
</div>
|